工具太多会拖垮 Agent:Claude Agent SDK 的 tool search 解决的是什么问题
先把问题问具体一点:你在一个项目里挂了几个 MCP server,每个 server 又暴露十几二十个工具。会话刚开始、你一个字还没输入的时候,这些工具的定义在不在上下文窗口里?
这个问题的答案会直接决定你后面每一轮对话还剩多少空间可用。Claude Code 官方文档里管这套机制叫 tool search,下面按文档描述的路径走一遍。
它撤掉的到底是什么
官方文档《Scale to many tools with tool search》(code.claude.com/docs/en/agent-sdk/tool-search)写明:tool search 生效时,工具定义会被从上下文窗口里扣下来(withheld),模型收到的是一份可用工具的摘要;当任务需要某个还没加载的能力时,模型去检索工具目录,把相关的工具加载进来。
MCP 那一页(code.claude.com/docs/en/mcp,「Scale with MCP tool search」一节)把会话启动时到底留下了什么说得更细:会话开始时只加载工具名和 server instructions。所以「摘要」不是一个模糊说法,它对应的是名字这一层,而不是完整的参数 schema。
这也解释了同一页里的另一句提醒:如果你在写 MCP server,tool search 打开之后 server instructions 这个字段的作用会变大——它是模型判断「要不要往这个方向搜一下」的依据之一。文档把它类比成 skills 的工作方式。
为什么要撤?文档自述了两条理由:一是上下文效率,工具定义会占掉窗口里相当可观的一块,留给实际工作的空间就少了;二是选择准确率,同时加载的工具超过一定量级之后,模型挑工具的准确率会下降。文档在这两处都给了具体数值,我不往正文里抄——这类数字改起来没有任何成本,你要引用就去那一页看当时的原文。
默认是开的,但有一串例外
文档的措辞是 tool search on by default。真正需要记住的是「除了哪些情况」,因为这几条例外正好覆盖了不少人的实际部署形态:
- 模型不在支持范围内:文档写明它要求模型支持
tool_reference块,并给出了最低世代与一个 model compatibility 页的链接。对不支持的模型,SDK 直接一次性加载全部工具定义,ENABLE_TOOL_SEARCH设什么都不管用。具体支持哪些型号随时会变,以官方兼容页为准。 - Google Cloud 的 Agent Platform 上按模型世代分叉:Claude 4.5 世代及以后默认开启;早于该世代的模型,SDK 一次性加载,理由是文档写的——它们的 serving stack 会拒绝所需的 beta header,
ENABLE_TOOL_SEARCH同样覆盖不了。文档还补了一条历史:在 Claude Codev2.1.221之前,Agent Platform 上的所有模型都会被禁用 tool search,除非你显式设了ENABLE_TOOL_SEARCH。 ANTHROPIC_BASE_URL指向非第一方主机:SDK 默认关掉 tool search,文档给的原因是大多数代理不转发tool_reference块。这一条是可以用ENABLE_TOOL_SEARCH覆盖的,但文档紧接着提醒:强开之后 beta header 会被发过代理,不支持tool_reference块的代理会直接让请求失败。- Microsoft Foundry 托管在 Azure 上的部署:文档明说 not supported,服务端会拒绝,SDK 检测到拒绝后改为一次性加载。因为拒绝来自部署本身,
ENABLE_TOOL_SEARCH覆盖不了。 - 设了
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:tool search 保持关闭,你自己设ENABLE_TOOL_SEARCH也覆盖不了。文档写明组织可以通过 managed settings 让它保持开启,这条需要 Claude Codev2.1.227或更高版本。
这里补一句我们能核到的边界:文档没有把 tool search 标成 beta 功能,但它确实落在 CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS 这个开关的管辖范围内,文档在这一处还挂了一条指向「Disable pre-release capabilities」那一页的链接,说明这个开关在哪些场合生效、会剥掉什么。这两处白纸黑字放在一起就到此为止——它到底算不算「预发布能力」,文档没有明说,我们也不替它下定义,真要判断就去那一页看。
ENABLE_TOOL_SEARCH 的取值改变的是什么
agent-sdk/tool-search 和 mcp 两页各给了一张表,取值一共五种。挑对本篇有用的三行说:
| 取值 | 这一行改变了什么 |
|---|---|
auto | 阈值模式。把「可以延迟的那些工具定义」的 token 数加起来,和模型上下文窗口做比较,没到阈值就全部一次性加载,到了阈值就全部延迟 |
auto:N | 同上,阈值百分比换成你给的 N(文档写明取值范围是 0-100)。数值越低越早激活 |
false | 关闭。每一轮都把全部工具定义加载进上下文 |
auto 的默认阈值是上下文窗口的 10%——这是文档写明的默认值,随版本可能变动,别当成契约。
auto 这行有个细节值得单独拎出来:文档写明,被计入这个阈值的是「tool search 能延迟的每一份定义」,包括来自任意 server 的、没有被标成 alwaysLoad 的 MCP 工具,加上那些按需加载的内置工具;而 Bash、Read、Edit 这类核心内置工具,SDK 始终一次性加载,也不计入阈值。
所以「关掉 tool search 上下文会涨多少」这个问题,答案不是「涨掉全部工具」,而是「涨掉可延迟的那一部分」。这两个量的差别在挂了很多 server 的项目上会很明显。
反过来,如果某个 server 的工具是你每一轮都要用的,文档给的做法是在该 server 配置里设 alwaysLoad: true,它的工具就会在会话开始时全部进上下文,不受 ENABLE_TOOL_SEARCH 影响:
{
"mcpServers": {
"core-tools": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"alwaysLoad": true
}
}
}
文档写明 alwaysLoad 在所有 server 类型上都可用;MCP server 也可以在单个工具的 _meta 里加 "anthropic/alwaysLoad": true,效果一样但只作用于那一个工具。同一页还提醒:设了 alwaysLoad: true 会让启动等待该 server 的工具就绪(有连接超时上限,数值以官方文档为准),因为构建第一次 prompt 时它们必须在场。
被搜出来的工具会待多久
这是本篇最该记住的一条。文档写明:一次检索默认最多加载最相关的五个工具(这是文档写明的默认值,随版本可能变动),加载之后它们留在上下文里,后续轮次可以直接用——不是用完就丢。
但还有下一句:如果对话长到 SDK 需要压缩早先的消息来腾空间,之前发现的工具可能会被移除,模型在需要时会重新检索。
也就是说,一个长会话里同一个工具被搜出来两次,按文档的描述属于预期行为,不是配置坏了。如果你在做可观测性、盯着调用序列排查,看到检索步骤在压缩之后又出现一遍,对照的就是文档这一句,不必往「配置漂了」的方向查。
代价文档也写了:第一次发现某个工具会多一次往返(就是那个检索步骤)。工具集大的时候,这一次往返被「每一轮都更小的上下文」摊掉了;而在工具很少、定义本来就塞得进上下文的情况下,文档的说法是一次性全部加载通常更快。注意这个「通常」是文档的措辞,不是性能承诺,我们也没有做过任何实测。
怎么判断当前这个会话是哪种模式
code.claude.com/docs/en/tools-reference 那张内置工具表里有两行可以当锚点:
ToolSearch:检索并加载被延迟的工具,表里标注的 Permission required 是 NoWaitForMcpServers:等待还在后台连接的MCPserver,表里明确写着它只在 tool search 被禁用时出现,因为开启时这个等待发生在ToolSearch调用内部
后面这条很实用:你看到会话里出现的是哪一个工具,就知道当前落在哪一边了。MCP 那一页还写了一处相关行为——server 连接失败时,Claude Code 会把是哪个 server 失败、错误是什么告诉模型,包括在没搜到匹配工具的 ToolSearch 结果里;而这需要 tool search 开启,在没有 tool search 的配置下不会上报。
另外,ToolSearch 不在 tools-reference 那张「规则格式」表里,按同页那句「表里没列的工具只接受裸工具名、不带 specifier」,它就该按裸名写。mcp 页给的禁用示例正好对得上:
{
"permissions": {
"deny": ["ToolSearch"]
}
}
让检索命中得准一点
文档在《Optimize tool discovery》一节写明:检索是拿查询去匹配工具的名称和描述。名字起成 search_slack_messages 这种,比 query_slack 能覆盖更宽的请求;描述里带具体关键词(「Search Slack messages by keyword, channel, or date range」)比笼统的一句「Query Slack」匹配到的查询更多。
另一个办法是在 system prompt 里补一段工具类目说明,让模型知道有哪几类工具值得搜。文档给的写法是用 claude_code 这个 preset 加 append,把你的文字追加到预设提示词上而不是替换掉它:
options: {
systemPrompt: {
type: "preset",
preset: "claude_code",
append: "You can search for tools to interact with Slack, GitHub, and Jira."
}
}
Python 侧对应的是 system_prompt,字段结构一样。
在命令行和代码里怎么设
mcp 页给的是 shell 前缀写法:
# Use a custom 5% threshold
ENABLE_TOOL_SEARCH=auto:5 claude
# Disable tool search entirely
ENABLE_TOOL_SEARCH=false claude
这两行在 Linux/macOS 的 shell 里可以直接用。Windows 侧要注意:PowerShell 不接受这种「变量赋值写在命令前面」的语法(这是 shell 语法的通用常识,不是该产品文档的内容),而官方文档这一页没有给 PowerShell 的等价写法。文档同页提到的另一条路是跨平台一致的——把值写进 settings.json 的 env 字段。
在 Agent SDK 里则是通过 query() 的 env 选项传。这里有一个真实的语言差异,文档专门写了:TypeScript 里 env 会替换子进程环境,所以要展开 ...process.env 才能保住继承来的变量;Python 里 env 是叠加在继承环境之上的。这一条踩过一次会记很久。
官方示例里同时做了三件事——连远程 MCP server、用通配符 mcp__enterprise-tools__* 预授权该 server 的全部工具、把阈值设成 auto:5:
options: {
mcpServers: {
"enterprise-tools": {
type: "http",
url: "https://tools.example.com/mcp"
}
},
allowedTools: ["mcp__enterprise-tools__*"],
env: {
...process.env,
ENABLE_TOOL_SEARCH: "auto:5"
}
}
以上片段抄自官方文档示例,未经实测,以官方文档与 --help 的实际输出为准。真要用请把示例 URL 换成你自己的 MCP server 地址。顺带提醒一句:通配符预授权意味着这个 server 的工具被搜出来之后可以直接执行,授权范围是否合适要你自己判断,别照抄进生产配置。
还有一处别忘了看
agent-sdk/tool-search 页末尾有一节 Limits,写了工具目录的规模上限和单次检索返回条数。规模上限那个数值我不抄进正文——这类上限调整起来没有成本,写死在文章里半年后大概率就是错的。你如果真的在往一个大目录上堆工具,去那一页确认一下当时的数字。
该产品迭代频繁,本文涉及的环境变量、字段名与默认值都随版本变动,以官方文档最新内容为准。
本文依据 Claude Code 官方文档(code.claude.com/docs)于 2026-08-17 的公开内容整理。
该产品闭源,本文只复述官方文档写明的机制,不推断其内部实现;
我们没有对文中涉及的功能做过实测,因此不涉及界面外观、操作手感与运行速度的任何描述。
该产品迭代频繁,文中涉及的命令、配置项与默认值随版本变动,请以官方文档最新内容为准。
本文不涉及价格、额度与限流的具体数值,相关信息请以官方定价与用量说明页为准。
安全与合规相关做法请结合自身环境评估,本文不构成安全方案建议。