3.5 高级特性:程序化工具调用

3.5.1 什么是程序化工具调用?

在标准的工具使用模式中,Claude 扮演的是一个“调度员”:它输出指令,代码执行指令。虽然这种模式简单清晰,但在面对复杂任务时,它通过 HTTP 请求往返的“乒乓”效应会导致显著的延迟。

2025 年,Anthropic 引入了 程序化工具调用。这是一种范式转变:Claude 不再仅仅输出单一的 JSON 指令,而是能够编写并在安全的沙箱容器中执行 Python 代码脚本。这使得 Claude 能够通过代码逻辑(循环、判断、变量传递)一次性编排多个工具调用,甚至直接在沙箱中处理数据。

支持的模型

程序化工具调用目前支持以下模型(均使用 code_execution_20260120 工具类型):

模型
说明

claude-opus-4-6

Opus 最新版

claude-sonnet-4-6

Sonnet 最新版

claude-sonnet-4-5-20250929

Sonnet 4.5

claude-opus-4-5-20251101

Opus 4.5

该功能通过 Claude API 和 Microsoft Foundry 提供。

3.5.2 架构对比:打破“乒乓”效应

以下通过一个场景来对比两种模式:“获取系统中所有活跃用户的名单,并为每个人生成一份月度报表。”

传统模式

  1. Claude: get_active_users()

  2. App: 返回 100 个用户的 JSON List(消耗大量 Token)。

  3. Claude: generate_report(user_id=1)

  4. App: 返回结果。

  5. Claude: generate_report(user_id=2)

  6. ... (重复100次)

由于上下文窗口 (Context Window) 限制和网络延迟,这种任务在传统模式下几乎不可行。

程序化模式

  1. Claude: 生成并执行如下 Python 代码:

  2. App/Container: 执行整段代码。

  3. App: 仅返回最终的一句话结果。

优势总结

  • 极低延迟:将 100 次网络往返压缩为 1 次。

  • 节省 Token:中间数据(如那 100 个用户的详细信息)在代码空间中流转,无需进入 LLM 的上下文窗口。程序化调用的工具结果 不计入 输入/输出 Token——只有最终代码执行结果和 Claude 的回复才计费。

  • 逻辑完备:支持 if-elsefor 循环和异常处理。

[!TIP] Token 效率:例如,直接调用 10 个工具大约消耗 10 倍于程序化调用后再返回摘要的 Token 量。

3.5.3 配置与启用

要启用此功能,需要告知 Claude 哪些工具允许被代码调用。

allowed_callers 字段

在定义工具 Schema 时,新增 allowed_callers 属性:

allowed_callers 的可选值:

含义

["direct"]

仅允许 Claude 标准模式调用(默认值)

["code_execution_20260120"]

仅允许从代码执行环境中调用

["direct", "code_execution_20260120"]

两种模式均可

[!TIP] 建议为每个工具只选择 ['direct']['code_execution_20260120'] 其中之一,这样能给 Claude 提供更明确的使用指引。

caller 响应字段

每个 tool_use 响应块都包含一个 caller 字段,标识该工具是如何被调用的:

这对于在应用层区分处理直接调用与程序化调用非常有用。

容器环境

当 Claude 决定使用程序化工具时,它不仅会生成 tool_use,还会请求一个 code_execution 环境。

  • 生命周期:每个 Session 默认创建一个新容器,并在闲置约 4.5 分钟后销毁。

  • 状态保持:通过传递 container_id,可以让 Claude 在后续对话中访问之前定义的变量(如 pd.DataFrame)。

  • 超时监控:当容器等待工具结果时,必须在容器过期前响应。可通过 expires_at 字段监控剩余时间。如果容器过期,Claude 可能会将该工具调用视为超时并重试。

3.5.4 高级模式

程序化调用支持多种强大的代码模式,以下是典型场景。

批量处理

此模式将 N 次模型往返减少为 1 次,且大量中间数据无需进入上下文窗口。

提前终止

条件选择工具

数据过滤

3.5.5 设计适合程序化调用的工具

程序化调用的工具设计理念与传统模式有所不同。

  • 返回结构化数据:工具最好返回 JSON 对象、列表或 Pandas DataFrame 兼容的数据,方便代码处理。避免返回“自然语言描述”。

    • Bad: “张三的年龄是30岁。”

    • Good: {"name": "Zhang San", "age": 30}

  • 提供详细的输出描述:由于 Claude 会在代码中反序列化工具结果,请清楚记录返回格式(JSON 结构、字段类型等)。

  • 原子化 (Atomic):工具功能应尽量单一。组合逻辑交给 Claude 写代码去完成。

  • 批量接口:虽然循环调用很快,但提供 batch_get_users([ids]) 这样的批量接口依然是性能优化的首选。

  • 保持响应简洁:仅返回必要数据,减少处理开销。

3.5.6 工具学习 (Tool Learning / Few-Shot)

对于极其复杂或非直观的工具,仅靠 description 可能不够。可以通过 Few-Shot Examples(少样本示例) 来“教会” Claude 如何编写正确的调用代码。

Anthropic 推荐使用 XML 格式提供示例:

将这部分内容包含在 system prompt 中,能显著提高一次成功率。

3.5.7 限制与注意事项

尽管功能强大,但目前仍存在边界:

功能不兼容项

限制
说明

结构化输出

设置了 strict: true 的工具不支持程序化调用

工具选择

无法通过 tool_choice 强制触发程序化调用

并行工具

disable_parallel_tool_use: true 与程序化调用不兼容

MCP 工具

通过 MCP Connector 提供的工具暂不支持程序化调用

响应格式限制

当回复程序化工具调用时,响应消息 必须仅包含 tool_result,不能夹带任何文本内容。这是一个严格的格式要求——如果包含了额外文本,会导致解析错误。

[!IMPORTANT] 此限制仅适用于程序化(代码执行)工具调用的回复。对于常规的客户端工具调用,仍然可以在 tool_result 之后包含文本内容。

安全注意事项

  • 虽然运行在沙箱中,但让 AI 写代码并执行总是伴随风险。建议对代码容器进行网络隔离,仅允许其访问白名单内的 API。

  • 工具结果以字符串形式返回,可能包含代码片段或可执行命令。如果工具返回来自外部来源的数据,需注意代码注入风险。

3.5.8 何时使用程序化调用

适合场景
不太适合场景

处理大数据集,仅需聚合/摘要

单次工具调用且返回简单

涉及 3 个以上相互依赖的工具调用

需要即时用户反馈的工具

需要对工具结果进行过滤、排序或转换

极快操作(代码执行开销大于收益)

中间数据不应影响 Claude 推理的场景

-

跨多项目并行操作(如检查 50 个端点)

-

3.5.9 最佳实践清单

维度
建议

工具粒度

保持工具简单、原子化。避免“万能工具”。

数据格式

始终针对“机器读取”而非“人类阅读”优化工具返回值。

输出描述

详细记录工具返回的 JSON 结构和字段类型。

错误处理

在工具内部捕获异常并返回清晰的错误 JSON,让 Claude 的代码能 try-catch

容器复用

发起多个相关请求时复用容器以保持状态。

监控

记录 Claude 生成的所有代码,这对于调试和安全审计至关重要。


当工具数量增长到数百个时,如何让 Claude 找到正确的工具?需要“工具搜索”。

➡️ 工具搜索与大规模管理

最后更新于