„Programmatic tool calling" (programmatische Tool-Aufrufe) ermöglicht es Claude, Code zu schreiben, der deine Tools programmatisch innerhalb eines Code-Ausführungs-Containers aufruft, anstatt für jeden Tool-Aufruf einen Roundtrip durch das Modell zu erfordern. Dies reduziert die „latency" (Latenz) bei Workflows mit mehreren Tools und senkt den Token-Verbrauch, indem Claude Daten filtern oder verarbeiten kann, bevor sie das „context window" (Kontextfenster) des Modells erreichen. Bei agentischen Such-Benchmarks wie BrowseComp und DeepSearchQA, die mehrstufige Web-Recherche und komplexe Informationsbeschaffung testen, verbesserte das Hinzufügen programmatischer Tool-Aufrufe zu einfachen Such-Tools die Leistung um durchschnittlich 11 %, während 24 % weniger Input-Token verbraucht wurden (siehe Improved web search with dynamic filtering).
Stell dir vor, du prüfst die Budgeteinhaltung von 20 Mitarbeitenden: Der herkömmliche Ansatz erfordert 20 separate Modell-Roundtrips und zieht dabei Tausende von Spesenposten in den Kontext. Mit programmatischen Tool-Aufrufen 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.
Programmatische Tool-Aufrufe erfordern code_execution_20260120 oder neuer, was von 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-Ausführungs-Tools findest du in der Modellkompatibilitätstabelle des Code-Ausführungs-Tools. Programmatische Tool-Aufrufe sind auf der Claude API, der Claude Platform on AWS und Microsoft Foundry verfügbar. Auf Microsoft Foundry erfordern programmatische Tool-Aufrufe ein Hosted on Anthropic-Deployment. Auf Amazon Bedrock oder Google Cloud ist die Funktion derzeit nicht verfügbar.
Hier ist ein Beispiel, in dem Claude programmatisch mehrfach eine Datenbank abfragt und die Ergebnisse aggregiert. Das Hinzufügen von allowed_callers: ["code_execution_20260120"] zu einer Tool-Definition macht dieses Tool aus der Code-Ausführung heraus aufrufbar (siehe Das Feld allowed_callers):
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-Ausführungslauf identifiziert, der ihn aufgerufen hat. Gib das Ergebnis wie in Schritt 3 des Beispiel-Workflows gezeigt zurück, damit der Code abschließen kann.
Wenn du ein Tool so konfigurierst, dass es aus der Code-Ausführung aufrufbar ist, und Claude feststellt, dass dieses Tool benötigt wird:
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 aus der Code-Ausführung heraus aufzurufen["direct", "code_execution_20260120"] - Claude kann dieses Tool direkt oder aus der Code-Ausführung heraus aufrufenSowohl "code_execution_20260120" als auch "code_execution_20260521" werden in allowed_callers akzeptiert und sind austauschbar: Eine Anfrage mit einer der beiden Versionen des Code-Ausführungs-Tools 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 (herkömmliche 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 server_tool_use-Blocks der Code-Ausführung, der den Aufruf getätigt hat, sodass du jedes programmatische tool_use dem Code-Ausführungslauf zuordnen kannst, der es erzeugt hat.
Programmatische Tool-Aufrufe verwenden dieselben Container wie die Code-Ausführung:
container zurückgegeben, zusammen mit einem expires_at-Zeitstempelexpires_at gibt an, wie viel Zeit dem Container noch bleibt. Inaktive Container werden derzeit nach etwa 5 Minuten freigegeben, und kein Container kann mehr als 30 Tage nach seiner Erstellung wiederverwendet werden.So funktioniert ein vollständiger Ablauf mit programmatischen Tool-Aufrufen:
Sende eine Anfrage mit Code-Ausführung und einem Tool, das programmatische Aufrufe zulässt. Um programmatische Aufrufe zu aktivieren, füge das Feld allowed_callers zu deiner Tool-Definition hinzu.
Die Form der Anfrage ist identisch mit dem Schnellstart-Beispiel: Nimm code_execution in deine Tools-Liste auf, füge allowed_callers: ["code_execution_20260120"] zu jedem Tool hinzu, das Claude aus Code aufrufen soll, und sende deine User-Nachricht. Die übrigen Schritte in diesem Workflow verwenden die User-Nachricht "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 in der ursprünglichen Anfrage. Das Code-Ausführungs-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-Ausführung ab und lässt Claude den Turn fortsetzen (Schritt 5). Prüfe stop_reason und das caller-Feld jedes tool_use-Blocks, um die beiden Fälle zu unterscheiden: Eine Antwort, die für dich pausiert, hat stop_reason: "tool_use" und einen tool_use-Block, dessen caller eine Code-Ausführungsversion nennt, und du wiederholst Schritt 3 mit einem tool_result für jeden ausstehenden programmatischen Aufruf in einer einzigen User-Nachricht.
Sobald die Code-Ausführung abgeschlossen ist, liefert Claude die endgültige 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)
# Ergebnisse programmatisch verarbeiten
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 beenden, sobald die 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 die Code-Ausführung 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 bedient 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 auftritt | Beschreibung | Lösung |
|---|---|---|---|
invalid_tool_input | error_code im code_execution_tool_result-Fehlerblock in der Antwort | Ungültige Parameter wurden an das Code-Ausführungs-Tool übergeben | Siehe die Fehler des Code-Ausführungs-Tools |
invalid_request_error (bei tool_choice) | HTTP-400-Fehlerantwort | tool_choice nennt 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 innerhalb von Claudes laufendem Code einen TimeoutError aus. Claude sieht den Fehler in stderr und wiederholt den Aufruf in der Regel:
{
"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 bei programmatischen Aufrufen nicht unterstützttool_choice erzwingendisable_parallel_tool_use: true wird bei programmatischen Aufrufen nicht unterstütztBenutzerdefinierte Tools, deren input_schema ein rekursives $ref enthält (einen Referenzzyklus, etwa ein Schema, das auf sich selbst verweist), können nicht für programmatische Aufrufe aktiviert werden. Wenn du für ein solches Tool eine Version des Code-Ausführungs-Tools in allowed_callers aufnimmst, schlägt die Anfrage mit einem 400 invalid_request_error fehl, dessen Meldung Circular $ref detected enthält. Dasselbe Schema wird für direkte Tool-Aufrufe akzeptiert.
Um dies zu umgehen, tue eines der folgenden Dinge:
allowed_callers weglässt (oder 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:
computer_toolset_20260801 und browser_toolset_20260801), deren allowed_callers-Feld nur "direct" akzeptiertBeim Antworten auf programmatische Tool-Aufrufe gelten 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 - Beim Antworten auf programmatische Tool-Aufrufe darf kein Text 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 Tool-Aufrufe (Code-Ausführung). Bei regulären clientseitigen Tool-Aufrufen kannst du nach den Tool-Ergebnissen Textinhalt einfügen.
Nur Text als Tool-Ergebnis-Inhalt: Der content jedes tool_result, das einen programmatischen Aufruf beantwortet, muss ein String oder text-Blöcke sein. Bild-, Dokument- und andere Inhaltsblocktypen werden abgelehnt.
Programmatische Tool-Aufrufe unterliegen denselben Ratenlimits wie reguläre Tool-Aufrufe. Jeder Tool-Aufruf aus der Code-Ausführung zählt als separater Aufruf.
Bei der Implementierung benutzerdefinierter Tools, die programmatisch aufgerufen werden:
Programmatische Tool-Aufrufe reduzieren den Token-Verbrauch auf drei Arten:
Zum Beispiel verbraucht das direkte Aufrufen von 10 Tools etwa das 10-Fache der Token im Vergleich zum programmatischen Aufrufen mit Rückgabe einer Zusammenfassung.
In Anthropics internen Evaluierungen mit einem produktiven Claude-Modell:
tools-Array 10 bis 49 Tool-Definitionen enthält, mit aktivierten programmatischen Tool-Aufrufen typische Token-Einsparungen von 20 % bis 40 %.Die tatsächlichen Einsparungen variieren je nach Form der Arbeitslast. Siehe Wann programmatische Aufrufe verwendet werden sollten.
Programmatische Tool-Aufrufe verwenden dieselbe Preisgestaltung wie die Code-Ausführung. Details findest du unter Preise für Code-Ausführung.
Programmatische Tool-Aufrufe tauschen einen kleinen fixen Overhead (Container-Start, Skriptgenerierung) gegen große Einsparungen bei Tool-Ergebnis-Token und Modell-Roundtrips. Ob sich dieser Tausch lohnt, hängt von der Form der Arbeitslast ab.
Gut geeignet:
Weniger geeignet:
Wenn du unsicher bist, miss die abgerechneten Input-Token mit und ohne allowed_callers an einer repräsentativen Stichprobe deines Traffics, bevor du die Funktion breit aktivierst.
invalid_request_error beim Setzen von tool_choice
tool_choice kann kein Tool nennen, dessen allowed_callers "direct" auslä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 freigegeben.Tool-Ergebnis wird nicht korrekt geparst
caller-Feld, um den programmatischen Aufruf zu bestätigenClaude ist auf großen Mengen von Code trainiert, sodass die Darstellung von Tools als aufrufbare Python-Funktionen diese Stärke nutzt:
Programmatische Tool-Aufrufe sind ein verallgemeinerbares Muster, das auch auf deiner eigenen Infrastruktur implementiert werden kann. So lassen sich die Ansätze vergleichen:
Stelle Claude ein Code-Ausführungs-Tool bereit 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 Sandbox-Container mit Sicherheitseinschränkungen (zum Beispiel kein ausgehender Netzwerkverkehr). 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 entscheidend ist und Anthropics verwaltete Lösung nicht zu deinen Anforderungen passt.
Anthropics programmatische Tool-Aufrufe sind eine verwaltete Version der Sandbox-Ausführung mit einer meinungsstarken, auf Claude abgestimmten Python-Umgebung. Anthropic übernimmt Container-Verwaltung, Code-Ausführung und die sichere Kommunikation bei Tool-Aufrufen.
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 erfordern programmatische Tool-Aufrufe ein Hosted on Anthropic-Deployment.
Programmatische Tool-Aufrufe basieren auf der Code-Ausführungs-Infrastruktur und verwenden dieselben Sandbox-Container. Container-Daten, einschließlich Ausführungsartefakten und Ausgaben, werden bis zu 30 Tage aufbewahrt.
Zur ZDR-Berechtigung über alle Funktionen hinweg siehe API und Datenaufbewahrung.
Streame Tool-Eingaben ohne serverseitiges JSON-Buffering für latenzempfindliche Anwendungen.
Führe Python- und Bash-Code in einem Sandbox-Container aus, um Daten zu analysieren, Dateien zu generieren und Lösungen iterativ zu verbessern.
Verbinde Claude mit externen Tools und APIs. Erfahre, wo Tools ausgeführt werden, wann Claude sie aufruft und welches Tool zu deiner Aufgabe passt.
Lege Tool-Schemas fest, schreibe wirksame Beschreibungen und steuere, wann Claude deine Tools aufruft.
Was this page helpful?