中文内容
在 Claude Developer Platform 上推出高级工具使用功能
发布于 2025 年 11 月 24 日
我们新增了三项测试版功能,使 Claude 能够动态地发现、学习和执行工具。以下是它们的工作原理。
AI 智能体的未来,是模型能够在数百甚至数千个工具之间无缝协作。一个 IDE 助手可以集成 git 操作、文件处理、包管理器、测试框架和部署流水线。一个运营协调器可以同时连接 Slack、GitHub、Google Drive、Jira、公司数据库以及数十个 MCP 服务器。
要构建有效的智能体,它们需要能够使用无限的工具库,而不是预先把每个定义都塞进上下文中。我们关于将代码执行与 MCP 结合使用的博客文章讨论了,在智能体读取请求之前,工具结果和定义有时会消耗 50,000 多个 token。智能体应当按需发现并加载工具,只保留与当前任务相关的内容。
智能体还需要具备从代码中调用工具的能力。使用自然语言工具调用时,每次调用都需要完整的一次推理过程,中间结果无论是否有用都会堆积在上下文中。代码天然适合编排逻辑,例如循环、条件判断和数据转换。智能体需要具备根据手头任务在代码执行和推理之间灵活选择的能力。
智能体还需要从示例中学习正确的工具用法,而不仅仅是 schema 定义。JSON schema 定义了结构上什么是有效的,但无法表达使用模式:何时包含可选参数、哪些组合是合理的,或你的 API 期望哪些约定。
今天,我们发布三项功能,使这成为可能:
- 工具搜索工具,使 Claude 能够使用搜索工具访问数千种工具,而不会消耗其上下文窗口
- 程序化工具调用,使 Claude 能够在代码执行环境中调用工具,从而减少对模型上下文窗口的影响
- 工具使用示例,为演示如何有效使用给定工具提供了通用标准
在内部测试中,我们发现这些功能帮助我们构建了使用传统工具调用模式无法实现的东西。例如,Claude for Excel 使用程序化工具调用来读取和修改包含数千行的电子表格,而不会使模型的上下文窗口过载。
根据我们的经验,我们认为这些功能为你可以用 Claude 构建的内容开启了新的可能性。
工具搜索工具
挑战
MCP 工具定义提供了重要的上下文,但随着连接的服务器增多,这些 token 可能会累积起来。以一个五服务器的配置为例:
- GitHub:35 个工具(约 26K 个 token)
- Slack:11 个工具(约 21K 个 token)
- Sentry:5 个工具(约 3K 个 token)
- Grafana:5 个工具(约 3K 个 token)
- Splunk:2 个工具(约 2K tokens)
这意味着在对话甚至开始之前,就有 58 个工具消耗了约 55K tokens。再添加像 Jira 这样的更多服务器(仅 Jira 就使用约 17K tokens),你很快就会接近 100K+ tokens 的开销。在 Anthropic,我们见过工具定义在优化前消耗 134K tokens。
但 token 成本并不是唯一的问题。最常见的失败是工具选择错误和参数不正确,尤其是当工具名称相似时,例如 notification-send-user 与 notification-send-channel。
我们的解决方案
Tool Search Tool 不会预先加载所有工具定义,而是按需发现工具。Claude 只会看到当前任务实际需要的工具。

传统方法:
- 所有工具定义预先加载(50 多个 MCP 工具约需 72K 个 token)
- 对话历史和系统提示会竞争剩余空间
- 在任何工作开始之前,总上下文消耗约为 77K tokens
使用 Tool Search Tool 时:
- 仅预先加载 Tool Search Tool(约 500 tokens)
- 按需发现所需工具(3-5 个相关工具,约 3K tokens)
- 总上下文消耗:约 8.7K tokens,保留 95% 的上下文窗口
这意味着在保持可访问完整工具库的同时,token 使用量减少了 85%。内部测试显示,在使用大型工具库时,启用 Tool Search Tool 后 MCP 评估的准确率显著提升。Opus 4 从 49% 提升至 74%,Opus 4.5 从 79.5% 提升至 88.1%。
Tool Search Tool 的工作原理
工具搜索工具让 Claude 能够动态发现工具,而不是预先加载所有定义。你将所有工具定义提供给 API,但用 defer_loading: true 标记工具,使其可按需发现。延迟加载的工具最初不会加载到 Claude 的上下文中。Claude 只会看到工具搜索工具本身,以及任何 defer_loading: false 的工具(你最关键、最常用的工具)。
当 Claude 需要特定能力时,它会搜索相关工具。工具搜索工具会返回匹配工具的引用,这些引用会在 Claude 的上下文中展开为完整定义。
例如,如果 Claude 需要与 GitHub 交互,它会搜索“github”,并且只加载 github.createPullRequest 和 github.listIssues,而不会加载你来自 Slack、Jira 和 Google Drive 的其他 50 多个工具。
这样,Claude 可以访问你的完整工具库,同时只为它实际需要的工具支付 token 成本。
提示缓存说明:Tool Search Tool 不会破坏提示缓存,因为延迟加载的工具会被完全排除在初始提示之外。它们只有在 Claude 搜索它们之后才会被添加到上下文中,因此你的系统提示和核心工具定义仍然可以缓存。
实现:
{
"tools": [
// Include a tool search tool (regex, BM25, or custom)
{"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"},
// Mark tools for on-demand discovery
{
"name": "github.createPullRequest",
"description": "Create a pull request",
"input_schema": {...},
"defer_loading": true
}
// ... hundreds more deferred tools with defer_loading: true
]
}
对于 MCP 服务器,你可以延迟加载整个服务器,同时保持特定的高频使用工具已加载:
{
"type": "mcp_toolset",
"mcp_server_name": "google-drive",
"default_config": {"defer_loading": true}, # defer loading the entire server
"configs": {
"search_files": {
"defer_loading": false
} // Keep most used tool loaded
}
}Claude Developer Platform 开箱即用地提供基于正则表达式和基于 BM25 的搜索工具,但你也可以使用嵌入或其他策略来实现自定义搜索工具。
何时使用 Tool Search Tool
与任何架构决策一样,启用 Tool Search Tool 涉及权衡。该功能会在工具调用之前增加一个搜索步骤,因此当上下文节省和准确性提升超过额外延迟带来的成本时,它能带来最佳投资回报。
在以下情况下使用它:
- 工具定义消耗超过 10K 个 token
- 遇到工具选择准确性问题
- 构建由 MCP 驱动、包含多个服务器的系统
- 可用工具超过 10 个
以下情况收益较小:
- 小型工具库(少于 10 个工具)
- 每个会话中都会频繁使用所有工具
- 工具定义很紧凑
程序化工具调用
挑战
随着工作流变得更加复杂,传统的工具调用会产生两个根本性问题:
- 中间结果造成的上下文污染:当 Claude 分析一个 10MB 的日志文件以寻找错误模式时,整个文件都会进入其上下文窗口,尽管 Claude 只需要错误频率的摘要。当跨多个表获取客户数据时,无论相关性如何,每条记录都会累积在上下文中。这些中间结果会消耗大量 token 预算,并且可能将重要信息完全挤出上下文窗口。
- 推理开销和手动综合:每次工具调用都需要一次完整的模型推理过程。收到结果后,Claude 必须通过自然语言处理来“目测”数据,以提取相关信息、推理各部分如何相互关联,并决定下一步做什么。一个包含五个工具的工作流意味着五次推理过程,再加上 Claude 解析每个结果、比较数值并综合结论。这既缓慢又容易出错。
我们的解决方案
程序化工具调用使 Claude 能够通过代码而不是通过单独的 API 往返来编排工具。Claude 不再一次请求一个工具且每个结果都返回到其上下文中,而是编写代码来调用多个工具、处理它们的输出,并控制哪些信息实际进入其上下文窗口。
Claude 擅长编写代码;通过让它用 Python 表达编排逻辑,而不是通过自然语言调用工具,你可以获得更可靠、更精确的控制流。循环、条件判断、数据转换和错误处理都在代码中显式呈现,而不是隐含在 Claude 的推理中。
示例:预算合规性检查
考虑一个常见的业务任务:“哪些团队成员超出了他们的第三季度差旅预算?”
你有三个可用工具:
- get_team_members(department) - 返回包含 ID 和级别的团队成员列表
- get_expenses(user_id, quarter) - 返回某个用户的费用明细项
- get_budget_by_level(level) - 返回某个员工级别的预算限额
传统方法:
- 获取团队成员 → 20 人
- 对于每个人,获取其第三季度费用 → 20 次工具调用,每次返回 50–100 条明细项(航班、酒店、餐饮、收据)
- 按员工级别获取预算限额
- 所有这些都会进入 Claude 的上下文:2,000 多条费用明细项(50 KB 以上)
- Claude 手动汇总每个人的支出,查找他们的预算,并将支出与预算限额进行比较
- 需要更多次与模型往返交互,并显著消耗上下文
使用程序化工具调用:
不再让每个工具结果都返回给 Claude,而是由 Claude 编写一个 Python 脚本来编排整个工作流程。该脚本在代码执行工具(一个沙盒环境)中运行,并在需要从你的工具获取结果时暂停。当你通过 API 返回工具结果时,这些结果由脚本处理,而不是被模型消耗。脚本继续执行,Claude 只看到最终输出。

以下是 Claude 用于预算合规任务的编排代码示例:
team = await get_team_members("engineering")
# Fetch budgets for each unique level
levels = list(set(m["level"] for m in team))
budget_results = await asyncio.gather(*[
get_budget_by_level(level) for level in levels
])
# Create a lookup dictionary: {"junior": budget1, "senior": budget2, ...}
budgets = {level: budget for level, budget in zip(levels, budget_results)}
# Fetch all expenses in parallel
expenses = await asyncio.gather(*[
get_expenses(m["id"], "Q3") for m in team
])
# Find employees who exceeded their travel budget
exceeded = []
for member, exp in zip(team, expenses):
budget = budgets[member["level"]]
total = sum(e["amount"] for e in exp)
if total > budget["travel_limit"]:
exceeded.append({
"name": member["name"],
"spent": total,
"limit": budget["travel_limit"]
})
print(json.dumps(exceeded))Claude 的上下文只接收最终结果:超出预算的两到三个人。2000 多条明细、中间求和以及预算查询都不会影响 Claude 的上下文,从而将消耗量从 200KB 的原始费用数据减少到仅 1KB 的结果。
效率提升非常显著:
- Token 节省:通过将中间结果排除在 Claude 的上下文之外,PTC 显著减少了 token 消耗。在复杂研究任务中,平均使用量从 43,588 个 token 降至 27,297 个,减少了 37%。
- 延迟降低:每次 API 往返都需要模型推理(数百毫秒到数秒)。当 Claude 在单个代码块中编排 20 多次工具调用时,你就消除了 19 次以上的推理过程。API 会处理工具执行,而无需每次都返回模型。
- 准确性提升:通过编写明确的编排逻辑,Claude 相比用自然语言处理多个工具结果时出错更少。内部知识检索从 25.6% 提升至 28.5%;GIA 基准从 46.5% 提升至 51.2%。
生产工作流涉及杂乱的数据、条件逻辑以及需要扩展的操作。Programmatic Tool Calling 让 Claude 能够以编程方式处理这种复杂性,同时将重点放在可执行的结果上,而不是原始数据处理。
Programmatic Tool Calling 的工作原理
1. 将工具标记为可从代码调用
将 code_execution 添加到 tools,并将 allowed_callers 设置为选择启用的工具,以进行编程式执行:
{
"tools": [
{
"type": "code_execution_20250825",
"name": "code_execution"
},
{
"name": "get_team_members",
"description": "Get all members of a department...",
"input_schema": {...},
"allowed_callers": ["code_execution_20250825"] # opt-in to programmatic tool calling
},
{
"name": "get_expenses",
...
},
{
"name": "get_budget_by_level",
...
}
]
}该 API 会将这些工具定义转换为 Claude 可以调用的 Python 函数。
2. Claude 编写编排代码
Claude 不再逐个请求工具,而是生成 Python 代码:
{
"type": "server_tool_use",
"id": "srvtoolu_abc",
"name": "code_execution",
"input": {
"code": "team = get_team_members('engineering')\n..." # the code example above
}
}3. 工具执行时不会占用 Claude 的上下文
当代码调用 get_expenses() 时,你会收到一个带有 caller 字段的工具请求:
{
"type": "tool_use",
"id": "toolu_xyz",
"name": "get_expenses",
"input": {"user_id": "emp_123", "quarter": "Q3"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_abc"
}
}你提供结果,该结果会在代码执行环境中处理,而不是在 Claude 的上下文中处理。对于代码中的每次工具调用,都会重复这一请求-响应循环。
4. 只有最终输出进入上下文
代码运行完成后,只有代码的结果会返回给 Claude:
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc",
"content": {
"stdout": "[{\"name\": \"Alice\", \"spent\": 12500, \"limit\": 10000}...]"
}
}这就是 Claude 所看到的全部内容,而不是沿途处理的 2000 多条费用明细。
何时使用程序化工具调用
程序化工具调用会在你的工作流中增加一个代码执行步骤。当 token 节省、延迟改善和准确性提升十分显著时,这种额外开销是值得的。
在以下情况下最有益:
- 处理只需要聚合结果或摘要的大型数据集
- 运行包含三个或更多相互依赖的工具调用的多步骤工作流
- 在 Claude 查看工具结果之前,对其进行筛选、排序或转换
- 处理中间数据不应影响 Claude 推理的任务
- 跨多个项目并行运行操作(例如,检查 50 个端点)
在以下情况下收益较小:
- 进行简单的单一工具调用
- 处理需要 Claude 查看所有中间结果并进行推理的任务
- 使用小型响应进行快速查询
工具使用示例
挑战
JSON Schema 擅长定义结构——类型、必填字段、允许的枚举值——但它无法表达使用模式:何时包含可选参数、哪些组合是合理的,或者你的 API 期望哪些约定。
考虑一个支持工单 API:
{
"name": "create_ticket",
"input_schema": {
"properties": {
"title": {"type": "string"},
"priority": {"enum": ["low", "medium", "high", "critical"]},
"labels": {"type": "array", "items": {"type": "string"}},
"reporter": {
"type": "object",
"properties": {
"id": {"type": "string"},
"name": {"type": "string"},
"contact": {
"type": "object",
"properties": {
"email": {"type": "string"},
"phone": {"type": "string"}
}
}
}
},
"due_date": {"type": "string"},
"escalation": {
"type": "object",
"properties": {
"level": {"type": "integer"},
"notify_manager": {"type": "boolean"},
"sla_hours": {"type": "integer"}
}
}
},
"required": ["title"]
}
}该架构定义了哪些内容是有效的,但留下了一些关键问题未回答:
- 格式歧义:due_date 应该使用 "2024-11-06"、"Nov 6, 2024",还是 "2024-11-06T00:00:00Z"?
- ID 约定:reporter.id 是 UUID、“USR-12345”,还是只是“12345”?
- 嵌套结构用法:Claude 应在什么时候填充 reporter.contact?
- 参数相关性:escalation.level 和 escalation.sla_hours 与 priority 有何关系?
这些歧义可能导致工具调用格式错误以及参数使用不一致。
我们的解决方案
工具使用示例允许你直接在工具定义中提供示例工具调用。你不是仅依赖架构,而是向 Claude 展示具体的使用模式:
{
"name": "create_ticket",
"input_schema": { /* same schema as above */ },
"input_examples": [
{
"title": "Login page returns 500 error",
"priority": "critical",
"labels": ["bug", "authentication", "production"],
"reporter": {
"id": "USR-12345",
"name": "Jane Smith",
"contact": {
"email": "jane@acme.com",
"phone": "+1-555-0123"
}
},
"due_date": "2024-11-06",
"escalation": {
"level": 2,
"notify_manager": true,
"sla_hours": 4
}
},
{
"title": "Add dark mode support",
"labels": ["feature-request", "ui"],
"reporter": {
"id": "USR-67890",
"name": "Alex Chen"
}
},
{
"title": "Update API documentation"
}
]
}从这三个示例中,Claude 学会了:
- 格式约定:日期使用 YYYY-MM-DD,用户 ID 遵循 USR-XXXXX,标签使用 kebab-case
- 嵌套结构模式:如何构建包含嵌套 contact 对象的 reporter 对象
- 可选参数关联:严重错误包含完整联系信息 + 升级处理,并具有严格的 SLA;功能请求包含 reporter,但没有 contact/escalation;内部任务仅包含标题
在我们自己的内部测试中,工具使用示例将复杂参数处理的准确率从 72% 提高到 90%。
何时使用工具使用示例
工具使用示例会为你的工具定义增加 token,因此当准确性提升超过额外成本时,它们最有价值。
在以下情况下最有益:
- 复杂的嵌套结构,其中有效的 JSON 并不意味着用法正确
- 包含许多可选参数和纳入模式的工具很重要
- 具有领域特定约定且这些约定未在 schema 中体现的 API
- 相似工具,需要通过示例说明应使用哪一个(例如 create_ticket 与 create_incident)
在以下情况下收益较小:
- 用途明显的简单单参数工具
- Claude 已经理解的标准格式,如 URL 或电子邮件
- 更适合通过 JSON Schema 约束处理的验证问题
最佳实践
构建能够执行现实世界操作的智能体,意味着要同时处理规模、复杂性和精确性。这三项特性协同作用,用于解决工具使用工作流中的不同瓶颈。以下是如何有效组合它们。
策略性地分层使用特性
并非每个智能体在执行特定任务时都需要使用全部三项特性。先从你最大的瓶颈入手:
- 工具定义导致的上下文膨胀 → Tool Search Tool
- 大型中间结果污染上下文 → 程序化工具调用
- 参数错误和格式错误的调用 → 工具使用示例
这种聚焦的方法让你能够解决限制智能体性能的具体约束,而不是一开始就增加复杂性。
然后根据需要叠加其他功能。它们是互补的:工具搜索工具确保找到正确的工具,程序化工具调用确保高效执行,工具使用示例确保正确调用。
设置工具搜索工具以实现更好的发现
工具搜索会根据名称和描述进行匹配,因此清晰、描述性的定义可提高发现准确性。
// Good
{
"name": "search_customer_orders",
"description": "Search for customer orders by date range, status, or total amount. Returns order details including items, shipping, and payment info."
}
// Bad
{
"name": "query_db_orders",
"description": "Execute order query"
}添加系统提示词指导,以便 Claude 知道有哪些可用内容:
You have access to tools for Slack messaging, Google Drive file management,
Jira ticket tracking, and GitHub repository operations. Use the tool search
to find specific capabilities.始终加载你最常用的三到五个工具,其余工具延后加载。这样可以在常见操作的即时访问与其他所有工具的按需发现之间取得平衡。
设置程序化工具调用以确保正确执行
由于 Claude 会编写代码来解析工具输出,因此请清楚地记录返回格式。这有助于 Claude 编写正确的解析逻辑:
{
"name": "get_orders",
"description": "Retrieve orders for a customer.
Returns:
List of order objects, each containing:
- id (str): Order identifier
- total (float): Order total in USD
- status (str): One of 'pending', 'shipped', 'delivered'
- items (list): Array of {sku, quantity, price}
- created_at (str): ISO 8601 timestamp"
}请参阅下方可受益于程序化编排的可选择启用工具:
- 可并行运行的工具(独立操作)
- 可安全重试的操作(幂等)
设置工具使用示例以确保参数准确性
编写示例以提升行为清晰度:
- 使用真实的数据(真实城市名称、合理的价格,而不是“string”或“value”)
- 展示多样性,包括最小化、部分和完整规格模式
- 保持简洁:每个工具提供 1-5 个示例
- 关注歧义(仅在无法从 schema 明显看出正确用法时添加示例)
开始使用
这些功能目前处于 beta 版。要启用它们,请添加 beta 标头并包含所需的工具:
client.beta.messages.create(
betas=["advanced-tool-use-2025-11-20"],
model="claude-sonnet-4-5-20250929",
max_tokens=4096,
tools=[
{"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"},
{"type": "code_execution_20250825", "name": "code_execution"},
# Your tools with defer_loading, allowed_callers, and input_examples
]
)有关详细的 API 文档和 SDK 示例,请参阅我们的:
- Tool Search Tool 的文档和 cookbook
- 文档和


