Zum Hauptinhalt springen

Programmatisches Tool Calling

Experte
What you'll learn
  • Verstehen, was tatsächlich passiert, wenn Claude dein Tool aus einer Sandbox heraus aufruft — und warum dein Tool trotzdem auf deiner eigenen Maschine läuft
  • Es korrekt mit allowed_callers aktivieren und wissen, warum das keine Sicherheitsgrenze ist
  • Die echten Zahlen kennen: was es spart, bei welchen Workloads, und wo es dich etwas kostet
  • Die fünf Fehlermodi vermeiden, die in Produktion 400er und TimeoutErrors erzeugen

Das Problem, das es löst

Klassische Tool-Nutzung ist ein Gespräch. Claude fordert einen Tool-Aufruf an, du antwortest, das gesamte Ergebnis landet im Kontextfenster, Claude liest es und fordert den nächsten an. Zwanzig Abfragen bedeuten zwanzig Inferenz-Durchläufe und zwanzig rohe Payloads, die für immer im Kontext liegen.

Der Großteil dieser Payload ist Verschwendung. Wenn du wissen willst, welche von zwanzig Mitarbeitenden ihr Spesenbudget gesprengt haben, braucht Claude nicht jede einzelne Buchungszeile — es braucht die Handvoll Namen. In der klassischen Tool-Nutzung müssen die Buchungszeilen aber durch das Modell hindurch, damit es sie filtern kann.

Programmatisches Tool Calling dreht das um. Claude schreibt ein Python-Skript, das Skript ruft deine Tools in einer Schleife auf, filtert die Ergebnisse, und nur das, was das Skript ausgibt, kommt zum Modell zurück. Die Rohdaten gelangen überhaupt nie ins Kontextfenster.

Was tatsächlich passiert

Hier ist der Punkt, den fast jede Zusammenfassung dieses Features falsch darstellt: dein Tool läuft nicht in der Sandbox. Anthropics Container hat keinen Zugriff auf deine Datenbank.

Was wirklich passiert: Claudes Python-Code pausiert mitten in der Ausführung, die API gibt den Aufruf an dich zurück, und der Interpreter läuft weiter, sobald du antwortest:

Guided walkthrough1 of 5
  1. Es läuft im Code-Execution-Container. Deine Tools erscheinen diesem Code als asynchrone Python-Funktionen — eine pro Tool, jede nimmt ein einzelnes Dict mit Argumenten entgegen und gibt einen String zurück.

Weil die Funktionen async sind, kann Claude mit asyncio.gather fächern und zehn Tools gleichzeitig anfragen — etwas, das klassische Tool-Nutzung mit parallelen Tool-Blöcken nur annähern kann.

Wie Claudes generierter Code tatsächlich aussieht

import json

rows = json.loads(await query_database({"sql": "<sql>"}))
top = sorted(rows, key=lambda r: r["revenue"], reverse=True)[:5]
print(f"Top 5 customers: {top}")

Beachte das json.loads. Die Tool-Funktion gibt einen String zurück — den wörtlichen Text des tool_result, das du zurückschickst. Wenn deine Tool-Beschreibung nicht sagt „gibt eine Liste von Zeilen als JSON-Objekte zurück", hat Claude keine Möglichkeit zu wissen, dass es das Ding deserialisieren kann, und behandelt deine Daten als undurchsichtigen Blob. Der Satz zum Ausgabeformat in deiner Tool-Beschreibung hört auf, Dokumentation zu sein, und wird zu tragendem Code. Das ist die Zeile mit der höchsten Hebelwirkung, die du beim Einführen dieses Features schreiben wirst.

Einschalten

Ein Feld am Tool, das aus Code heraus aufgerufen werden soll, plus das Code-Execution-Tool im Request:

Programmatisches Calling an einem Tool aktivieren

{
"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" } }, "required": ["sql"] },
"allowed_callers": ["code_execution_20260120"]
}

allowed_callers kennt drei Ausprägungen:

WertBedeutung
["direct"]Klassische Tool-Nutzung. Das ist der Standard, wenn das Feld weggelassen wird.
["code_execution_20260120"]Claude wird angeleitet, es nur aus Code heraus aufzurufen.
["direct", "code_execution_20260120"]Beides. Die Doku rät davon ab — wähle eines, damit Claude ein eindeutiges Signal bekommt.

Jeder tool_use-Block in der Antwort trägt nun einen caller: entweder {"type": "direct"} oder einen Code-Execution-Caller, dessen tool_id zum server_tool_use-Block passt, der das Skript ausgeführt hat. So ordnest du einen Aufruf dem Skript zu, das ihn gemacht hat.

Es ist keine Sicherheitsgrenze

Die Doku ist hier ungewöhnlich deutlich, und es lohnt sich, das zu wiederholen, weil man leicht das Gegenteil annimmt: allowed_callers steuert, wie das Tool Claude präsentiert wird. Es ist keine harte Sperre auf API-Ebene. Claude wird stark angeleitet, sich daran zu halten — aber dein Client muss trotzdem darauf vorbereitet sein, für jedes Tool, das er definiert, ein direktes tool_use zu empfangen, und du darfst dieses Feld nicht als Autorisierungsmechanismus verwenden. Autorisierung gehört in deinen Tool-Handler, so wie schon immer.

Die Zahlen

Anthropics eigene veröffentlichte Werte, damit du beurteilen kannst, ob sich die Komplexität lohnt:

  • Bei komplexen Recherche-Aufgaben sank der durchschnittliche Verbrauch von 43.588 auf 27.297 Tokens — eine Reduktion um 37 %.
  • Bei den GIA-Benchmarks stieg die Genauigkeit von 46,5 % auf 51,2 %; bei interner Wissensabfrage von 25,6 % auf 28,5 %. Weniger Tokens und bessere Antworten, weil das Modell über Schlussfolgerungen nachdenkt, statt in rohen Payloads zu ertrinken.
  • Bei agentischen Such-Benchmarks (BrowseComp, DeepSearchQA) verbesserte das Aufsetzen von programmatischem Calling auf einfache Such-Tools die Leistung um durchschnittlich 11 % bei 24 % weniger Input-Tokens.
  • Latenz: 20+ Tool-Aufrufe in einem Codeblock zu orchestrieren eliminiert 19+ Inferenz-Durchläufe.

Die Form des Gewinns ist das entscheidende Signal. Es zahlt sich aus, wenn du 3+ voneinander abhängige Aufrufe, eine Schleife, einen Filter oder ein Fan-out hast. Es bringt nichts — und kostet dich einen Container —, wenn Claude genau einen Tool-Aufruf braucht und die ganze Antwort ohnehin lesen will.

Watch out
  • Claude Haiku 4.5 akzeptiert die neueren Tool-Typen, unterstützt aber KEIN programmatisches Tool Calling und auch nicht die davon abhängige REPL-State-Persistenz. Die neueren Versionen verhalten sich dort stillschweigend wie code_execution_20250825. Wenn du aus Kostengründen zu Haiku routest, bekommst du dieses Feature nicht — und du bekommst auch keinen Fehler, der dich darauf hinweist.

Was es kostet

Programmatisches Tool Calling wird als Code Execution abgerechnet, und Code Execution wird nach Container-Stunde abgerechnet, nicht pro Aufruf:

  • 1.550 Freistunden pro Monat, pro Organisation.
  • Darüber hinaus 0,05 $ pro Stunde, pro Container.
  • Die Ausführungszeit hat ein Minimum von 5 Minuten — ein Zwei-Sekunden-Skript stellt trotzdem fünf Minuten Container in Rechnung.
  • Wenn du dem Request Dateien anhängst, wird die Ausführungszeit auch dann berechnet, wenn das Tool nie aufgerufen wird, weil die Dateien ohnehin auf einen Container vorgeladen werden.
  • Es ist kostenlos, wenn derselbe Request auch Web-Suche oder Web-Fetch nutzt (web_search_20260209 / web_fetch_20260209 oder neuer).

Zwei Konsequenzen sind es wert, verinnerlicht zu werden. Erstens: Die 5-Minuten-Untergrenze bedeutet, dass viele kurzlebige Container das teure Muster sind; einen Container über eine Session hinweg wiederzuverwenden ist das billige. Zweitens: Dieses Feature ist nicht Zero-Data-Retention-fähig — wenn ZDR für dich vertraglich vorgeschrieben ist, ist das ein hartes Ausschlusskriterium und kein Stellschräubchen.

Die fünf Arten, wie das kaputtgeht

Guided walkthrough1 of 5
  1. Wenn programmatische Tool-Aufrufe ausstehen, darf deine Antwort-Message NUR tool_result-Blöcke enthalten. Nicht Text plus Tool-Ergebnisse. Nicht Tool-Ergebnisse gefolgt von einem höflichen Satz. Ausschließlich tool_result-Blöcke.

Versionsstrings, entschlüsselt

Alle drei Code-Execution-Versionen sind allgemein verfügbar und brauchen keinen Beta-Header:

VersionWas sie ergänzt
code_execution_20250825Die Basis. Bash + Python + Datei-Operationen. Auf jedem aktuellen Modell unterstützt.
code_execution_20260120Ergänzt REPL-State-Persistenz und programmatisches Tool Calling. Das ist die, die du brauchst.
code_execution_20260521Identische Runtime wie 20260120. Der einzige Unterschied: Die Tool-Beschreibung informiert Claude über das 90-Sekunden-Wanduhr-Limit pro Python-Zelle, damit es lang laufende Zellen einplanen kann. Eine Zelle, die das Limit sprengt, liefert einen return_code ungleich null mit dem Status detection_timeout.

Diese letzte Zeile ist ein hübsches Stück API-Design, das man bemerken sollte: ein Versionssprung, dessen gesamter Inhalt ein besserer Prompt für das Modell ist. Beide Strings sind innerhalb von allowed_callers austauschbar, und Antworten kennzeichnen den Caller immer als code_execution_20260120, egal welchen du deklariert hast.

Der Container selbst hat keinen Internetzugang — Claude kann zur Laufzeit kein pip install machen, du bekommst also den vorinstallierten Bibliotheks-Satz (pandas, numpy, scipy, scikit-learn, statsmodels und Konsorten) und sonst nichts. Container werden nach etwa fünf Minuten Inaktivität per Checkpoint gesichert, sind per ID wiederherstellbar und laufen 30 Tage nach Erstellung ab.

Wann man dazu greift

Greife zu programmatischem Tool Calling, wenn das Modell als Schleife und Filter eingesetzt wird und nicht als Denker: Batch-Abfragen über N Entitäten, frühzeitiger Abbruch, sobald eine Bedingung erfüllt ist, bedingte Tool-Auswahl basierend auf einem Zwischenergebnis, oder das Eindampfen eines 200-KB-Log-Dumps auf die zehn Zeilen, die zählen.

Greife stattdessen zum Tool Search Tool, wenn dein Problem darin besteht, dass die Definitionen deinen Kontext auffressen, bevor überhaupt ein einziger Aufruf passiert ist — markiere Tools mit defer_loading: true, und Claude lädt sie bei Bedarf. Die beiden sind Ergänzungen, keine Alternativen: Tool Search findet das richtige Tool, programmatisches Calling führt es günstig aus. Wenn deine Tool-Definitionen etwa 10K Tokens überschreiten, brauchst du wahrscheinlich beides.

Und wenn du von der anderen Seite kommst — ein Agent, dessen Kontext in MCP-Tool-Ergebnissen ertrinkt —, fang bei MCP-Token-Kosten und Context Engineering an, denn die billigsten Tokens sind immer noch die, die du nie sendest.

Check yourself

0/5
  1. Wo wird dein Tool beim programmatischen Tool Calling tatsächlich ausgeführt?
  2. Kannst du dich darauf verlassen, dass allowed_callers verhindert, dass ein Tool direkt aufgerufen wird?
  3. Dein Agent routet zu Claude Haiku 4.5, um Geld zu sparen, und übergibt code_execution_20260120. Was passiert?
  4. Wenn ein programmatischer Tool-Aufruf aussteht, was darf deine Antwort-Message enthalten?
  5. Ein Zwei-Sekunden-Skript läuft in einem frischen Container. Wie viel Code-Execution-Zeit wird abgerechnet?
Drücke Enter oder die Leertaste, um die Karte umzudrehen. Nutze die Pfeiltasten links und rechts, um zwischen den Karten zu wechseln.Begriff angezeigt.
1 / 7

Quellen & weiterführende Lektüre