跳转至

工具搜索

Tool Search 是 OpenClaw 代理运行时的一项实验性功能。它为代理提供了一种简洁的方式来发现和调用大型工具目录。当一次运行中有许多可用工具、但模型很可能只需要其中少数几个时,此功能非常有用。

本文档介绍 OpenClaw Tool Search。它并不等同于 Codex 原生的 tool search 或 dynamic-tools 界面。Codex 原生的 code mode、tool search、deferred dynamic tools(延迟动态工具)和 nested tool calls(嵌套工具调用)是稳定的 Codex harness 界面,且不依赖于 tools.toolSearch。

对于暴露 JavaScript exec/wait 界面而非 Tool Search 控制的通用 OpenClaw 运行时,请参阅 Code Mode。

当 tools.toolSearch 未设置时,OpenClaw embedded(嵌入式)和 Copilot 运行会自动使用结构化的 Tool Search。这会延迟暴露工具 schema,同时保持经策略批准的能力可用。它不会启用 lean mode,也不会移除可选工具。设置 tools.toolSearch: false 可恢复直接 schema。已启用的 Code Mode 优先,而 Codex 保留其原生界面。这一自动默认行为不会改写配置文件。

为 OpenClaw 运行启用后,模型会自动收到一个有界目录,其中包含可用可信工具的名称和描述,以及结构化的 tool_search、tool_describe 和 tool_call 控制。设置 tools.toolSearch: true 或一个不含 mode 的对象即可选择此结构化界面。Direct-only 工具会与这些控制一起保持可见。

该目录会随活动模型的上下文窗口进行缩放。当空间紧张时,描述会先被缩短,然后才会省略工具名称;每个已获授权的目录条目仍然可搜索、可调用。对于 OpenClaw 自有工具的无效参数错误,会在可渲染时包含一个受限的预期输入签名,因此模型无需再次查询 schema 即可修正调用。如果某次调用将已获准入的技能(skill)名称误认为工具 ID,错误信息会指回该技能的完整说明,而不是让模型进入工具搜索。

延迟目录(deferred directory)会省略已直接暴露的工具。这些工具仍然可搜索,因此发现操作仍能返回它们的完整 schema,而不会重复原生指引。

目录可包含可纳入目录(catalog-eligible)的 OpenClaw 工具、插件工具、MCP 工具和客户端提供的工具。该目录让模型大致了解它可发现哪些受信任的能力,而不必预先暴露所有已入目录的 schema。它还会说明,经策略批准的 MCP 和客户端工具也可能是可发现的。这些工具不受信任的名称和描述不会被复制到系统提示词中。取而代之的是,模型会搜索紧凑的描述符,在需要确切 schema 时描述某个选中的工具,并通过 OpenClaw 调用该工具。Direct-only 工具对模型保持可见,且不会被加入目录。

Codex harness 运行不会收到这些实验性的 OpenClaw Tool Search 控制。OpenClaw 将产品能力以动态工具(dynamic tools)的形式传递给 Codex,而 Codex 拥有稳定的原生 code mode、原生 tool search、deferred dynamic tools 和 nested tool calls。

回合如何运行

在规划阶段,OpenClaw 嵌入式运行器会为本次运行构建有效目录:

  1. 解析代理、配置(profile)、沙箱和会话的当前工具策略。
  2. 列出符合条件的 OpenClaw 和插件工具。
  3. 通过会话 MCP 运行时列出符合条件的 MCP 工具。
  4. 添加为当前运行提供的符合条件的客户端工具。
  5. 保持核心编码原语(coding primitives)和 direct-only 工具对模型可见,并为其余可纳入目录的工具建立紧凑描述符索引。
  6. 将确定性、有界、经策略过滤的能力目录添加到缓存稳定的系统提示词前缀中。
  7. 将结构化的搜索、描述和调用工具,或紧凑的目录界面,与那些稳定、可直接调用的工具一起暴露。

在执行时,每个真实的工具调用都会返回到 OpenClaw,常规的策略、审批、钩子(hook)、日志记录和结果处理仍然适用。

模式

tools.toolSearch 有两个面向模型的模式:

  • tools:当 tools.toolSearch 未设置、为 true 或不含 mode 的对象时的默认模式。将 tool_search、tool_describe 和 tool_call 作为普通结构化工具暴露,并与能力目录和 direct-only 工具一起呈现。
  • directory:暴露 tool_search、tool_describe 和 tool_call,外加一个有界、缓存稳定的提示词目录。核心编码原语、direct-only 工具以及运行交付策略所要求的工具保持可见;其他 schema 保持延迟状态。

所有模式都使用相同的策略过滤目录和常规 OpenClaw 执行路径。标记为 catalogMode: "direct-only" 的工具位于该目录之外,并保持对模型可见。在 directory 模式下,客户端提供的工具在当前运行中保持直接可见,而 OpenClaw 工具、插件工具和 MCP 工具则可以被压缩收纳到目录(catalog)之后。在嵌入式 harness 中,对某个确切隐藏目录名称的直接调用会在执行前从同一授权目录水合(hydrate)出完整定义。而 Copilot harness 则将 directory 映射为结构化的 tools 语义:隐藏的 OpenClaw 目录名称必须通过 tool_call 调用,因为它们不是已注册的 SDK 处理器。

结构化 tools 界面默认对 OpenClaw 运行开启。目标工具保留各自的超时和审批行为。Codex harness 运行使用其原生界面。

压缩并不总是更便宜:小型目录可能增加 schema 开销,额外的发现回合也可能抵消最初的有效载荷节省。当直接 schema 更适合你的工作负载时,请设置 tools.toolSearch: false。

没有单独的来源选择配置。启用 Tool Search 后,目录在常规策略过滤后会包含可纳入目录的 OpenClaw、MCP 和客户端工具;direct-only 工具则单独保留。

为什么需要此功能

大型目录很有用,但代价高昂。将每个工具 schema 都发送给模型会使请求变大、拖慢规划速度,并增加误选工具的概率。

Tool Search 改变形态:

  • 直接工具:模型在第一个 token 之前看到每个选定的 schema
  • Tool Search 工具模式:模型看到三个紧凑的结构化工具、相同的能力目录,以及任何仅直接工具
  • Tool Search 目录模式:模型看到一个有界目录,外加 search/describe/call 控件、策略要求的直接工具,以及任何仅直接工具
  • 在轮次期间:模型可以按需加载其余 schema

当单次运行可能看到许多工具时,Tool Search 非常有用,尤其是来自 MCP 服务器或客户端提供的应用工具。结构化搜索是默认方式,但实际的请求大小和延迟取决于工具目录以及模型的调用。

能力目录按工具名称排序,限制为 18,000 个字符,并基于已经过策略过滤的工具目录构建。对于未更改的工具目录快照,OpenClaw 会复用渲染后的能力目录,并将其放在 system prompt 缓存边界之上。用户消息、每轮工具猜测、会话标识符以及不受信任的 MCP 或客户端元数据不会进入目录。这使得重复轮次可以复用 prompt KV 缓存。当授权工具目录发生变化时,OpenClaw 会为新快照构建新的能力目录。prompt 钩子 toolsAllow 限制在最终 prompt 提交之前生效:嵌入式 prompt 和 Copilot prompt 仅展示剩余的工具目录,而不会重新运行钩子或重写早期对话轮次。

结构化控件

tool_search 搜索当前运行的有效工具目录。它接受一个查询和一个可选的限制。

查询必须用英语书写。排序基于词法匹配(对工具名称、描述以及第一方参数名称和描述应用 Okapi BM25),并带轻量级英语词干还原,因此 scheduling 可以匹配到描述为 Schedule a recurring task 的工具;另有小型意图扩展,使 look up the price 可以匹配到描述为 Search the web 的工具。工具名称和描述均使用英语编写,因此其他语言的查询通常匹配不到任何内容。这种查询不会被拒绝——工具目录可能合理地用其他文字描述工具——但一个没有可用词的查询返回的是零个排序结果,而不是工具目录中的任意切片。即使精确的工具名称分词结果为空,它也仍然有效。tool_search 在其面向模型的描述中说明了这一要求。

不受信任的参数 schema 永远不会被索引。MCP 和客户端工具仅按名称和描述进行匹配,这与将它们的输入签名延迟为 input: "unknown" 的边界相同。

结果紧凑且可以安全地放回 prompt 上下文中。每个命中项都包含一个有界的 TypeScript 风格 input 签名,例如 { id: string; mode?: "drip" | "flood" },因此当该签名足够时,模型可以跳过 tool_describe。受信任的 OpenClaw 核心或插件工具也可以包含一个紧凑的 output 提示,例如 Array<{ id: string; paid: boolean }>。MCP 和客户端的输出 schema 声明不会被提升到这个受信任提示中。它们不受信任的输入 schema 也同样以 input: "unknown" 的形式被延迟;在调用它们之前,请使用 tool_describe。开放的、过大的或部分不完整的输出 schema 会省略该提示,并仍可通过 tool_describe 获取。

{ "query": "calendar event", "limit": 5 }

描述

tool_describe 接受搜索结果的 id,并加载其完整元数据,包括精确的输入 schema,以及在工具声明时受信任的完整 outputSchema。

{ "id": "mcp:calendar:create_event" }

调用

tool_call 接受工具 id 及其目标 args,通过 OpenClaw 调用所选工具,并返回 { tool, result } 信封。返回 JSON 的工具通常会将其值放在 result.details 中。OpenClaw 会在执行前验证受信任的核心或插件工具所声明的输入 schema。缺失的必需参数、不正确的类型和被禁止的属性会返回可操作的工具错误,而不是执行该工具;拼写错误的属性在可用时会包含一个建议的参数。如果受信任的工具还声明了 outputSchema,OpenClaw 会在执行前编译该 schema,并在正常工具钩子之后、返回目录调用的结果之前验证最终的 details。MCP 和客户端拥有的 schema 仍保持延迟,交由它们各自的执行边界处理。

如果 tool_call 命名了为当前轮次声明的仅直接工具,它会返回一条指导:按该工具声明的名称和参数直接调用它。它不会通过工具目录分派仅直接工具,也不会建议搜索它们。当前轮次中不可用的工具仍会收到普通的工具目录未命中错误。

tool_call 还会修复来自本地模型的扁平化目标参数。它保留诸如 id 和 name 之类的目标字段,并拒绝有歧义的工具选择器,而不是调用错误的工具。当某个目标字段与另一个已编入工具目录的工具匹配时,请将目标参数嵌套在 args 之下。

该结构化控件面向模型的文本只包含工具的 id、name 和 source,以及不变的目标 result;它不会重复描述和输入签名。其结构化 details 为运行时消费者保留完整的调用信封。如需完整的工具元数据,请使用 tool_describe。

{
  "id": "mcp:calendar:create_event",
  "args": {
    "summary": "Planning",
    "start": "2026-05-09T14:00:00Z"
  }
}

工具作者在工具的 outputSchema 属性上声明输出契约。它描述的是 AgentToolResult.details,而不是渲染的内容块。请包含所有不会抛错的变体;如果结果不稳定,则省略它。请参阅 Code Mode 输出契约 和 工具插件。

延迟的名称是工具目录条目,并非此模式中可直接调用的函数。请将结果 ID 或名称放在 tool_call.id 中,并将所有目标参数放在 tool_call.args 中,即使其他指令按名称引用延迟工具时也是如此。紧凑的搜索签名可能足以调用它;当需要完整 schema 时,请使用 tool_describe。

tool_search 接受单查询形式或一组独立查询:

{
  "query": "today's calendar events",
  "limit": 3
}
{
  "queries": [
    { "query": "today's calendar events", "limit": 3 },
    { "query": "Slack messages needing attention", "limit": 3 }
  ]
}

单查询调用仍会直接返回紧凑候选数组。当两种形式都包含搜索时,非空的 query 会先执行,顶层 limit 仅作用于它。批量条目按请求顺序跟随,包括重复的查询文本;每次出现都保留自己的 limit,并计入批量预算。

当存在非空批量时,省略、null、空或仅包含空白字符的 query 会被忽略。在这种情况下,省略顶层 limit 或将其设置为 null;非 null 的顶层 limit 会被拒绝,而不是应用到批量。省略或 null 的 queries 保持标量行为,并且 queries: [] 在 query 非空时也会回退到标量形式。没有批量时的空白标量查询仍返回空候选数组。没有批量时缺失或 null 的标量,或没有非空标量的空批量,会被拒绝。标量 limit: null 使用默认限制,与省略 limit 相同。无效的查询形式、无效的限制以及超出预算的批量仍会失败。

批量调用按请求顺序返回 { results: [{ query, candidates }] }。每个查询使用与普通搜索相同的有效目录、排序、过滤和每查询限制;候选项可能出现在多个结果组中。描述在输出前会被压缩。如果完整批量将超过 4,000 字符的响应预算,排名较低的候选项会被移除,并且响应包含 truncated: true。丢失候选项的结果组也会包含 truncated: true,因此空的截断组不会被误认为没有匹配的查询。省略的每查询限制使用 searchDefaultLimit。一个批量中的有效限制最多可请求总计 50 个候选项。一个批量最多接受 16 个查询,每个查询最多 512 个字符,序列化查询列表总计最多 512 个 UTF-8 字节。无效批量作为单个请求失败,而没有匹配的合法查询返回空 candidates 数组。

目录模式

目录模式公开:

  • tool_search
  • tool_describe
  • tool_call

它还会让核心文件和 shell 原语、客户端提供的工具、仅限直接调用的工具以及策略要求的交付工具保持直接可见。其他已授权的工具模式保持延迟处理,而不是随每个用户提示变化。MCP 工具不能冒充直接可见的核心工具或策略要求的交付工具。如果有限目录省略了条目,请使用 tool_search 查找它们,并使用 tool_describe 获取其完整模式。如果模型直接请求一个确切的隐藏目录工具名称,嵌入式 harness 会在正常执行前从已授权目录中解析它。Copilot 则改用 tool_call,如 模式 中所述。目录模式中的客户端工具名称不得与 OpenClaw、插件或 MCP 工具名称冲突,因为精确延迟调度使用这些名称。

执行策略

普通 OpenClaw 行为仍然适用于最终调用:

  • 工具允许和拒绝策略
  • 每个代理和每个沙箱的工具限制
  • 通道/运行时工具策略
  • 审批钩子
  • 插件 before_tool_call 钩子
  • 工具 executionMode:顺序调用与同一目录中的其他调用互斥运行,包括来自其他 Tool Search 或 Code Mode 单元格的调用
  • 会话身份、日志和遥测

配置

当 tools.toolSearch 未设置时,OpenClaw 执行使用结构化 tools 模式,默认搜索限制为 8,最大为 20。本地 Ollama 模型、LM Studio 和托管本地服务保留其较小的限制 5 和 10。已知的托管 Ollama 路由使用通用限制。由 Ollama 守护进程提供的未标记别名会继承该守护进程的限制,即使该别名转发到托管模型。其他提供商不会仅凭模型名称或回环 URL 被归类为本地。

显式的 tools.toolSearch 值优先,包括 false。设置 agents.defaults.experimental.localModelLean: false 会恢复可选工具,但不会关闭自动 Tool Search。

显式启用结构化 Tool Search:

openclaw config set tools.toolSearch true

等效 JSON:

{
  tools: {
    toolSearch: true,
  },
}

显式固定结构化默认值:

{
  tools: {
    toolSearch: {
      mode: "tools",
    },
  },
}

对于 OpenClaw 执行,请改用紧凑目录界面:

{
  tools: {
    toolSearch: {
      mode: "directory",
    },
  },
}

调整搜索结果限制(所示值为默认值):

{
  tools: {
    toolSearch: {
      mode: "tools",
      searchDefaultLimit: 8,
      maxSearchLimit: 20,
    },
  },
}

运行时会将 maxSearchLimit 限制在 1-50,将 searchDefaultLimit 限制在 1..maxSearchLimit。

禁用它:

{
  tools: {
    toolSearch: false,
  },
}

升级

Tool Search 代码模式(tool_search_code)已弃用。运行 openclaw doctor --fix 将 tools.toolSearch.mode: "code" 迁移为 "tools",并移除 codeTimeoutMs。该迁移会保留 Tool Search 是否启用。openclaw update 通常会自动为你运行;延迟 Doctor 配置修复的更新(例如旧版 Git 更新器)之后需要 openclaw doctor --fix。在未迁移配置上启动的网关会退出,并指明已弃用的键和该命令。toolSearch: true 以及没有 mode 的对象现在会选择结构化搜索。使用 Code Mode 及其 exec/wait 界面进行 JavaScript 编排。

会话活动

搜索、描述和调用结果会携带该操作的目录数据。OpenClaw 不会记录序列化的工具或 prompt 字节数。E2E 场景 会单独测量提供商负载字节数,与 mock 提供商通道分开。

无论模式如何,已完成的目标调用都会作为受限、脱敏的显示活动持久化在会话历史中,而不会添加用于回放的合成模型轮次。 搜索、描述和调用结果均携带每个工具的 id 和 source。 因此,会话日志仍然能够回答:

  • 模型预先看到了多少个工具 schema
  • 它执行了多少次搜索和描述操作
  • 最终调用了哪个工具
  • 结果来自 OpenClaw、MCP 还是客户端工具

E2E 验证

QA Lab 网关场景使用 OpenClaw 运行时比较直接模式和结构化模式的 Tool Search:

pnpm openclaw qa suite --provider-mode mock-openai --scenario tool-search-gateway-e2e

它会创建一个带有大型工具目录的临时假插件,启动 mock OpenAI 提供商,然后以直接模式和结构化 Tool Search 模式运行 Gateway。它会比较提供商请求负载,然后验证两条链路中的会话日志和工具流程。

该回归测试证明:

  1. 直接模式可以调用假插件工具。
  2. Tool Search 可以调用同一个假插件工具。
  3. 直接模式会直接向提供商暴露假插件工具 schema。
  4. Tool Search 会暴露紧凑的结构化控件以及任何仅直接模式可用的工具。
  5. 对于大型假目录,Tool Search 请求负载更小。
  6. 会话日志显示预期的工具调用次数。
  7. 结构化模式在选中的插件工具通过 tool_call 运行之前,使用一次 tool_search 调用解析两个查询。

真实模型对比

pnpm test:live -- src/agents/tool-search.live.test.ts

此可选探针使用已配置的 OpenAI 凭据;如果没有这些凭据,则跳过。 它通过 OpenClaw runner 使用小型和大型合成目录,比较直接暴露、未设置时的默认值以及两种显式 Tool Search 模式。在目标工具内部创建的验证代码可证明实际执行。该探针检查策略拒绝的工具和仅直接模式可用的工具、延迟 schema 以及对话记录传递,而不强制模型选择工具。它报告请求字节数、发现和调用次数、schema 恢复以及耗时。小型目录通过测量来评估,而不是假设其能从压缩中受益。成功的探针并不是跨提供商可靠性基准。

失败行为

Tool Search 应当失败关闭:

  • 如果工具不在有效策略中,搜索不应返回它
  • 如果选中的工具变得不可用,tool_call 应失败
  • 如果策略或审批阻止执行,调用结果应报告该阻止,而不是绕过它

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw