程式化工具呼叫
程式化工具呼叫允許 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 決定使用該工具時:
- Claude 編寫 Python 程式碼,以函式形式呼叫工具,可能包括多個工具呼叫和前置/後置處理邏輯
- Claude 透過程式碼執行在沙箱容器中執行此程式碼
- 當呼叫工具函式時,程式碼執行暫停,API 傳回
tool_use區塊 - 您提供工具結果,程式碼執行繼續(中間結果不會載入到 Claude 的上下文視窗中)
- 一旦所有程式碼執行完成,Claude 接收最終輸出並繼續處理任務
此方法特別適用於:
- 大型資料處理:在資料到達 Claude 的上下文之前過濾或彙總工具結果
- 多步驟工作流程:通過在工具呼叫之間不進行 Claude 取樣來節省代幣和延遲
- 條件邏輯:根據中間工具結果做出決策
自訂工具被轉換為非同步 Python 函式以支援平行工具呼叫。當 Claude 編寫呼叫您的工具的程式碼時,它使用 await(例如,result = await query_database("<sql>"))並自動包含適當的非同步包裝函式。
為了清晰起見,本文件中的程式碼範例中省略了非同步包裝。
核心概念
allowed_callers 欄位
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 欄位每個工具使用區塊都包含一個 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 參考進行程式化呼叫的程式碼執行工具。
容器生命週期
程式化工具呼叫使用與程式碼執行相同的容器:
- 容器建立:除非您重複使用現有容器,否則為每個工作階段建立新容器
- 過期:容器在大約 4.5 分鐘的不活動後過期(可能會變更)
- 容器 ID:透過
container欄位在回應中傳回 - 重複使用:傳遞容器 ID 以在請求之間維持狀態
當工具以程式方式呼叫且容器正在等待您的工具結果時,您必須在容器過期前回應。監控 expires_at 欄位。如果容器過期,Claude 可能會將工具呼叫視為逾時並重試。
範例工作流程
以下是完整的程式化工具呼叫流程的工作方式:
步驟 1:初始請求
傳送包含程式碼執行和允許程式化呼叫的工具的請求。要啟用程式化呼叫,請將 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"]
}
]
)步驟 2:API 回應與工具呼叫
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:提供工具結果
包含完整的對話歷史記錄加上您的工具結果:
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=[...]
)步驟 4:下一個工具呼叫或完成
程式碼執行繼續並處理結果。如果需要其他工具呼叫,重複步驟 3,直到所有工具呼叫都得到滿足。
步驟 5:最終回應
一旦程式碼執行完成,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")此模式:
- 將模型往返次數從 N(每個區域一次)減少到 1
- 在返回 Claude 之前以程式方式處理大型結果集
- 通過只傳回彙總結論而不是原始資料來節省代幣
提前終止
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不支援程式化呼叫
工具限制
以下工具目前無法以程式方式呼叫,但未來版本可能會新增支援:
- 網路搜尋
- 網路擷取
- 由 MCP 連接器提供的工具
訊息格式限制
在回應程式化工具呼叫時,有嚴格的格式要求:
僅工具結果回應:如果有待處理的程式化工具呼叫等待結果,您的回應訊息必須僅包含 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}]"}
]
}此限制僅適用於回應程式化(程式碼執行)工具呼叫。對於常規客戶端工具呼叫,您可以在工具結果後包含文字內容。
速率限制
程式化工具呼叫受與常規工具呼叫相同的速率限制。來自程式碼執行的每個工具呼叫都計為單獨的呼叫。
在使用前驗證工具結果
實施將以程式方式呼叫的自訂工具時:
- 工具結果作為字串傳回:它們可以包含任何內容,包括程式碼片段或可執行命令,這些可能由執行環境處理。
- 驗證外部工具結果:如果您的工具傳回來自外部來源的資料或接受使用者輸入,請注意如果輸出將被解釋或執行為程式碼時的程式碼注入風險。
代幣效率
程式化工具呼叫可以顯著降低代幣消耗:
- 來自程式化呼叫的工具結果不會新增到 Claude 的上下文中 - 只有最終程式碼輸出
- 中間處理在程式碼中進行 - 過濾、彙總等不消耗模型代幣
- 一個程式碼執行中的多個工具呼叫 - 與單獨的模型轉換相比減少開銷
例如,直接呼叫 10 個工具使用的代幣大約是以程式方式呼叫它們並傳回摘要的 10 倍。
使用和定價
程式化工具呼叫使用與程式碼執行相同的定價。有關詳細資訊,請參閱程式碼執行定價。
程式化工具呼叫的代幣計數:來自程式化呼叫的工具結果不計入您的輸入/輸出代幣使用量。只有最終程式碼執行結果和 Claude 的回應計數。
最佳實踐
工具設計
- 提供詳細的輸出描述:由於 Claude 在程式碼中反序列化工具結果,請清楚記錄格式(JSON 結構、欄位類型等)
- 傳回結構化資料:JSON 或其他易於解析的格式最適合程式化處理
- 保持回應簡潔:只傳回必要的資料以最小化處理開銷
何時使用程式化呼叫
良好的使用案例:
- 處理大型資料集,其中您只需要彙總或摘要
- 具有 3 個以上相依工具呼叫的多步驟工作流程
- 需要過濾、排序或轉換工具結果的操作
- 中間資料不應影響 Claude 推理的任務
- 跨許多項目的平行操作(例如,檢查 50 個端點)
不太理想的使用案例:
- 具有簡單回應的單個工具呼叫
- 需要立即使用者回饋的工具
- 程式碼執行開銷會超過好處的非常快速的操作
效能最佳化
- 重複使用容器,在進行多個相關請求時維持狀態
- 在單個程式碼執行中批次類似操作(如果可能)
疑難排解
常見問題
「工具不允許」錯誤
- 驗證您的工具定義包含
"allowed_callers": ["code_execution_20250825"] - 檢查您是否使用正確的測試版標頭
容器過期
- 確保您在容器的生命週期內回應工具呼叫(約 4.5 分鐘)
- 監控回應中的
expires_at欄位 - 考慮實施更快的工具執行
測試版標頭問題
- 您需要標頭:
"advanced-tool-use-2025-11-20"
工具結果未正確解析
- 確保您的工具傳回 Claude 可以反序列化的字串資料
- 在您的工具描述中提供清晰的輸出格式文件
除錯提示
- 記錄所有工具呼叫和結果以追蹤流程
- 檢查
caller欄位以確認程式化呼叫 - 監控容器 ID 以確保正確重複使用
- 獨立測試工具,然後再啟用程式化呼叫
為什麼程式化工具呼叫有效
Claude 的訓練包括對程式碼的廣泛接觸,使其能夠有效地推理和鏈接函式呼叫。當工具在程式碼執行環境中呈現為可呼叫函式時,Claude 可以利用這一優勢來:
- 自然地推理工具組合:像編寫任何 Python 程式碼一樣自然地鏈接操作和處理相依性
- 有效地處理大型結果:過濾大型工具輸出、提取僅相關資料或在返回摘要到上下文視窗之前將中間結果寫入檔案
- 顯著降低延遲:消除在多步驟工作流程中每個工具呼叫之間重新取樣 Claude 的開銷
此方法啟用了使用傳統工具使用不切實際的工作流程,例如處理超過 1M 代幣的檔案,通過允許 Claude 以程式方式處理資料而不是將所有內容載入對話上下文。
替代實現
程式化工具呼叫是一個可推廣的模式,可以在 Anthropic 的託管程式碼執行之外實現。以下是方法的概述:
客戶端直接執行
為 Claude 提供程式碼執行工具,並描述該環境中可用的函式。當 Claude 使用程式碼呼叫工具時,您的應用程式在定義這些函式的本地執行它。
優點:
- 簡單實施,最少重新架構
- 完全控制環境和指令
缺點:
- 在沙箱外執行不受信任的程式碼
- 工具呼叫可能是程式碼注入的向量
使用時機:您的應用程式可以安全地執行任意程式碼、您想要簡單的解決方案,以及 Anthropic 的託管產品不符合您的需求。
自我管理的沙箱執行
從 Claude 的角度來看相同的方法,但程式碼在具有安全限制的沙箱容器中執行(例如,無網路出口)。如果您的工具需要外部資源,您將需要一個協議來在沙箱外執行工具呼叫。
優點:
- 在您自己的基礎設施上進行安全的程式化工具呼叫
- 完全控制執行環境
缺點:
- 複雜的建置和維護
- 需要管理基礎設施和程序間通訊
使用時機:安全至關重要,Anthropic 的託管解決方案不符合您的要求。
Anthropic 託管執行
Anthropic 的程式化工具呼叫是沙箱執行的託管版本,具有為 Claude 調整的固執 Python 環境。Anthropic 處理容器管理、程式碼執行和安全工具呼叫通訊。
優點:
- 預設安全且安全
- 最少配置即可輕鬆啟用
- 為 Claude 最佳化的環境和指令
如果您使用 Claude API,我們建議使用 Anthropic 的託管解決方案。