Anthropic · 工程博客

Claude 开发者平台推出高级工具使用功能

Introducing advanced tool use on the Claude Developer Platform

二〇二六年七月三十日 · 英文原文

Anthropic 发布三项功能以提升 AI agent 在大量工具间的协作效率:工具搜索工具(Tool Search Tool)让模型按需发现工具,而非预加载所有定义,内部测试显示 token 使用量减少 85%,Opus 4 评估准确率从 49% 提升至 74%,Opus 4.5 从 79.5% 提升至 88.1%;程序化工具调用(Programmatic Tool Calling)允许 Claude 通过 Python 代码编排多工具工作流,将 200KB 上下文消耗降至 1KB;工具使用示例(Tool Use Examples)在定义中提供具体调用样例,将复杂参数处理准确率从 72% 提升至 90%。

AI Agent的未来:模型如何在成百上千个工具间无缝协作

一个IDE助手,能整合git操作、文件管理、包管理器、测试框架和部署流水线。一个运维协调器,能同时连接Slack、GitHub、Google Drive、Jira、公司数据库和数十个MCP服务器。

要构建有效的agent,它们需要能够使用无限的工具库,而无需预先将所有定义塞入上下文。我们关于使用MCP进行代码执行的文章讨论了工具结果和定义有时会在agent读取请求前消耗50,000+ token。Agent应该按需发现和加载工具,只保留与当前任务相关的内容。

Agent还需要能够通过代码调用工具。使用自然语言工具调用时,每次调用都需要一次完整的推理过程,中间结果无论是否有用都会堆积在上下文中。代码天然适合编排逻辑,如循环、条件判断和数据转换。Agent需要灵活性,能够根据手头任务在代码执行和推理之间做出选择。

Agent还需要从示例中学习正确的工具使用方式,而不仅仅是schema定义。JSON schema定义了结构上有效的内容,但无法表达使用模式:何时包含可选参数,哪些组合有意义,或者你的API期望什么约定。

今天,我们发布三个功能来实现这一点:

在内部测试中,我们发现这些功能帮助我们构建了使用传统工具使用模式无法实现的东西。例如,Claude for Excel使用Programmatic Tool Calling来读取和修改包含数千行的电子表格,而不会使模型的上下文窗口过载。

根据我们的经验,我们相信这些功能为使用Claude构建应用开辟了新的可能性。

工具搜索工具

MCP工具定义提供了重要的上下文,但随着更多服务器连接,这些token会累积起来。考虑一个五台服务器的配置:

在对话开始之前,58个工具就已经消耗了大约55K token。添加更多服务器,如Jira(仅这一个就使用约17K token),你很快就会接近100K+ token的开销。在Anthropic,我们看到工具定义在优化前消耗了134K token。

但token成本并非唯一问题。最常见的失败是工具选择错误和参数不正确,尤其是当工具名称相似时,如notification-send-user vs. notification-send-channel。

工具搜索工具不是预先加载所有工具定义,而是按需发现工具。Claude只看到当前任务实际需要的工具。

传统方法:

使用工具搜索工具:

这表示token使用量减少了85%,同时保持了对完整工具库的访问。内部测试显示,在处理大型工具库时,MCP评估的准确性显著提高。启用工具搜索工具后,Opus 4从49%提升到74%,Opus 4.5从79.5%提升到88.1%。

工具搜索工具让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成本。

提示缓存说明:工具搜索工具不会破坏提示缓存,因为延迟加载的工具完全被排除在初始提示之外。它们只在Claude搜索后才被添加到上下文中,因此你的系统提示和核心工具定义仍然可以缓存。

实现:

对于MCP服务器,你可以延迟加载整个服务器,同时保持特定的高频使用工具加载:

tools=[
  {
    "name": "get_weather",
    "defer_loading": False,  # 始终可用
    # ... 定义
  },
  {
    "name": "search_tool",
    "type": "search_tool",
    "defer_loading": False,  # 搜索工具本身始终可用
    # ... 定义
  }
]

Claude开发者平台提供了基于正则表达式和BM25的搜索工具,但你也可以使用embedding或其他策略实现自定义搜索工具。

与任何架构决策一样,启用工具搜索工具涉及权衡。该功能在工具调用前增加了一个搜索步骤,因此当上下文节省和准确性提升超过额外延迟时,它能带来最佳回报。

何时使用:

不太有益的情况:

程序化工具调用

随着工作流程变得复杂,传统工具调用会产生两个根本性问题:

  1. 上下文膨胀:每个工具结果都返回给模型,即使只有一小部分有用
  2. 顺序瓶颈:工具必须一个接一个调用,每个结果都经过推理

程序化工具调用使Claude能够通过代码编排工具,而不是通过单独的API往返。Claude不是一次请求一个工具并将每个结果返回给其上下文,而是编写调用多个工具、处理其输出并控制哪些信息实际进入其上下文窗口的代码。

Claude擅长编写代码,通过让它在Python中表达编排逻辑而不是通过自然语言工具调用,你可以获得更可靠、更精确的控制流。循环、条件判断、数据转换和错误处理在代码中都是显式的,而不是隐含在Claude的推理中。

考虑一个常见的业务任务:"哪些团队成员超出了他们的Q3旅行预算?"

你有三个工具可用:

传统方法:

  1. Claude请求get_expenses("sales", "Q3") → 返回2,000个明细项(200KB)
  2. Claude请求get_budget("sales") → 返回预算
  3. Claude计算哪些人超出预算
  4. Claude请求get_employee(emp_123) → 返回姓名
  5. 所有2,000个明细项和中间结果都保留在上下文中

使用程序化工具调用:

Claude不是将每个工具结果返回给上下文,而是编写一个Python脚本,编排整个工作流程。该脚本在代码执行工具(沙盒环境)中运行,在需要从你的工具获取结果时暂停。当你通过API返回工具结果时,它们由脚本处理,而不是由模型消费。脚本继续执行,Claude只看到最终输出。

以下是Claude为预算合规任务编写的编排代码:

expenses = get_expenses("sales", "Q3")
budget = get_budget("sales")

# 按员工汇总费用
from collections import defaultdict
totals = defaultdict(float)
for expense in expenses:
    totals[expense.employee_id] += expense.amount

# 找出超出预算的人
over_budget = []
for emp_id, total in totals.items():
    if total > budget.per_employee:
        emp = get_employee(emp_id)
        over_budget.append({
            "name": emp.name,
            "total": total,
            "budget": budget.per_employee,
            "excess": total - budget.per_employee
        })

return over_budget

Claude的上下文只接收最终结果:超出预算的两到三个人。2,000多个明细项、中间汇总和预算查询不会影响Claude的上下文,将原始费用数据的200KB消耗减少到仅1KB的结果。

效率提升显著:

生产工作流程涉及杂乱的数据、条件逻辑和需要扩展的操作。程序化工具调用让Claude能够以编程方式处理这种复杂性,同时将注意力集中在可操作的结果上,而不是原始数据处理。

实现:

code_execution添加到工具中,并设置allowed_callers来选择用于程序化执行的工具:

tools=[
  {
    "name": "get_expenses",
    "code_execution": True,
    "allowed_callers": ["code_execution"],
    # ... 定义
  },
  {
    "name": "code_execution",
    "type": "code_execution",
    # ... 定义
  }
]

API将这些工具定义转换为Claude可以调用的Python函数。

Claude不是一次请求一个工具,而是生成Python代码:

# Claude生成此代码
expenses = get_expenses("sales", "Q3")
budget = get_budget("sales")
# ... 处理逻辑

当代码调用get_expenses()时,你会收到一个带有caller字段的工具请求:

{
  "tool_call": "get_expenses",
  "parameters": {"team": "sales", "quarter": "Q3"},
  "caller": "code_execution"
}

你提供结果,该结果在代码执行环境中处理,而不是在Claude的上下文中。对于代码中的每个工具调用,此请求-响应周期都会重复。

当代码运行完成时,只有代码的结果返回给Claude:

{
  "result": [
    {"name": "Alice", "total": 12500, "budget": 10000, "excess": 2500},
    {"name": "Bob", "total": 11000, "budget": 10000, "excess": 1000}
  ]
}

这就是Claude看到的所有内容,而不是沿途处理的2000多个费用明细项。

程序化工具调用为你的工作流程增加了一个代码执行步骤。当token节省、延迟改进和准确性提升显著时,这种额外开销是值得的。

最有益的情况:

不太有益的情况:

工具使用示例

JSON Schema擅长定义结构——类型、必填字段、允许的枚举——但它无法表达使用模式:何时包含可选参数,哪些组合有意义,或者你的API期望什么约定。

考虑一个支持工单API:

{
  "name": "create_ticket",
  "description": "创建支持工单",
  "input_schema": {
    "type": "object",
    "properties": {
      "title": {"type": "string"},
      "description": {"type": "string"},
      "priority": {"type": "string", "enum": ["low", "medium", "high", "critical"]},
      "assignee": {"type": "string"},
      "labels": {"type": "array", "items": {"type": "string"}},
      "due_date": {"type": "string"}
    },
    "required": ["title", "description"]
  }
}

schema定义了什么是有效的,但留下了关键问题未回答:

这些歧义可能导致格式错误的工具调用和参数使用不一致。

工具使用示例让你直接在工具定义中提供示例工具调用。Claude不是仅依赖schema,而是看到具体的使用模式:

{
  "name": "create_ticket",
  "description": "创建支持工单",
  "input_schema": { /* ... */ },
  "tool_use_examples": [
    {
      "description": "为生产中断创建紧急工单",
      "input": {
        "title": "生产数据库连接失败",
        "description": "所有生产实例无法连接到主数据库。需要立即调查。",
        "priority": "critical",
        "assignee": "oncall@company.com",
        "labels": ["production", "database", "p0"],
        "due_date": "2024-01-15"
      }
    },
    {
      "description": "为UI改进创建低优先级工单",
      "input": {
        "title": "更新仪表盘颜色方案",
        "description": "将主颜色从蓝色改为绿色以匹配品牌指南。",
        "priority": "low",
        "labels": ["ui", "enhancement"]
      }
    },
    {
      "description": "为功能请求创建工单",
      "input": {
        "title": "添加CSV导出功能",
        "description": "用户应该能够将他们的数据导出为CSV格式。",
        "priority": "medium",
        "labels": ["feature-request"],
        "due_date": "2024-02-01"
      }
    }
  ]
}

从这三个示例中,Claude学习到:

在我们自己的内部测试中,工具使用示例在复杂参数处理上将准确性从72%提高到90%。

工具使用示例为你的工具定义增加了token,因此当准确性提升超过额外成本时,它们最有价值。

最有益的情况:

不太有益的情况:

将它们结合起来

构建执行实际操作的agent意味着同时处理规模、复杂性和精度。这三个功能协同工作,解决工具使用工作流程中的不同瓶颈。以下是如何有效组合它们。

并非每个agent都需要为给定任务使用所有三个功能。从你最大的瓶颈开始:

  1. 工具太多? → 启用工具搜索工具
  2. 数据太多? → 启用程序化工具调用
  3. 工具太复杂? → 添加工具使用示例

这种聚焦方法让你解决限制agent性能的具体约束,而不是预先增加复杂性。

然后根据需要添加更多功能。它们是互补的:工具搜索工具确保找到正确的工具,程序化工具调用确保高效执行,工具使用示例确保正确调用。

最佳实践

清晰的工具命名:工具搜索根据名称和描述进行匹配,因此清晰、描述性的定义可以提高发现准确性。

系统提示指导:添加系统提示指导,让Claude知道有什么可用:

You have access to a large tool library. Use the Tool Search Tool to find 
relevant tools for your task. For data-intensive operations, use 
Programmatic Tool Calling to process results efficiently.

分层工具加载:保持三到五个最常用的工具始终加载,其余延迟加载。这平衡了常见操作的即时访问和所有其他操作的按需发现。

清晰的返回格式:由于Claude编写代码来解析工具输出,请清晰地记录返回格式。这有助于Claude编写正确的解析逻辑:

# 返回格式:{"employees": [{"id": str, "name": str, "department": str}]}
employees = get_employees("engineering")

选择性程序化执行:查看下面选择加入程序化编排的工具:

tools = [
  # 高频工具 - 始终可用
  {"name": "search_knowledge_base", "defer_loading": False},
  {"name": "get_current_time", "defer_loading": False},
  
  # 按需工具 - 延迟加载
  {"name": "github_create_pr", "defer_loading": True},
  {"name": "jira_create_ticket", "defer_loading": True},
  
  # 数据密集型工具 - 程序化执行
  {"name": "get_analytics", "code_execution": True, "allowed_callers": ["code_execution"]},
  {"name": "process_report", "code_execution": True, "allowed_callers": ["code_execution"]},
]

行为示例:为行为清晰度制作示例:

{
  "tool_use_examples": [
    {
      "description": "搜索用户时,使用全名以获得更精确的结果",
      "input": {"query": "Alice Smith", "limit": 5}
    }
  ]
}

入门指南

这些功能处于beta阶段。要启用它们,添加beta头并包含你需要的工具:

client = Anthropic()
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=8192,
    tools=[...],  # 包含你的工具定义
    extra_headers={
        "anthropic-beta": "tool-search-2025-04-04,code-execution-2025-04-04,tool-use-examples-2025-04-04"
    },
    messages=[...]
)

有关详细的API文档和SDK示例,请参阅我们的:

这些功能将工具使用从简单的函数调用推向智能编排。随着agent处理跨越数十个工具和大型数据集的更复杂工作流程,动态发现、高效执行和可靠调用成为基础。

我们期待看到你构建的内容。


由Bin Wu撰写,感谢Adam Jones、Artur Renault、Henry Tay、Jake Noble、Noah Picard、Sam Jiang和Claude开发者平台团队的贡献。这项工作建立在Chris Gorgolewski、Daniel Jiang、Jeremy Fox和Mike Lambert的基础研究之上。我们还从整个AI生态系统中汲取了灵感,包括Joel Pobar的LLMVM、Cloudflare的Code Mode和Code Execution as MCP。特别感谢Andy Schumeister、Hamish Kerr、Keir Bradwell、Matt Bleifer和Molly Vorwerck的支持。

译自 Anthropic · 工程博客 · 录于 二〇二六年七月三十日