程序化工具调用允许 Claude 在代码执行容器中编写代码以编程方式调用您的工具,而不是需要为每次工具调用进行往返。这减少了多工具工作流的延迟,并通过允许 Claude 在数据到达模型的上下文窗口之前过滤或处理数据来降低令牌消耗。
程序化工具调用在以下模型上可用:
| 模型 | 工具版本 |
|---|---|
Claude Opus 4.5 (claude-opus-4-5-20251101) | code_execution_20250825 |
Claude Sonnet 4.5 (claude-sonnet-4-5-20250929) | code_execution_20250825 |
程序化工具调用可通过 Claude API 和 Microsoft Foundry 获得。
这是一个简单的示例,其中 Claude 以编程方式多次查询数据库并聚合结果:
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "anthropic-beta: advanced-tool-use-2025-11-20" \
--header "content-type: application/json" \
--data '{
"model": "claude-sonnet-4-5",
"max_tokens": 4096,
"messages": [
{
"role": "user",
"content": "Query sales data for the West, East, and Central regions, then tell me which region had the highest revenue"
}
],
"tools": [
{
"type": "code_execution_20250825",
"name": "code_execution"
},
{
"name": "query_database",
"description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
"input_schema": {
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "SQL query to execute"
}
},
"required": ["sql"]
},
"allowed_callers": ["code_execution_20250825"]
}
]
}'当您配置一个工具可从代码执行调用,并且 Claude 决定使用该工具时:
tool_use 块这种方法特别适用于:
自定义工具被转换为异步 Python 函数以支持并行工具调用。当 Claude 编写调用您的工具的代码时,它使用 await(例如,result = await query_database("<sql>"))并自动包含适当的异步包装函数。
为了清晰起见,本文档中的代码示例中省略了异步包装。
allowed_callers 字段allowed_callers 字段指定哪些上下文可以调用工具:
{
"name": "query_database",
"description": "Execute a SQL query against the database",
"input_schema": {...},
"allowed_callers": ["code_execution_20250825"]
}可能的值:
["direct"] - 仅 Claude 可以直接调用此工具(如果省略则为默认值)["code_execution_20250825"] - 仅可从代码执行中调用["direct", "code_execution_20250825"] - 可直接调用和从代码执行中调用我们建议为每个工具选择 ["direct"] 或 ["code_execution_20250825"],而不是同时启用两者,因为这为 Claude 提供了更清晰的指导,说明如何最好地使用该工具。
caller 字段每个工具使用块都包含一个 caller 字段,指示它是如何被调用的:
直接调用(传统工具使用):
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": {"sql": "<sql>"},
"caller": {"type": "direct"}
}程序化调用:
{
"type": "tool_use",
"id": "toolu_xyz789",
"name": "query_database",
"input": {"sql": "<sql>"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_abc123"
}
}tool_id 引用进行程序化调用的代码执行工具。
程序化工具调用使用与代码执行相同的容器:
container 字段在响应中返回当工具以编程方式调用并且容器正在等待您的工具结果时,您必须在容器过期之前响应。监视 expires_at 字段。如果容器过期,Claude 可能会将工具调用视为超时并重试它。
以下是完整的程序化工具调用流程的工作方式:
发送包含代码执行和允许程序化调用的工具的请求。要启用程序化调用,请将 allowed_callers 字段添加到您的工具定义中。
在工具描述中提供工具输出格式的详细描述。如果您指定工具返回 JSON,Claude 将尝试在代码中反序列化和处理结果。您提供的关于输出架构的细节越多,Claude 就能更好地以编程方式处理响应。
response = client.beta.messages.create(
model="claude-sonnet-4-5",
betas=["advanced-tool-use-2025-11-20"],
max_tokens=4096,
messages=[{
"role": "user",
"content": "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"
}],
tools=[
{
"type": "code_execution_20250825",
"name": "code_execution"
},
{
"name": "query_database",
"description": "Execute a SQL query against the sales database. Returns a list of rows as JSON objects.",
"input_schema": {...},
"allowed_callers": ["code_execution_20250825"]
}
]
)Claude 编写调用您的工具的代码。API 暂停并返回:
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll query the purchase history and analyze the results."
},
{
"type": "server_tool_use",
"id": "srvtoolu_abc123",
"name": "code_execution",
"input": {
"code": "results = await query_database('<sql>')\ntop_customers = sorted(results, key=lambda x: x['revenue'], reverse=True)[:5]\nprint(f'Top 5 customers: {top_customers}')"
}
},
{
"type": "tool_use",
"id": "toolu_def456",
"name": "query_database",
"input": {"sql": "<sql>"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_abc123"
}
}
],
"container": {
"id": "container_xyz789",
"expires_at": "2025-01-15T14:30:00Z"
},
"stop_reason": "tool_use"
}包括完整的对话历史加上您的工具结果:
response = client.beta.messages.create(
model="claude-sonnet-4-5",
betas=["advanced-tool-use-2025-11-20"],
max_tokens=4096,
container="container_xyz789", # Reuse the container
messages=[
{"role": "user", "content": "Query customer purchase history from the last quarter and identify our top 5 customers by revenue"},
{
"role": "assistant",
"content": [
{"type": "text", "text": "I'll query the purchase history and analyze the results."},
{
"type": "server_tool_use",
"id": "srvtoolu_abc123",
"name": "code_execution",
"input": {"code": "..."}
},
{
"type": "tool_use",
"id": "toolu_def456",
"name": "query_database",
"input": {"sql": "<sql>"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_abc123"
}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_def456",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}, {\"customer_id\": \"C2\", \"revenue\": 38000}, ...]"
}
]
}
],
tools=[...]
)代码执行继续并处理结果。如果需要额外的工具调用,重复步骤 3,直到所有工具调用都得到满足。
一旦代码执行完成,Claude 提供最终响应:
{
"content": [
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "Top 5 customers by revenue:\n1. Customer C1: $45,000\n2. Customer C2: $38,000\n3. Customer C5: $32,000\n4. Customer C8: $28,500\n5. Customer C3: $24,000",
"stderr": "",
"return_code": 0,
"content": []
}
},
{
"type": "text",
"text": "I've analyzed the purchase history from last quarter. Your top 5 customers generated $167,500 in total revenue, with Customer C1 leading at $45,000."
}
],
"stop_reason": "end_turn"
}Claude 可以编写代码来高效处理多个项目:
# async wrapper omitted for clarity
regions = ["West", "East", "Central", "North", "South"]
results = {}
for region in regions:
data = await query_database(f"<sql for {region}>")
results[region] = sum(row["revenue"] for row in data)
# Process results programmatically
top_region = max(results.items(), key=lambda x: x[1])
print(f"Top region: {top_region[0]} with ${top_region[1]:,} in revenue")这种模式:
Claude 可以在满足成功标准后立即停止处理:
# async wrapper omitted for clarity
endpoints = ["us-east", "eu-west", "apac"]
for endpoint in endpoints:
status = await check_health(endpoint)
if status == "healthy":
print(f"Found healthy endpoint: {endpoint}")
break # Stop early, don't check remaining# async wrapper omitted for clarity
file_info = await get_file_info(path)
if file_info["size"] < 10000:
content = await read_full_file(path)
else:
content = await read_file_summary(path)
print(content)# async wrapper omitted for clarity
logs = await fetch_logs(server_id)
errors = [log for log in logs if "ERROR" in log]
print(f"Found {len(errors)} errors")
for error in errors[-10:]: # Only return last 10 errors
print(error)当代码执行调用工具时:
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": {"sql": "<sql>"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_xyz789"
}
}您的工具结果被传递回运行的代码:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000, \"orders\": 23}, {\"customer_id\": \"C2\", \"revenue\": 38000, \"orders\": 18}, ...]"
}
]
}当所有工具调用都得到满足且代码完成时:
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_xyz789",
"content": {
"type": "code_execution_result",
"stdout": "Analysis complete. Top 5 customers identified from 847 total records.",
"stderr": "",
"return_code": 0,
"content": []
}
}| 错误 | 描述 | 解决方案 |
|---|---|---|
invalid_tool_input | 工具输入与架构不匹配 | 验证您的工具的 input_schema |
tool_not_allowed | 工具不允许请求的调用者类型 | 检查 allowed_callers 是否包含正确的上下文 |
missing_beta_header | 未提供 PTC 测试版标头 | 将两个测试版标头添加到您的请求中 |
如果您的工具响应时间过长,代码执行将收到 TimeoutError。Claude 在 stderr 中看到这一点,通常会重试:
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "",
"stderr": "TimeoutError: Calling tool ['query_database'] timed out.",
"return_code": 0,
"content": []
}
}为了防止超时:
expires_at 字段如果您的工具返回错误:
# Provide error information in the tool result
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "Error: Query timeout - table lock exceeded 30 seconds"
}Claude 的代码将收到此错误并可以适当地处理它。
strict: true 的工具不支持程序化调用tool_choice 强制程序化调用特定工具disable_parallel_tool_use: true 不支持程序化调用以下工具目前无法以编程方式调用,但可能在未来版本中添加支持:
在响应程序化工具调用时,有严格的格式要求:
仅工具结果响应:如果有待处理的程序化工具调用等待结果,您的响应消息必须仅包含 tool_result 块。您不能包含任何文本内容,即使在工具结果之后也不行。
// ❌ 无效 - 在响应程序化工具调用时不能包含文本
{
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": "toolu_01", "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"},
{"type": "text", "text": "What should I do next?"} // This will cause an error
]
}
// ✅ 有效 - 仅在响应程序化工具调用时使用工具结果
{
"role": "user",
"content": [
{"type": "tool_result", "tool_use_id": "toolu_01", "content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"}
]
}此限制仅在响应程序化(代码执行)工具调用时适用。对于常规客户端工具调用,您可以在工具结果后包含文本内容。
程序化工具调用受与常规工具调用相同的速率限制。来自代码执行的每个工具调用都计为单独的调用。
在实现将以编程方式调用的自定义工具时:
程序化工具调用可以显著降低令牌消耗:
例如,直接调用 10 个工具使用的令牌数约为以编程方式调用它们并返回摘要的 10 倍。
程序化工具调用使用与代码执行相同的定价。有关详细信息,请参阅代码执行定价。
程序化工具调用的令牌计数:来自程序化调用的工具结果不计入您的输入/输出令牌使用。仅最终代码执行结果和 Claude 的响应计数。
良好的用例:
不太理想的用例:
"工具不允许"错误
"allowed_callers": ["code_execution_20250825"]容器过期
expires_at 字段测试版标头问题
"advanced-tool-use-2025-11-20"工具结果解析不正确
caller 字段以确认程序化调用Claude 的训练包括对代码的广泛接触,使其能够有效地推理和链接函数调用。当工具在代码执行环境中作为可调用函数呈现时,Claude 可以利用这一优势来:
这种方法支持使用传统工具使用会不切实际的工作流——例如处理超过 1M 令牌的文件——通过允许 Claude 以编程方式处理数据,而不是将所有内容加载到对话上下文中。
程序化工具调用是一个可以在 Anthropic 的托管代码执行之外实现的可泛化模式。以下是方法概述:
为 Claude 提供代码执行工具,并描述该环境中可用的函数。当 Claude 使用代码调用工具时,您的应用程序在定义这些函数的本地执行它。
优点:
缺点:
使用时机:您的应用程序可以安全地执行任意代码,您想要一个简单的解决方案,并且 Anthropic 的托管产品不适合您的需求。
从 Claude 的角度来看相同的方法,但代码在具有安全限制的沙箱容器中运行(例如,无网络出口)。如果您的工具需要外部资源,您需要一个协议来在沙箱外执行工具调用。
优点:
缺点:
使用时机:安全至关重要,Anthropic 的托管解决方案不适合您的要求。
Anthropic 的程序化工具调用是沙箱执行的托管版本,具有为 Claude 调整的固定 Python 环境。Anthropic 处理容器管理、代码执行和安全工具调用通信。
优点:
如果您使用 Claude API,我们建议使用 Anthropic 的托管解决方案。