当工具数量较多时,应按权限、任务阶段和语义相关性动态暴露少量 Schema,而不是把全部工具永久放入上下文。
工具很多时如何选择
如果系统有几百或几千个工具,不能无脑把全部 Schema 塞进上下文,否则会:
- 占用大量 Token;
- 增加延迟和成本;
- 让相似工具互相干扰;
- 降低工具选择和参数生成准确率;
- 破坏稳定的 Prompt Cache 前缀。
常见方案有四种。
静态小工具集
工具数量很少且长期稳定时,直接全部注册:
search_code、read_file、apply_patch、run_test、git_diff
Harness 每轮筛选工具
Harness 在调用主模型前,根据任务状态筛选:
定位阶段:search_code、list_files、read_file
修改阶段:read_file、apply_patch、git_diff
验证阶段:run_test、read_log、git_diff
筛选依据包括:
- 用户权限与租户;
- 当前任务阶段;
- 项目语言和运行环境;
- 工具风险和副作用;
- 上一步结果;
- 硬编码规则、关键词、Embedding 或路由模型。
这一步发生在主模型调用之前,主模型看不到未暴露的工具。
Tool Search 延迟加载
开始只暴露高层 Namespace、MCP Server 描述和 tool_search 能力,模型需要时再搜索并加载少量具体工具 Schema。
MCP 动态发现
Harness 作为 MCP Client,通过 tools/list 获取 name、description 和 inputSchema,转换为模型工具定义;模型返回 Tool Call 后,再通过 tools/call 调用真实 MCP Server。
MCP Tools 规范将工具定义为模型可发现和调用的能力;MCP TypeScript Client 指南展示了 listTools() → 交给模型 → callTool() → 回填结果的完整流程。
相关笔记
- 智能体工具调用原理 — Tool Call 的完整执行闭环
- Agent Skills — 工作流知识的渐进披露
- 模型上下文协议 MCP
- 工具与运行时 MOC
工具调用上的渐进式披露
工具渐进披露的是“可以执行什么”以及具体参数接口。
L0:Namespace 或 MCP Server 名称、简介
↓
L1:Tool Search 加载相关工具完整 Schema
↓
L2:模型生成 Tool Call
↓
L3:Harness 执行并回填结果
例如模型最初只看到:
{
"type": "namespace",
"name": "crm",
"description": "客户、订单、物流和退款管理"
}
需要查询物流时,再加载:
crm.get_order_status
crm.get_tracking_events
crm.get_shipping_eta
Skill 与 Tool 的区别:
| 维度 | Skill 渐进披露 | Tool 渐进披露 |
|---|---|---|
| 披露内容 | 工作流、规范和方法 | 可执行接口和参数 Schema |
| 第一层 | Skill 名称和描述 | Namespace/Server 名称和描述 |
| 第二层 | 完整 SKILL.md |
具体 Tool Definition |
| 第三层 | References/Scripts/Assets | Tool Call 与 Tool Result |
| 作用 | 告诉 Agent 应该怎么做 | 让 Agent 真的能够执行 |
Harness 每轮筛选与 Tool Search 的区别
不能简单理解为“一个完全在 Harness,一个完全在模型”。
| 机制 | 谁决定发起 | 谁检索候选工具 | 谁最终选择具体工具 |
|---|---|---|---|
| Harness 预筛选 | Harness | Harness 的规则、检索器或路由模型 | 主模型 |
| Hosted Tool Search | 主模型 | 模型服务平台 | 主模型 |
| Client-executed Tool Search | 主模型 | Harness/应用程序 | 主模型 |
Harness 预筛选
发生在主模型调用之前:
active_tools = route_before_model(
request=user_request,
state=task_state,
permissions=user_permissions
)
response = call_model(tools=active_tools)
其中 route_before_model() 可以使用传统代码、检索器或另一个小模型,但对主模型而言,未选工具不可见。
Hosted Tool Search
模型判断自己需要搜索工具;平台在请求中已声明的 Deferred Tools、Namespaces 或 MCP Servers 中检索,并直接把相关 Schema 注入上下文。
Client-executed Tool Search
模型产生 tool_search_call 和搜索目标;Harness 自己查询动态工具目录,然后返回 tool_search_output。
官方文档建议:候选工具在创建请求时已经确定,可优先使用 Hosted Tool Search;工具发现依赖项目、租户或应用自有状态时,使用 Client-executed Tool Search。OpenAI Docs:Tool search types
Tool Search 具体如何搜索
标准执行链
模型看到 Namespace/Tool Search
↓
模型判断缺少某类能力
↓
生成 tool_search_call 和搜索意图
↓
平台或 Harness 检索候选工具
↓
返回 tool_search_output 和完整 Schema
↓
模型从候选工具中生成真正的 function_call
例如用户说:
帮我查订单 42 什么时候能到。
模型可能生成:
{
"type": "tool_search_call",
"arguments": {
"goal": "查询订单的预计送达时间和物流进度"
}
}
搜索系统返回:
{
"type": "tool_search_output",
"tools": [
{
"type": "function",
"name": "get_shipping_eta",
"description": "查询指定订单的预计送达时间",
"parameters": {
"type": "object",
"properties": {
"order_id": {"type": "string"}
},
"required": ["order_id"]
}
}
]
}
模型随后调用:
{
"type": "function_call",
"name": "get_shipping_eta",
"arguments": {
"order_id": "42"
}
}
Hosted Search 的匹配算法是否公开
当前官方文档公开了 Hosted Tool Search 的输入输出和行为,但没有公开内部究竟使用 Embedding、BM25、LLM Reranker 还是其他混合算法。因此不能直接断言 Hosted Tool Search 一定使用向量数据库或余弦相似度。
可以确认的是:开发者声明 Deferred Tool、Namespace 或 MCP Server,模型决定发起搜索,平台返回相关工具子集。OpenAI Docs:Hosted Tool Search
Client-executed Search 的常见语义匹配
自己实现时,通常采用:
权限、租户和环境过滤
↓
关键词/BM25 召回
↓
Embedding 语义召回
↓
融合与业务规则加权
↓
Cross-Encoder 或 LLM 重排
↓
返回 Top-K 工具完整 Schema
工具检索文档不应只有工具名,可以拼接:
Namespace: logistics
Name: get_shipping_eta
Description: 查询订单预计发货和送达时间
Use when: 用户询问什么时候到、配送进度、ETA、预计到货时间
Do not use when: 取消订单、创建退款
Inputs: order_id
Outputs: shipping_status, estimated_delivery_date
Side effect: none
Tags: 物流, 配送, ETA, 到货, 发货
混合评分示例:
final_score =
0.55 × semantic_similarity
+ 0.25 × keyword_score
+ 0.10 × namespace_score
+ 0.10 × business_rule_score
这样即使用户说“东西啥时候到”,也能与 get_shipping_eta 的“预计送达时间”建立语义联系。
权限过滤必须在检索前执行,工具执行前还要再次鉴权:
权限/租户过滤 → 语义检索 → 返回候选 → 模型选择 → 执行前再次鉴权
工具描述应包含“做什么、何时使用、何时不使用、输入输出、是否有副作用和常见同义词”。Namespace 也应有清晰的业务描述。官方文档建议优先使用 Namespace 或 MCP Server 组织 Deferred Tools,并建议每个 Namespace 尽量少于 10 个函数以改善 Token 效率和模型表现。OpenAI Docs:Tool Search 与 Namespace