Claude 如何减少 85% 工具 Token:Tool Search 如何在不破坏 Prompt Cache 和约束解码的情况下实现工具按需加载

随着 Agent 能力增强,工具数量正在快速膨胀。

一个简单的聊天 Agent 可能只有几个工具:

search() calculator() weather()

但进入真实生产环境后,一个企业级 Agent 往往需要接入:

  • GitHub MCP
  • Slack MCP
  • Jira MCP
  • 数据库 MCP
  • 浏览器 MCP
  • 云服务 MCP
  • 内部业务系统 MCP

最终可能拥有数百甚至上千个工具。

问题来了:

这些工具的 schema 会占据大量上下文窗口。

Anthropic 官方提出的 Tool Search,就是为了解决这个问题。

它可以让 Claude 在大量工具环境下减少超过 85% 的工具相关 token 消耗。

但它真正优秀的地方,不只是“少放一些工具描述”,而是在上下文、Prompt Cache、约束解码三个层面同时优化。


传统 Agent:所有工具全部进入 Context

传统 Tool Calling 模式:

Request: system prompt + tools: tool_1 schema tool_2 schema tool_3 schema ... tool_1000 schema + conversation

模型每次请求都会看到完整工具定义。

例如:

{"name":"database_query","description":"Execute SQL query","input_schema":{"properties":{"operation":{"enum":["select","insert","update"]}}}}

这些 schema 不只是文本。

它们承担三个作用:

  1. 告诉模型有哪些工具
  2. 告诉模型参数格式
  3. 提供工具调用约束

当工具数量增长:

1000 tools ↓ 几十万 tokens

会产生:

  • Context 占用增加
  • Prefill 成本增加
  • KV Cache 增大
  • Prompt Cache 容易失效
  • 模型选择工具难度增加

Tool Search 的核心:工具定义仍然存在,但不进入模型上下文

很多人第一次理解 Tool Search 会误解:

Anthropic 是不是不发送这些工具了?

不是。

实际上:

请求中仍然包含:

tools:[github_search,mysql_query,slack_send,...]

完整工具定义仍然发送给 Anthropic API。

但是:

API 会把工具分成两部分:

tools array | | +----------------+ | Tool Search Index | | Context Builder

对于:

defer_loading:true

的工具:

不会直接进入模型上下文。

例如:

原来:

System Prompt github schema mysql schema slack schema 1000 tools Conversation

变成:

System Prompt Tool Search Conversation

模型一开始根本看不到大量工具 schema。


找到工具后,API 如何加载?

用户:

查询 GitHub issue

Claude:

我需要 GitHub issue 工具

调用:

tool_search("github issue")

Tool Search 返回:

github_search_issue

然后 API 自动插入:

tool_reference

展开成:

github_search_issue 完整 schema

进入后续 conversation。

于是模型下一步才看到:

{"name":"github_search_issue","parameters":{...}}

然后调用工具。


最关键的问题:Prompt Cache 会不会被破坏?

这是很多 Agent 架构容易踩坑的地方。

如果简单实现:

第一次: System + 所有工具 第二次: System + 不同工具集合

那么:

Prompt Cache 前缀直接失效。

因为缓存要求:

prefix token 完全一致

Anthropic 的设计:

Cached Prefix: System Prompt + Tool Search Tool + 固定工具 --------------------- Dynamic Context: tool_reference 展开后的工具 schema Conversation

动态工具加载发生在 prefix 后面。

因此:

缓存前缀保持稳定 ↓ Prompt Cache 继续生效

这也是为什么 Tool Search 不是简单的“工具 RAG”。


另一个隐藏问题:工具 schema 还负责约束解码

很多人只关注 token。

但 Tool Schema 还有一个重要作用:

Constrained Decoding(约束解码)。

例如:

工具:

{"operation":{"enum":["select","insert","delete"]}}

模型生成:

{"operation":

Decoder 可以限制:

允许:

select insert delete

禁止:

hello abc random

流程:

JSON Schema ↓ Grammar ↓ Logits Mask ↓ Decoder

那么问题来了:

如果 deferred tool 不在 context 中,

Claude 怎么知道 enum?

答案:

Tool Search 并没有移除工具 schema。

完整 tools array 仍然用于:

1. Tool Search Index 2. Strict Tool Grammar 3. Constrained Decoding

也就是说:

同一个 schema 有三条路径:

Tool Schema | +------------+-------------+ | | | Search Context Decoder Index Loading Grammar

这就是 Anthropic 设计强大的地方:

它不是:

删除工具 schema

而是:

延迟 schema 进入模型上下文

为什么不是所有模型厂商都能直接复制?

这里有一个容易忽略的问题。

很多人看到 Tool Search 后,会想:

我是不是自己写一个 tool router,把工具检索出来?

这并不完全等价。

因为 Anthropic 有 API 层支持:

完整 tools array ↓ 服务器内部: - 建索引 - 管理 tool_reference - 构建 grammar - 保持 cache prefix

如果模型厂商没有类似能力,简单做:

Agent: 每轮动态修改 tools 只发送当前需要工具

可能产生反效果。

例如:

第一次:

System Tool A Tool B

第二次:

System Tool C Tool D

结果:

Prompt Cache miss

每轮都重新 prefill。


甚至:

为了减少:

tool token

反而增加:

cache miss成本

最终:

token下降 但 latency 上升 成本增加

Tool Search 的本质:不是减少工具,而是分离三种职责

优秀 Agent 架构应该把工具 schema 分成三个用途:

Tool Schema | +------------+------------+ | | | Search Index Context Decoder 找工具 给模型看 约束生成

传统方式:

一个 schema 三个任务全部塞进 Context

Tool Search:

一个 schema 三个系统分别使用

对 Coding Agent 的启发

未来 Coding Agent 的工具数量只会越来越多。

例如:

Filesystem MCP Git MCP Browser MCP Database MCP Cloud MCP Issue MCP CI/CD MCP

如果全部进入 Context:

工具 schema 很快成为主要 token 消耗。

更合理的架构:

System Prompt | | Prompt Cache | Tool Search Index | User Intent | Retrieve Tool | Load Schema | Call Tool

总结

Claude Tool Search 看似只是一个:

“减少工具 token 的功能”

但实际上解决的是 Agent 工程中的三个核心问题:

问题传统方式Tool Search
工具 token全部加载按需加载
Prompt Cache容易失效保持 prefix 稳定
约束解码依赖 context schemaAPI 保留完整 schema

所以它减少 85% 工具 token 的真正原因不是删除工具,而是:

让工具 schema 不再同时承担 Context、搜索、解码三个职责,而是在 API 层进行分离。

这也是为什么类似设计不能简单复制到所有模型。如果底层 API 不支持 Tool Search、tool_reference 和 schema grammar 管理,盲目动态修改工具列表,很可能导致 Prompt Cache 频繁失效,最终优化变成反优化。