在 Responses API 中,Tool Search 需要同时加入 {"type":"tool_search"},并给希望延迟的函数或 MCP 设置 defer_loading:true。候选工具已知时先用 Hosted;工具取决于租户、项目或权限时才用 Client-executed。官方当前说明只有 gpt-5.4 及之后模型支持 Tool Search。
Tool Search 解决什么问题?
Function Calling、MCP 与内置工具让模型能够执行操作,但工具越多,完整名称、说明和参数 Schema 就越占上下文。Tool Search 把“哪些工具可用”与“现在加载哪些工具”拆开:模型先看到可搜索表面的概要,需要时再把匹配定义注入上下文。
| 场景 | 建议 | 原因 |
|---|---|---|
| 只有 3–5 个稳定函数 | 直接 Function Calling | 目录很小,额外搜索回合未必值得 |
| 几十个函数,按业务域分组 | Tool Search + namespace | 首轮只展示分组概要,按需加载内部 Schema |
| 一个 MCP 服务器暴露大量工具 | Tool Search + 延迟 MCP | 保留 server 名称与说明,晚些加载工具定义 |
| 工具随租户、角色或项目变化 | Client-executed | 应用在搜索时执行真实权限过滤 |
| 需要运行 Python 计算 | Code Interpreter | 这是执行环境,不是工具目录 |
最小 Hosted 示例
官方文档要求同时声明 tool_search 和延迟工具。下面用 namespace 把 CRM 工具分组;模型先看到 namespace 概要,搜索命中后才加载内部函数 Schema。
import OpenAI from "openai";
const client = new OpenAI();
const response = await client.responses.create({
model: "gpt-6-astra",
input: "查询 customer_42 的未完成订单。",
tools: [
{
type: "namespace",
name: "crm",
description: "客户资料与订单管理工具。",
tools: [{
type: "function",
name: "list_open_orders",
description: "按客户 ID 查询未完成订单。",
defer_loading: true,
strict: true,
parameters: {
type: "object",
properties: { customer_id: { type: "string" } },
required: ["customer_id"],
additionalProperties: false
}
}]
},
{ type: "tool_search" }
]
});
console.log(response.output);响应里会出现 tool_search_call 与 tool_search_output;Hosted 模式的 execution 为 server、call_id 为 null。被加载函数随后像普通函数一样产生 function_call,你的服务仍要执行并回传结果。
为什么优先使用命名空间?
单个延迟函数在请求开始时仍会暴露函数名称和描述,主要延迟参数 Schema。命名空间或 MCP 只展示高层名称与说明,内部工具直到搜索命中后才加载,因此通常节省更多输入 Token。
- 按意图分组,例如
crm、billing、support,不要建一个“everything”。 - 命名空间描述要短且可区分;细节放在延迟函数中。
- 官方最佳实践建议每个命名空间少于 10 个函数,以改善 Token 效率和模型表现。
- 同一命名空间可混合立即可调用与延迟函数;只给需要延迟的函数设置标记。
Hosted 与 Client-executed 怎么选?
| 维度 | Hosted | Client-executed |
|---|---|---|
| 工具目录 | 发请求时已声明 | 搜索时由应用查询 |
| 执行位置 | OpenAI 服务端搜索 | 你的注册表或权限服务 |
| 响应流程 | 同一响应返回加载子集 | 先收 tool_search_call,再回 tool_search_output |
| 典型场景 | 固定函数、namespace、MCP 清单 | 多租户、项目插件、动态授权 |
| 复杂度 | 低,优先起步 | 高,需目录、权限和 Schema 校验 |
Client-executed 两步闭环
第一步把 execution:"client"、搜索说明和参数 Schema 放进工具定义;模型返回 tool_search_call 后停止。应用按参数查询可信工具注册表,第二步用相同 call_id 回传 tool_search_output。
const search = await client.responses.create({
model: "gpt-6-astra",
input: "找到当前项目可用的物流工具。",
parallel_tool_calls: false,
tools: [{
type: "tool_search",
execution: "client",
description: "查找当前项目已授权的工具。",
parameters: {
type: "object",
properties: { goal: { type: "string" } },
required: ["goal"],
additionalProperties: false
}
}]
});
// 从 search.output 读取 tool_search_call;
// 查询可信注册表后,使用相同 call_id 回传 tool_search_output。Hosted 模式只声明当前用户允许搜索的工具;Client 模式按租户、角色和资源范围过滤。真正调用时再次校验身份、参数、审批与幂等,写操作、付款、删除和外发消息不要只依赖模型判断。
Token、缓存、延迟和费用
Tool Search 的价值主要来自减少预加载工具定义。官方说明,新发现工具会放在上下文末尾,Hosted 和 Client-executed 都如此,以尽量保留 Prompt Cache。它不等于“免费”或“必然更快”:模型 Token、实际工具费用、MCP 第三方费用和你的目录服务成本仍存在。
- 记录完整工具目录 Token 与启用 Tool Search 后的
input_tokens。 - 观察
cached_tokens、搜索次数、加载工具数和端到端延迟。 - 按“成功任务”比较成本,不只看单次请求 Token。
- 不要无故改变已加载工具集;官方指出改变集合会从该点破坏缓存。
- 长描述和错误分组会导致二次搜索或加载过多工具。
与 Remote MCP、Function Calling 的边界
Function Calling 定义具体业务工具;Remote MCP 连接远程服务器;Tool Search 是二者之上的按需发现与加载层。它不负责真正执行函数、保存 OAuth、保证工具可信,也不替代 MCP 审批。
| 输出 | 含义 | 应用动作 |
|---|---|---|
| tool_search_call | 模型请求发现工具 | Hosted 等服务端;Client 查询并校验目录 |
| tool_search_output | 已加载工具集合 | 记录集合、版本和授权上下文 |
| function_call | 模型请求执行函数 | 重新鉴权、校验参数、执行并回传 |
| mcp_list_tools / mcp_call | MCP 发现或调用 | 遵守 allowed_tools、审批和 OAuth 边界 |
常见错误与排查顺序
- 模型不支持:确认 Responses API 使用
gpt-5.4或之后的支持模型。 - 没有搜索:检查是否加入
tool_search,以及函数/MCP 是否设置defer_loading:true。 - namespace 无效:延迟标记应在内部函数,而不是 namespace 对象。
- Client 第二回合失败:确认
execution:"client"、原call_id、状态和 Schema。 - 加载太多:缩小 namespace、改写描述,并按租户与权限过滤。
- 成本增加:检查重复搜索、过宽分组和频繁改变工具集合。
- 越权风险:目录查询和工具执行两处分别授权,不信任未知 Schema。
上线前检查清单
- 用真实支持模型跑通搜索→加载→函数/MCP 调用→结果回传。
- 验证未授权工具不出现在 Hosted 声明或 Client 返回集合。
- 固定 namespace 名称、描述与 Schema 版本,记录变更。
- 记录搜索次数、加载工具数、Token、缓存、延迟、拒绝与失败。
- 为工具执行保留参数校验、超时、幂等、审批和审计日志。
常见问题
OpenAI Tool Search 和 Function Calling 有什么区别?
Tool Search 负责按需发现并加载工具定义;工具加载后,模型仍通过普通 function_call 或 MCP 调用执行。它不是业务函数的替代品,而是工具目录的加载层。
哪些模型支持 Tool Search?
截至 2026-11-01,OpenAI 官方 Tool Search 指南说明,Responses API 仅 gpt-5.4 及之后模型支持 tool_search。接入前还应在模型页和实际项目中确认可用性,旧模型不能因为加入 tool_search 配置就自动获得支持。
defer_loading 应该放在哪里?
单个函数可在函数定义上设置 defer_loading:true;MCP 则在 MCP server 工具定义上设置。命名空间场景要把 defer_loading 放在命名空间内部的函数上,而不是 namespace 对象本身。
为什么官方更推荐命名空间或 MCP?
请求开始时,命名空间或 MCP 只向模型展示名称和高层描述,内部函数 Schema 在被搜索到后才加载;单个延迟函数仍会暴露函数名称和描述,主要只延迟参数 Schema。因此分组通常能获得更明显的 Token 节省。
Hosted 与 Client-executed Tool Search 怎么选?
候选工具在发请求时已经确定,优先 Hosted,由 OpenAI 在同一响应中返回加载结果;工具目录取决于租户、项目、权限或内部注册表时,使用 Client-executed,由应用处理 tool_search_call,并用相同 call_id 回传 tool_search_output。
Tool Search 一定会降低费用和延迟吗?
不保证。它可能减少预先载入的工具定义 Token,并把新加载工具放到上下文末尾以保留缓存,但搜索回合、错误分组、过宽命名空间或频繁改变已加载工具集都可能增加延迟或破坏缓存。应比较 input_tokens、cached_tokens、搜索次数、端到端延迟和成功任务成本。
怎样防止 Tool Search 加载越权工具?
工具发现不能替代授权。Hosted 模式只声明当前用户允许搜索的工具;Client 模式按租户、角色和资源范围过滤返回 Schema,并验证工具定义来自可信注册表。真正执行工具时仍要重新校验身份、参数、幂等和审批,不能把模型的搜索结果当成权限。
官方资料
本文核对日期为 2026-11-01。模型支持、Tool Search 参数、Schema、缓存与费用可能调整;生产上线前请重新读取 Tool Search、Tools、MCP 与 Deployment checklist 官方文档。