„Programmatic tool calling" (programmatischer Tool-Aufruf) ermöglicht es Claude, Code zu schreiben, der deine Tools programmatisch innerhalb eines code execution-Containers aufruft, anstatt für jeden Tool-Aufruf Roundtrips durch das Modell zu erfordern. Dies reduziert die Latenz für Multi-Tool-Workflows und verringert den Token-Verbrauch, indem Claude Daten filtern oder verarbeiten kann, bevor sie das Kontextfenster des Modells erreichen. Bei agentischen Such-Benchmarks wie BrowseComp und DeepSearchQA, die mehrstufige Web-Recherche und komplexe Informationsbeschaffung testen, verbesserte das Hinzufügen von programmatischem Tool-Aufruf zusätzlich zu grundlegenden Such-Tools die Leistung um durchschnittlich 11 % bei gleichzeitiger Verwendung von 24 % weniger Input-Tokens (siehe Improved web search with dynamic filtering).
Betrachte die Überprüfung der Budgeteinhaltung bei 20 Mitarbeitenden: Der traditionelle Ansatz erfordert 20 separate Modell-Roundtrips und zieht dabei Tausende von Ausgabenposten in den Kontext. Mit programmatischem Tool-Aufruf führt ein einziges Skript alle 20 Abfragen aus, filtert die Ergebnisse und gibt nur die Mitarbeitenden zurück, die ihre Limits überschritten haben, wodurch das, worüber Claude nachdenken muss, von Hunderten von Kilobytes auf eine Handvoll Zeilen schrumpft.
Programmatischer Tool-Aufruf erfordert code_execution_20260120 oder neuer, was auf den folgenden Modellen unterstützt wird:
| Modell |
|---|
| Claude Fable 5 () |
| Claude Mythos 5 () |
| Claude Opus 5 () |
| Claude Opus 4.8 () |
| Claude Opus 4.7 () |
| Claude Opus 4.6 () |
| Claude Sonnet 5 () |
| Claude Sonnet 4.6 () |
| Claude Opus 4.5 () |
| Claude Sonnet 4.5 () |
Die vollständige Versionsmatrix des Code-Execution-Tools findest du in der Modellkompatibilitätstabelle des Code-Execution-Tools. Programmatischer Tool-Aufruf ist auf der Claude API, der Claude Platform on AWS und Microsoft Foundry verfügbar. Auf Microsoft Foundry erfordert der programmatische Tool-Aufruf ein Hosted on Anthropic Deployment. Er ist derzeit nicht auf Amazon Bedrock oder Google Cloud verfügbar.
Hier ist ein Beispiel, bei dem Claude programmatisch eine Datenbank mehrfach abfragt und die Ergebnisse aggregiert:
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-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_20260120", "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_20260120"],
},
],
)
print(response)Die Antwort stoppt mit stop_reason: "tool_use", einer container-ID und einem tool_use-Block für query_database, dessen caller-Feld den Code-Execution-Lauf identifiziert, der ihn aufgerufen hat. Gib das Ergebnis wie in Schritt 3 des Beispiel-Workflows gezeigt zurück, damit der Code abgeschlossen werden kann.
Wenn du ein Tool so konfigurierst, dass es aus der Code Execution aufrufbar ist, und Claude sich entscheidet, dieses Tool zu verwenden:
tool_use-Block zurückDieser Ansatz ist besonders nützlich für:
allowed_callersDas Feld allowed_callers gibt an, welche Kontexte ein Tool aufrufen können:
{
"name": "query_database",
"description": "Execute a SQL query against the database",
"input_schema": {
// ...
},
"allowed_callers": ["code_execution_20260120"]
}Mögliche Werte:
["direct"] - Claude wird angeleitet, dieses Tool direkt aufzurufen (Standard, wenn weggelassen)["code_execution_20260120"] - Claude wird angeleitet, dieses Tool nur innerhalb der Code Execution aufzurufen["direct", "code_execution_20260120"] - Claude kann dieses Tool direkt oder innerhalb der Code Execution aufrufenSowohl "code_execution_20260120" als auch "code_execution_20260521" werden in allowed_callers akzeptiert und sind austauschbar: Eine Anfrage, die eine der beiden Code-Execution-Tool-Versionen verwendet, erfüllt Tools, die einen der beiden Caller auflisten. Antwortblöcke kennzeichnen den Caller immer als code_execution_20260120, unabhängig davon, welche Version die Anfrage deklariert hat.
caller in AntwortenJeder Tool-Use-Block enthält ein caller-Feld, das angibt, wie er aufgerufen wurde:
Direkter Aufruf (traditionelle Tool-Nutzung):
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": { "type": "direct" }
}Programmatischer Aufruf:
{
"type": "tool_use",
"id": "toolu_xyz789",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_abc123"
}
}Die tool_id ist die id des Code-Execution-server_tool_use-Blocks, der den Aufruf getätigt hat, sodass du jeden programmatischen tool_use dem Code-Execution-Lauf zuordnen kannst, der ihn erzeugt hat.
Programmatischer Tool-Aufruf verwendet dieselben Container wie Code Execution:
container zurückgegeben, zusammen mit einem expires_at-Zeitstempelexpires_at sagt dir, wie lange der Container noch verfügbar ist. Inaktive Container werden derzeit nach etwa 5 Minuten zurückgefordert, und kein Container kann mehr als 30 Tage nach seiner Erstellung wiederverwendet werden.So funktioniert ein vollständiger programmatischer Tool-Aufruf-Ablauf:
Sende eine Anfrage mit Code Execution und einem Tool, das programmatische Aufrufe erlaubt. Um programmatische Aufrufe zu aktivieren, füge das Feld allowed_callers zu deiner Tool-Definition hinzu.
Die Anfrageform ist identisch mit dem Schnellstart-Beispiel: Füge code_execution in deine Tool-Liste ein, füge allowed_callers: ["code_execution_20260120"] zu jedem Tool hinzu, das Claude aus Code aufrufen soll, und sende deine Benutzernachricht. Die verbleibenden Schritte in diesem Workflow verwenden die Benutzernachricht "Query customer purchase history from the last quarter and identify our top 5 customers by revenue".
Claude schreibt Code, der dein Tool aufruft. Die API pausiert und gibt zurück:
{
"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": "import json\n\nrows = json.loads(await query_database({'sql': '<sql>'}))\ntop_customers = sorted(rows, 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_20260120",
"tool_id": "srvtoolu_abc123"
}
}
],
"container": {
"id": "container_xyz789",
"expires_at": "2026-01-20T14:30:00Z"
},
"stop_reason": "tool_use"
}Sende den vollständigen Gesprächsverlauf plus dein Tool-Ergebnis. Drei Details sind bei dieser Anfrage wichtig:
tool_result-Blöcke enthalten. Siehe Einschränkungen bei der Nachrichtenformatierung.container-ID aus der pausierten Antwort. Die API lehnt eine Fortsetzung ab, die ausstehende programmatische Tool-Aufrufe, aber keine Container-ID hat.tools-Array wie bei der ursprünglichen Anfrage. Das Code-Execution-Tool muss weiterhin vorhanden sein, damit der pausierte Code fortgesetzt werden kann, und die Tools, die du bei dieser Anfrage sendest, sind die Definitionen, die Claude und der laufende Code für den Rest des Turns verwenden können.response = client.messages.create(
model="claude-opus-5",
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_20260120",
"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}, ...]',
}
],
},
],
# Dasselbe tools-Array wie in der ursprünglichen Anfrage
tools=[
{"type": "code_execution_20260120", "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_20260120"],
},
],
)
print(response)Der Code setzt dort fort, wo er pausiert hat, und verarbeitet dein Ergebnis. Jede Fortsetzungsantwort pausiert entweder erneut mit weiteren programmatischen tool_use-Blöcken oder schließt die Code Execution ab und lässt Claude den Turn fortsetzen (Schritt 5). Prüfe stop_reason und den caller jedes tool_use-Blocks, um die beiden zu unterscheiden: Eine Antwort, die für dich pausiert, hat stop_reason: "tool_use" und einen tool_use-Block, dessen caller eine Code-Execution-Version benennt, und du wiederholst Schritt 3 mit einem tool_result für jeden ausstehenden programmatischen Aufruf in einer Benutzernachricht.
Sobald die Code Execution abgeschlossen ist, liefert Claude die finale Antwort:
{
"content": [
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "Top 5 customers: [{'customer_id': 'C1', 'revenue': 45000}, {'customer_id': 'C2', 'revenue': 38000}, {'customer_id': 'C5', 'revenue': 32000}, {'customer_id': 'C8', 'revenue': 28500}, {'customer_id': 'C3', 'revenue': 24000}]",
"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 kann Code schreiben, der mehrere Elemente effizient verarbeitet:
regions = ["West", "East", "Central", "North", "South"]
results = {}
for region in regions:
rows = json.loads(await query_database({"sql": f"<sql for {region}>"}))
results[region] = sum(row["revenue"] for row in rows)
# Verarbeite die Ergebnisse programmatisch
top_region = max(results.items(), key=lambda x: x[1])
print(f"Top region: {top_region[0]} with ${top_region[1]:,} in revenue")Dieses Muster:
Claude kann die Verarbeitung stoppen, sobald Erfolgskriterien erfüllt sind:
endpoints = ["us-east", "eu-west", "apac"]
for endpoint in endpoints:
status = await check_health({"endpoint": endpoint})
if status == "healthy":
print(f"Found healthy endpoint: {endpoint}")
break # Stop early, don't check remainingpath = "/tmp/example.txt"
file_info = json.loads(await get_file_info({"path": path}))
if file_info["size"] < 10000:
content = await read_full_file({"path": path})
else:
content = await read_file_summary({"path": path})
print(content)server_id = "srv-01"
log_text = await fetch_logs({"server_id": server_id})
errors = [line for line in log_text.splitlines() if "ERROR" in line]
print(f"Found {len(errors)} errors")
for error in errors[-10:]: # Only return last 10 errors
print(error)Wenn Code Execution ein Tool aufruft:
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_xyz789"
}
}Dein Tool-Ergebnis wird an den laufenden Code zurückgegeben:
{
"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}, ...]"
}
]
}Wenn alle Tool-Aufrufe erfüllt sind und der Code abgeschlossen ist:
{
"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": []
}
}| Fehler | Wo er erscheint | Beschreibung | Lösung |
|---|---|---|---|
invalid_tool_input | error_code im code_execution_tool_result-Fehlerblock in der Antwort | Ungültige Parameter wurden an das Code-Execution-Tool übergeben | Siehe die Fehler des Code-Execution-Tools |
invalid_request_error (bei tool_choice) | HTTP-400-Fehlerantwort | tool_choice benennt ein Tool, dessen allowed_callers "direct" nicht enthält | Füge entweder "direct" zu den allowed_callers dieses Tools hinzu oder entferne das Tool aus tool_choice und lass Claude es aus Code aufrufen |
Wenn dein Tool-Ergebnis nicht innerhalb von etwa 4 Minuten eintrifft, löst der ausstehende Aufruf einen TimeoutError innerhalb von Claudes laufendem Code aus. Claude sieht den Fehler in stderr und wiederholt den Aufruf typischerweise:
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "",
"stderr": "TimeoutError: Calling tool ['query_database'] timed out (no response after 270s).",
"return_code": 0,
"content": []
}
}Um Timeouts zu vermeiden:
expires_at in AntwortenWenn dein Tool einen Fehler zurückgibt:
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "Error: Query timeout - table lock exceeded 30 seconds"
}Claudes Code erhält diesen Fehler und kann ihn angemessen behandeln.
strict: true werden mit programmatischem Aufruf nicht unterstützttool_choice erzwingendisable_parallel_tool_use: true wird mit programmatischem Aufruf nicht unterstütztBenutzerdefinierte Tools, deren input_schema ein rekursives $ref enthält (ein Referenzzyklus, wie z. B. ein Schema, das auf sich selbst verweist), können nicht für programmatische Aufrufe aktiviert werden. Das Einbeziehen einer Code-Execution-Tool-Version in allowed_callers für ein solches Tool führt dazu, dass die Anfrage mit einem 400 invalid_request_error fehlschlägt, dessen Nachricht Circular $ref detected enthält. Dasselbe Schema wird für direkte Tool-Aufrufe akzeptiert.
Um dies zu umgehen, tu eines der Folgenden:
allowed_callers weglässt (oder es auf ["direct"] setzt). Andere Tools in derselben Anfrage können weiterhin programmatische Aufrufe verwenden.description der innersten Ebene, oder ersetze die rekursive Eigenschaft durch ein einfaches {"type": "object"}, dessen description die erwartete Form erklärt.Die folgenden Tools können nicht programmatisch aufgerufen werden:
Beim Antworten auf programmatische Tool-Aufrufe gibt es strenge Formatierungsanforderungen:
Antworten nur mit Tool-Ergebnissen: Wenn ausstehende programmatische Tool-Aufrufe auf Ergebnisse warten, darf deine Antwortnachricht nur tool_result-Blöcke enthalten. Du kannst keinen Textinhalt einfügen, auch nicht nach den Tool-Ergebnissen.
Ungültig - Text kann beim Antworten auf programmatische Tool-Aufrufe nicht enthalten sein:
{
"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?" }
]
}Gültig - Nur Tool-Ergebnisse beim Antworten auf programmatische Tool-Aufrufe:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
}
]
}Diese Einschränkung gilt nur beim Antworten auf programmatische (Code-Execution-)Tool-Aufrufe. Bei regulären clientseitigen Tool-Aufrufen kannst du Textinhalt nach den Tool-Ergebnissen einfügen.
Nur-Text-Inhalt für Tool-Ergebnisse: Der content jedes tool_result, das einen programmatischen Aufruf beantwortet, muss ein String oder text-Blöcke sein. Bild-, Dokument- und andere Content-Block-Typen werden abgelehnt.
Programmatische Tool-Aufrufe unterliegen denselben Ratenlimits wie reguläre Tool-Aufrufe. Jeder Tool-Aufruf aus der Code Execution zählt als separater Aufruf.
Bei der Implementierung benutzerdefinierter Tools, die programmatisch aufgerufen werden:
Programmatischer Tool-Aufruf reduziert den Token-Verbrauch auf drei Arten:
Zum Beispiel verbraucht der direkte Aufruf von 10 Tools ~10x so viele Tokens wie der programmatische Aufruf mit Rückgabe einer Zusammenfassung.
In Anthropics internen Evaluierungen auf einem Produktions-Claude-Modell:
tools-Array 10 bis 49 Tool-Definitionen enthält, typische Token-Einsparungen von 20 % bis 40 % mit aktiviertem programmatischem Tool-Aufruf.Die tatsächlichen Einsparungen variieren je nach Workload-Form. Siehe Wann programmatische Aufrufe verwendet werden sollten.
Programmatischer Tool-Aufruf verwendet dieselben Preise wie Code Execution. Siehe die Code-Execution-Preise für Details.
Programmatischer Tool-Aufruf tauscht einen kleinen festen Overhead (Container-Start, Skript-Generierung) gegen große Einsparungen bei Tool-Ergebnis-Tokens und Modell-Roundtrips. Ob sich dieser Tausch lohnt, hängt von der Workload-Form ab.
Gut geeignet:
Schlecht geeignet:
Wenn du unsicher bist, miss die abgerechneten Input-Tokens mit und ohne allowed_callers an einer repräsentativen Stichprobe deines Traffics, bevor du es breit aktivierst.
invalid_request_error beim Setzen von tool_choice
tool_choice kann kein Tool benennen, dessen allowed_callers "direct" weglässt. Füge entweder "direct" zu den allowed_callers dieses Tools hinzu oder entferne das Tool aus tool_choice und lass Claude es aus Code aufrufen.Container-Ablauf
expires_at-Zeitstempel der pausierten Antwort. Claudes Code hört nach etwa 4 Minuten auf, auf ein Ergebnis zu warten, und inaktive Container werden derzeit nach etwa 5 Minuten zurückgefordert.Tool-Ergebnis nicht korrekt geparst
caller-Feld, um den programmatischen Aufruf zu bestätigenClaude ist auf großen Mengen von Code trainiert, daher kann es diese Stärke nutzen, wenn Tools als aufrufbare Python-Funktionen präsentiert werden:
Programmatischer Tool-Aufruf ist ein verallgemeinerbares Muster, das auch auf deiner eigenen Infrastruktur implementiert werden kann. So vergleichen sich die Ansätze:
Stelle Claude ein Code-Execution-Tool zur Verfügung und beschreibe, welche Funktionen in dieser Umgebung verfügbar sind. Wenn Claude das Tool mit Code aufruft, führt deine Anwendung ihn lokal aus, wo diese Funktionen definiert sind.
Vorteile:
Nachteile:
Verwende dies, wenn: Deine Anwendung beliebigen Code sicher ausführen kann, du die kleinste Implementierung möchtest und Anthropics verwaltetes Angebot nicht zu deinen Anforderungen passt.
Derselbe Ansatz aus Claudes Perspektive, aber der Code läuft in einem sandboxed Container mit Sicherheitseinschränkungen (zum Beispiel kein Netzwerk-Egress). Wenn deine Tools externe Ressourcen benötigen, brauchst du ein Protokoll zur Ausführung von Tool-Aufrufen außerhalb der Sandbox.
Vorteile:
Nachteile:
Verwende dies, wenn: Sicherheit kritisch ist und Anthropics verwaltete Lösung nicht zu deinen Anforderungen passt.
Anthropics programmatischer Tool-Aufruf ist eine verwaltete Version der sandboxed Ausführung mit einer auf Claude abgestimmten Python-Umgebung. Anthropic übernimmt die Container-Verwaltung, die Code Execution und die sichere Kommunikation für Tool-Aufrufe.
Vorteile:
Erwäge die Verwendung von Anthropics verwalteter Lösung, wenn du die Claude API, die Claude Platform on AWS oder Microsoft Foundry verwendest. Auf Microsoft Foundry erfordert der programmatische Tool-Aufruf ein Hosted on Anthropic Deployment.
Programmatischer Tool-Aufruf basiert auf der Code-Execution-Infrastruktur und verwendet dieselben Sandbox-Container. Container-Daten, einschließlich Ausführungsartefakten und Ausgaben, werden bis zu 30 Tage aufbewahrt.
Für die ZDR-Berechtigung über alle Funktionen hinweg siehe API und Datenspeicherung.
Streame Tool-Inputs ohne serverseitiges JSON-Buffering für latenzempfindliche Anwendungen.
Führe Python- und Bash-Code in einem sandboxed Container aus, um Daten zu analysieren, Dateien zu generieren und Lösungen zu iterieren.
Verbinde Claude mit externen Tools und APIs. Sieh, wo Tools ausgeführt werden, wann Claude sie aufruft und welches Tool zu deiner Aufgabe passt.
Spezifiziere Tool-Schemas, schreibe effektive Beschreibungen und steuere, wann Claude deine Tools aufruft.
Was this page helpful?