程序化工具调用允许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就能更好地以编程方式处理响应。
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"
}包含完整的对话历史加上您的工具结果:
代码执行继续并处理结果。如果需要额外的工具调用,重复步骤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的托管解决方案。
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"]
}
]
)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=[...]
)了解Claude工具使用的基础知识。