Anthropic 宣布推出三项新的测试版功能,使 Claude 能够动态发现、学习和执行工具。这些功能标志着 AI 智能体开发迈入了新阶段。

AI 智能体发展的新方向

未来的 AI 智能体将能够无缝操作成百上千个工具。想象一个集成了 git 操作、文件处理、包管理器、测试框架和部署流程的 IDE 助手,或是一个能同时连接 Slack、GitHub、Google Drive、Jira、公司数据库以及数十个 MCP 服务器的运营协调系统。

要打造真正有效的智能体系统,关键在于让它们能够灵活使用海量工具库,而无需将所有工具定义都预先加载到上下文中。据 Anthropic 此前关于使用 MCP 进行代码执行的博客文章显示,工具结果和定义有时会在智能体处理请求之前就消耗掉超过 50000 个 Token。理想的解决方案是让智能体能够按需发现和加载工具,只保留当前任务真正需要的部分。

除此之外,智能体还需要具备从代码中调用工具的能力。传统的自然语言工具调用方式要求每次调用都进行一次完整的推理过程,中间结果会不断堆积在上下文中,无论这些结果是否真正有用。相比之下,代码天然适合处理编排逻辑,循环、条件判断、数据转换等操作都能更清晰地表达。智能体需要根据具体任务灵活选择使用代码执行还是推理。

另一个重要需求是让智能体能够从实例中学习正确的工具使用方法,而不仅仅依赖抽象的模式定义。JSON 模式虽然能定义结构上的有效性,但无法传达使用习惯。何时该包含可选参数、哪些参数组合才合理,或者 API 遵循什么样的约定。

为解决这些挑战,Anthropic 发布了三项功能

  • 工具搜索工具(Tool Search Tool):让 Claude 能够使用搜索功能访问数千个工具,而不会占用上下文窗口
  • 编程式工具调用(Programmatic Tool Calling):允许 Claude 在代码执行环境中调用工具,大幅降低对上下文窗口的占用
  • 工具使用示例(Tool Use Examples):提供了一套通用标准,用于演示如何高效使用特定工具

Anthropic 在内部测试中发现,这些功能帮助团队实现了许多用传统工具使用模式难以完成的项目。例如,Claude for Excel 就利用编程式工具调用来读取和修改包含数千行数据的电子表格,完全没有造成上下文窗口过载的问题。

基于这些实践经验,Anthropic 认为这些功能将为开发者使用 Claude 构建应用开辟全新的可能性。

工具搜索工具:按需发现所需功能

面临的挑战

MCP 工具定义虽然提供了重要的上下文信息,但随着连接服务器数量的增加,Token 消耗会迅速累积。以一个包含五个服务器的典型配置为例:

  • GitHub:35 个工具(约 26K Token)
  • Slack:11 个工具(约 21K Token)
  • Sentry:5 个工具(约 3K Token)
  • Grafana:5 个工具(约 3K Token)
  • Splunk:2 个工具(约 2K Token)

这样一来,58 个工具在对话开始前就已经消耗了约 55K Token。如果再加入 Jira(单独就需要约 17K Token)等更多服务器,Token 开销很快就会突破 100K。Anthropic 团队在优化前曾观察到工具定义消耗高达 134K Token 的情况。

Token 成本还不是唯一的问题。实际应用中最常见的故障是工具选择错误和参数使用不当,特别是当工具名称相似时,比如 notification-send-usernotification-send-channel 就很容易混淆。

Anthropic 的解决方案

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

工具搜索”工具与传统方法的上下文使用对比图

对比数据显示,“工具搜索” 工具能保留 191300 个 Token 的上下文空间,而传统方法只能保留 122800 个 Token。

传统方法的问题:

  • 预先加载所有工具定义(50+ MCP 工具消耗约 72K Token)
  • 对话历史和系统提示争夺剩余空间
  • 总上下文消耗:工作开始前就已使用约 77K Token

“工具搜索” 工具的优势:

  • 预先加载的仅有工具搜索工具本身(约 500 Token)
  • 按需发现所需工具(3-5 个相关工具,约 3K Token)
  • 总上下文消耗:约 8.7K Token,保留了 95% 的上下文窗口

这意味着 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.createPullRequestgithub.listIssues,而不会加载来自 Slack、Jira 和 Google Drive 的其他 50 多个工具。

通过这种方式,Claude 既能访问完整的工具库,又只需为实际使用的工具付出 Token 成本。

实现示例:

{
  "tools": [
    // 包含 “工具搜索” 工具(支持正则表达式、BM25 或自定义方式)
    {"type": "tool_search_tool_regex_20251119", "name": "tool_search_tool_regex"},

    // 将工具标记为按需发现
    {
      "name": "github.createPullRequest",
      "description": "创建拉取请求",
      "input_schema": {...},
      "defer_loading": true
    }
    // ... 更多延迟加载的工具,都设置 defer_loading: true
  ]
}

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

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

Claude 开发者平台默认提供基于正则表达式和 BM25 的搜索工具,开发者也可以使用嵌入向量或其他策略实现自定义搜索工具。

适用场景

与所有架构决策一样,启用 “工具搜索” 工具需要权衡利弊。该功能在工具调用前增加了搜索步骤,因此只有当上下文节省和准确性提升超过额外延迟时,才能带来最佳投资回报。

推荐使用的情况:

  • 工具定义消耗超过 10K Token
  • 经常出现工具选择准确性问题
  • 构建包含多个服务器的 MCP 驱动系统
  • 可用工具数量超过 10 个

不太必要的情况:

  • 工具库规模较小(少于 10 个工具)
  • 所有工具在每次会话中都频繁使用
  • 工具定义非常简洁

编程式工具调用:智能编排复杂工作流

传统方式的局限性

随着工作流复杂度的提升,传统工具调用会产生两个根本性问题:

1. 中间结果导致的上下文污染:当 Claude 分析 10MB 的日志文件查找错误模式时,整个文件都会进入上下文窗口,即使 Claude 实际只需要错误频率的统计摘要。在跨多个数据表获取客户信息时,每一条记录都会累积在上下文中,无论是否与任务相关。这些中间结果大量消耗 Token 预算,甚至可能将重要信息完全挤出上下文窗口。

2. 推理开销和手动数据综合:每次工具调用都需要完整的模型推理过程。接收到结果后,Claude 必须通过自然语言处理来"审视"数据、提取相关信息、推理各部分如何组合,并决定下一步操作。一个包含五步的工具工作流就意味着五次推理过程,外加 Claude 解析每个结果、比较数值和综合结论的时间。这种方式既缓慢又容易出错。

Anthropic 的创新方案

编程式工具调用让 Claude 能够通过代码而非单次 API 调用来编排工具。Claude 不再逐个请求工具并将每个结果返回到上下文中,而是编写能够调用多个工具、处理输出并控制哪些信息真正进入上下文窗口的代码。

Claude 本身就擅长编写代码,让它用 Python 而非自然语言来表达编排逻辑,能够获得更可靠、更精确的控制流程。循环、条件判断、数据转换和错误处理都在代码中明确表达,而非隐含在 Claude 的推理过程中。

实际应用案例:预算合规检查

以一个常见的企业任务为例:"找出第三季度差旅费用超出预算的团队成员?"

假设有三个可用工具:

  • get_team_members(department) - 返回包含 ID 和职级的团队成员列表
  • get_expenses(user_id, quarter) - 返回用户的费用明细
  • get_budget_by_level(level) - 返回对应职级的预算限额

传统方法的处理流程:

  1. 获取团队成员信息 → 返回 20 人
  2. 逐个获取每人的第三季度费用 → 20 次工具调用,每次返回 50-100 条明细(机票、酒店、餐饮、发票)
  3. 按职级获取预算限额
  4. 所有数据都进入 Claude 的上下文:2,000+ 条费用明细(超过 50 KB)
  5. Claude 手动计算每个人的总费用,查询对应预算,将费用与限额对比
  6. 需要多次往返模型,上下文消耗巨大

采用编程式工具调用的处理方式:

Claude 不再让每个工具结果都返回到自身,而是编写一个 Python 脚本来编排整个工作流。这个脚本在代码执行工具(一个沙盒环境)中运行,需要工具结果时会暂停执行。当开发者通过 API 返回工具结果时,这些结果由脚本处理而非模型消费。脚本继续执行,Claude 最终只看到最后的输出结果。

编程式工具调用允许并行工具执行的示意图

编程式工具调用使 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 的上下文中只会接收到最终结果:超出预算的两三个人的信息。那 2000 多条明细、中间的求和计算、预算查询都不会影响 Claude 的上下文,Token 消耗从 200KB 的原始费用数据降低到仅 1KB 的结果数据。

效率提升相当显著:

  • 节省 Token:通过将中间结果排除在 Claude 的上下文之外,编程式工具调用大幅降低了 Token 消耗。在复杂研究任务中,平均 Token 使用量从 43588 降至 27297,降幅达 37%。
  • 延迟降低:每次 API 往返都需要进行模型推理(耗时从数百毫秒到数秒不等)。当 Claude 在单个代码块中编排 20 多次工具调用时,可以省去 19 次以上的推理过程。API 直接处理工具执行,无需每次都返回模型。
  • 准确性提高:通过编写明确的编排逻辑,Claude 在处理多个工具结果时比使用自然语言方式出错更少。内部知识检索准确率从 25.6% 提升至 28.5%;GIA 基准测试从 46.5% 提升至 51.2%。

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

技术实现细节

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

将 code_execution 添加到工具配置中,并设置 allowed_callers 来指定哪些工具可以通过编程方式执行:

{
  "tools": [
    {
      "type": "code_execution_20250825",
      "name": "code_execution"
    },
    {
      "name": "get_team_members",
      "description": "获取部门的所有成员...",
      "input_schema": {...},
      "allowed_callers": ["code_execution_20250825"] # 启用编程式工具调用
    },
    {
      "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 的上下文

当代码调用 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.levelescalation.sla_hours 与优先级之间是什么关系?

这些模糊之处可能导致工具调用格式错误和参数使用不一致。

Anthropic 提供的解决方案

工具使用示例允许开发者直接在工具定义中提供具体的调用样例。这样不仅仅依赖抽象的模式,还能向 Claude 展示实际的使用模式:

{
    "name": "create_ticket",
    "input_schema": { /* 与上面相同的模式 */ },
    "input_examples": [
      {
        "title": "登录页面返回 500 错误",
        "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": "添加深色模式支持",
        "labels": ["feature-request", "ui"],
        "reporter": {
          "id": "USR-67890",
          "name": "Alex Chen"
        }
      },
      {
        "title": "更新 API 文档"
      }
    ]
  }

通过这三个示例,Claude 能够学到:

  • 格式约定:日期使用 YYYY-MM-DD 格式,用户 ID 采用 USR-XXXXX 模式,标签使用 kebab-case 命名
  • 嵌套结构模式:如何正确构建包含嵌套 contact 对象的 reporter 对象
  • 可选参数的使用规律:紧急 bug 需要完整的联系信息和紧急升级配置及严格的 SLA。功能请求只需要 reporter 信息但不需要联系方式和升级配置。内部任务只需要标题

Anthropic 的内部测试数据显示,工具使用示例将复杂参数处理的准确率从 72% 提升到了 90%。

何时使用工具使用示例

工具使用示例会增加工具定义的 Token 消耗,因此只有当准确性提升超过额外成本时才最有价值。

最适合使用的场景:

  • 复杂的嵌套结构,结构上有效的 JSON 不等于正确的使用方式
  • 包含大量可选参数且参数包含模式很重要的工具
  • 具有模式无法表达的特定领域约定的 API
  • 功能相似的工具,示例能帮助明确该使用哪一个(如 create_ticket vs create_incident

不太必要的场景:

  • 用法显而易见的简单单参数工具
  • Claude 已经熟悉的标准格式,如 URL 或电子邮件
  • 更适合通过 JSON Schema 约束处理的验证问题

最佳实践指南

构建能够在真实世界中执行操作的智能体,意味着需要同时处理规模、复杂性和精确度。这三个功能协同工作,分别解决工具使用工作流中的不同瓶颈。以下是如何有效组合使用它们的建议。

分层应用各项功能

并非每个智能体都需要在每个任务中使用所有三项功能。应该从最大的瓶颈入手:

  • 工具定义导致上下文膨胀 → 使用工具搜索工具
  • 大量中间结果污染上下文 → 使用编程式工具调用
  • 参数错误和调用格式问题 → 使用工具使用示例

这种聚焦的方法能够针对性地解决限制智能体性能的具体约束,而不是一开始就增加系统复杂度。

然后根据需要逐步添加其他功能。这些功能是互补的:工具搜索工具确保找到正确的工具,编程式工具调用确保高效执行,工具使用示例确保正确调用。

优化工具搜索配置

工具搜索基于名称和描述进行匹配,因此清晰、描述性的定义能够提高发现准确性。

// 良好示例
{
    "name": "search_customer_orders",
    "description": "根据日期范围、状态或总金额搜索客户订单。返回订单详细信息,包括商品、运输和支付信息。"
}

// 不良示例
{
    "name": "query_db_orders",
    "description": "执行订单查询"
}

在系统提示中添加指导信息,让 Claude 了解可用的工具类别:

你可以使用 Slack 消息发送、Google Drive 文件管理、Jira 工单跟踪和 GitHub 仓库操作等工具。使用工具搜索功能来查找具体的能力。

保持三到五个最常用的工具始终处于加载状态,其余工具延迟加载。这样能在常用操作的即时访问和其他工具的按需发现之间取得平衡。

为编程式调用准备工具文档

由于 Claude 需要编写代码来解析工具输出,因此清晰记录返回格式至关重要。这有助于 Claude 编写正确的解析逻辑:

{
    "name": "get_orders",
    "description": "检索客户的订单信息。
返回值:
    订单对象列表,每个对象包含:
    - id (str):订单标识符
    - total (float):订单总额(美元)
    - status (str):状态值,可选 'pending'、'shipped'、'delivered'
    - items (list):商品数组,格式为 {sku, quantity, price}
    - created_at (str):ISO 8601 格式时间戳"
}

以下类型的工具特别适合通过编程方式编排:

  • 可以并行运行的工具(彼此独立的操作)
  • 可以安全重试的操作(幂等性操作)

精心设计工具使用示例

为提高行为清晰度,示例应该遵循以下原则:

  • 使用真实数据(真实的城市名称、合理的价格,而非"string"或"value"等占位符)
  • 展示多样化的使用模式,从最简配置到完整配置
  • 保持简洁:每个工具提供 1-5 个示例
  • 聚焦于模糊之处(仅在模式定义无法清楚表达正确用法时添加示例)

如何开始使用

这些功能目前处于测试阶段。要启用它们,需要添加 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"},
        # 你的工具定义,包含 defer_loading、allowed_callers 和 input_examples 配置
    ]
)

详细的 API 文档和 SDK 示例,可以参考以下资源:

这些功能将工具使用从简单的函数调用提升到了智能编排的层面。随着智能体需要处理跨越数十个工具和大规模数据集的复杂工作流,动态发现、高效执行和可靠调用正在成为基础能力。

原文链接

Introducing advanced tool use on the Claude Developer Platform