在 Claude 开发者平台上引入高级工具的使用

原文 Introducing advanced tool use on the Claude Developer Platform \ Anthropic

AI Agent 的未来是模型能够无缝地跨越数百或数千个工具协同工作。一个 IDE 助手集成了 git 操作、文件操作、包管理器、测试框架和部署 pipeline。一个运维协调器同时连接 Slack、GitHub、Google Drive、Jira、公司数据库以及数十个 MCP server。

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

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

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

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

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

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

Tool Search Tool

挑战

MCP 工具定义提供了重要的 context,但随着更多 server 连接,这些 token 会累积。考虑一个五服务器设置:

那就是 58 个工具在对话甚至开始之前就消耗了大约 55K token。添加更多 server,如 Jira(仅其一项就使用 ~17K token),你很快就会接近 100K+ token 开销。在 Anthropic,我们看到工具定义在优化之前消耗了 134K token。

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

我们的解决方案

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

Tool Search Tool 图示

与 Claude 的传统方法相比,Tool Search Tool 节省了 191,300 token 的 context(传统方法为 122,800)

传统方法:

使用 Tool Search Tool:

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

Tool Search Tool 如何工作

Tool Search Tool 让 Claude 动态发现工具,而不是预先加载所有定义。你向 API 提供所有工具定义,但使用 defer_loading: true 标记工具以使其可按需发现。延迟的工具最初不会加载到 Claude 的 context 中。Claude 只看到 Tool Search Tool 本身以及任何带有 defer_loading: false 的工具(你最关键、最常用的工具)。

当 Claude 需要特定功能时,它会搜索相关工具。Tool Search Tool 返回对匹配工具的引用,这些引用会扩展为 Claude context 中的完整定义。

例如,如果 Claude 需要与 GitHub 交互,它会搜索 “github”,只有 github.createPullRequestgithub.listIssues 被加载——而不是你来自 Slack、Jira 和 Google Drive 的其他 50+ 个工具。

这样,Claude 可以访问你的完整工具库,同时只为它实际需要的工具支付 token 成本。

Prompt caching 注意事项: Tool Search Tool 不会破坏 prompt caching,因为延迟工具完全从初始 prompt 中排除。它们只在 Claude 搜索它们后添加到 context 中,因此你的 system prompt 和核心工具定义保持可缓存。

实现:

{
  "tools": [
    // 包含一个工具搜索工具 (regex、BM25 或自定义)
    {"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"},

    // 标记工具以按需发现
    {
      "name": "github.createPullRequest",
      "description": "Create a pull request",
      "input_schema": {...},
      "defer_loading": true
    }
    // ... 数百个具有 defer_loading: true 的延迟工具
  ]
}

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

{
  "type": "mcp_toolset",
  "mcp_server_name": "google-drive",
  "default_config": {"defer_loading": true}, // 延迟加载整个 server
  "configs": {
    "search_files": {
      "defer_loading": false
    }  // 保持最常用的工具加载
  }
}

Claude Developer Platform 开箱即用地提供基于 regex 和 BM25 的搜索工具,但你也可以使用 embedding 或其他策略实现自定义搜索工具。

何时使用 Tool Search Tool

像任何架构决策一样,启用 Tool Search Tool 涉及权衡。该功能在工具调用之前添加了搜索步骤,因此当 context 节省和准确性改进超过额外延迟时,它提供最佳 ROI。

使用场景:

收益较少的场景:

Programmatic Tool Calling

挑战

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

我们的解决方案

Programmatic Tool Calling 使 Claude 能够通过代码而不是通过单独的 API 往返来编排工具。Claude 不是一次请求一个工具并将每个结果返回到其 context,而是编写调用多个工具、处理其输出并控制哪些信息实际进入其 context window 的代码。

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

示例:预算合规检查

考虑一个常见的业务任务:“哪些团队成员超出了他们的第三季度差旅预算?”

你有三个可用工具:

传统方法:

使用 Programmatic Tool Calling:

每个工具结果不是返回到 Claude,而是 Claude 编写一个编排整个工作流的 Python 脚本。该脚本在 Code Execution 工具(沙盒环境)中运行,当它需要来自你的工具的结果时暂停。当你通过 API 返回工具结果时,它们由脚本处理而不是被模型消耗。脚本继续执行,Claude 只看到最终输出。

Programmatic tool calling 流程

Programmatic Tool Calling 使 Claude 能够通过代码而不是通过单独的 API 往返来编排工具,允许并行工具执行。

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

team = await get_team_members("engineering")

# 为每个唯一级别获取预算
levels = list(set(m["level"] for m in team))
budget_results = await asyncio.gather(*[
    get_budget_by_level(level) for level in levels
])

# 创建查找字典: {"junior": budget1, "senior": budget2, ...}
budgets = {level: budget for level, budget in zip(levels, budget_results)}

# 并行获取所有费用
expenses = await asyncio.gather(*[
    get_expenses(m["id"], "Q3") for m in team
])

# 查找超出差旅预算的员工
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 的 context 只接收最终结果:超出预算的两三个人。2,000+ 行项目、中间总和和预算查找不会影响 Claude 的 context,将消耗从 200KB 原始费用数据减少到仅 1KB 结果。

效率提升是显著的:

生产工作流涉及混乱的数据、条件逻辑和需要扩展的操作。Programmatic Tool Calling 让 Claude 以编程方式处理这种复杂性,同时将其重点放在可操作的结果上,而不是原始数据处理上。

Programmatic Tool Calling 如何工作

1. 标记工具为可从代码调用

将 code_execution 添加到工具中,并设置 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"] // 选择加入 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..." // 上面的代码示例
  }
}

3. 工具执行而不命中 Claude 的 context

当代码调用 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"
  }
}

你提供结果,该结果在 Code Execution 环境中处理,而不是在 Claude 的 context 中。对于代码中的每次工具调用,此请求-响应周期重复。

4. 仅最终输出进入 context

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

{
  "type": "code_execution_tool_result",
  "tool_use_id": "srvtoolu_abc",
  "content": {
    "stdout": "[{\"name\": \"Alice\", \"spent\": 12500, \"limit\": 10000}...]"
  }
}

这就是 Claude 看到的全部,而不是沿途处理的 2000+ 费用行项目。

何时使用 Programmatic Tool Calling

Programmatic Tool Calling 在你的工作流中添加了一个代码执行步骤。当 token 节省、延迟改进和准确性提升显著时,这种额外开销是值得的。

最有益的场景:

收益较少的场景:

Tool Use Examples

挑战

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"]
  }
}

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

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

我们的解决方案

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

{
    "name": "create_ticket",
    "input_schema": { /* 与上面相同的 schema */ },
    "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 学习:

在我们自己的内部测试中,Tool Use Examples 将复杂参数处理的准确性从 72% 提高到 90%。

何时使用 Tool Use Examples

Tool Use Examples 向你的工具定义添加 token,因此当准确性改进超过额外成本时,它们最有价值。

最有益的场景:

收益较少的场景:

最佳实践

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

战略性地分层功能

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

这种专注的方法让你解决限制 Agent 性能的特定约束,而不是预先添加复杂性。

然后根据需要分层添加其他功能。它们是互补的:Tool Search Tool 确保找到正确的工具,Programmatic Tool Calling 确保高效执行,Tool Use Examples 确保正确调用。

设置 Tool Search Tool 以实现更好的发现

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

// 好
{
    "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."
}

// 不好
{
    "name": "query_db_orders",
    "description": "Execute order query"
}

添加 system prompt 指导,以便 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.

始终加载你最常用的三到五个工具,延迟其余工具。这平衡了常见操作的即时访问与其他所有内容的按需发现。

设置 Programmatic Tool Calling 以实现正确执行

由于 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"
}

查看下面受益于程序化编排的选择加入工具:

设置 Tool Use Examples 以实现参数准确性

为行为清晰度制作示例:

入门

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

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"},
        # 你的工具,带有 defer_loading、allowed_callers 和 input_examples
    ]
)

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

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

我们很高兴看到你构建的内容。