Wenn Claude Code ein Tool ausführt, läuft das normalerweise so ab: eine Funktion aufrufen, auf das Ergebnis warten, es verarbeiten, die nächste Funktion aufrufen. Das Ganze fünfzigmal für fünfzig Aufgaben. Das funktioniert, aber jeder Schritt braucht einen vollständigen Roundtrip über die API, und diese Roundtrips summieren sich schnell. Programmatic Tool Calling (PTC) dreht dieses Muster um. Statt Tools über Gesprächsrunden zu orchestrieren, schreibt Claude Programmcode und führt ihn aus, der mehrere Tools aufruft, ihre Ausgaben verarbeitet und nur die Endergebnisse an sein Kontextfenster zurückgibt. Ein Inferenzdurchlauf, ein Ausführungsblock. Der Unterschied ist nicht graduell, er liegt in der Architektur.
Dieser Leitfaden erklärt, wie PTC funktioniert, warum es für ernsthafte Agentenentwicklung wichtig ist und wie Sie es mit Claude Code und eigenen MCP-Servern umsetzen. Wir behandeln den Mechanismus, bauen ein funktionierendes Beispiel und gehen die Stolperfallen durch, an denen die meisten Entwickler hängen bleiben.
Das Problem, das PTC löst
Nehmen wir einen praktischen Fall: Sie müssen den Status von fünfzig Servern prüfen. Beim normalen Tool Use ruft Claude check_status(server_1) auf, wartet auf das Ergebnis, verarbeitet es, ruft check_status(server_2) auf und so weiter. Fünfzig Tool-Aufrufe bedeuten fünfzig API-Roundtrips, und jeder verbraucht Token für die Anfrage, die Antwort und Claudes Überlegungen zum nächsten Schritt. Das Kontextfenster füllt sich mit Zwischenergebnissen. Die Latenz wächst mit jedem Schritt.
Jetzt die Alternative: Claude schreibt ein Python-Skript, das check_status für alle fünfzig Server aufruft, die Ergebnisse zu einer Zusammenfassung verdichtet und ein einziges JSON-Objekt zurückgibt. Weniger Roundtrips, minimaler Kontextverbrauch. Die Orchestrierungslogik steckt in explizitem Code statt in Claudes natürlichsprachlichen Überlegungen. Laut Anthropics internen Tests (nicht unabhängig überprüft) kann PTC den Tokenverbrauch bei komplexen Rechercheaufgaben um bis zu 37 % senken und in bestimmten Benchmarks die Genauigkeit verbessern. Die Gewinne sollen aus zwei Quellen stammen: weniger Kontextverschmutzung durch Zwischenergebnisse und explizite programmatische Ablaufsteuerung statt Orchestrierung im Gespräch. Wie viel bei Ihnen herauskommt, hängt von der Art der Aufgabe und vom Tool-Design ab.
So funktioniert Programmatic Tool Calling
Der Mechanismus besteht aus drei Komponenten, die zusammenspielen:
1. Code Execution Tool: PTC setzt voraus, dass die Code-Execution-Sandbox aktiviert ist. In dieser abgeschotteten Umgebung kann Claude während eines Gesprächs Code schreiben und ausführen.
2. Tool-Opt-in: Ihre Tools müssen ausdrücklich erklären, dass sie aus der Code Execution heraus aufgerufen werden dürfen, und dazu "allowed_callers" mit dem passenden Versions-String in ihre Definition aufnehmen. Ohne dieses Flag greift Claude auf das normale sequenzielle Tool Calling zurück. Das Opt-in ist Absicht: So lassen sich Tools mit Nebenwirkungen (Zahlungen, Löschvorgänge, Produktiv-Deployments) nicht standardmäßig aus generiertem Code aufrufen.
3. Skript-Generierung: Stößt Claude auf eine Aufgabe, die von Batch-Ausführung oder komplexer Datenverarbeitung profitiert, schreibt Claude ein Skript, das Ihre Tools aufruft. Das Skript setzt während der Ausführung Tool-Call-Anfragen ab; die Host-Anwendung löst diese Aufrufe auf und steigt mit den Ergebnissen wieder in die Ausführung ein. In Claudes Kontext landet nur die fertig verarbeitete Ausgabe.
Der letzte Punkt verdient Betonung: Claude „pausiert“ die Ausführung nicht im klassischen asynchronen Sinn. Die Code-Execution-Umgebung gibt Tool-Call-Absichten aus, und die Host-Anwendung ist dafür zuständig, sie aufzulösen und die Ausführung fortzusetzen. Eine echte Coroutine-Unterbrechung gibt es nicht. Es handelt sich um ein Request-Response-Muster, das Ihre Anwendungsschicht vermittelt.
So sieht die Struktur der API-Antwort aus, wenn PTC greift. (Das Schema ist der Lesbarkeit halber vereinfacht; die Feldnamen unterscheiden sich je nach SDK und Debug-Trace.)
{
"role": "assistant",
"content": [
{
"type": "text",
"text": "I'll query the server status and summarize the results."
},
{
"type": "server_tool_use",
"id": "srvtoolu_abc123",
"name": "code_execution",
"input": {
"code": "import asyncio\n\nasync def check_all():\n tasks = [check_status(f'server_{i}') for i in range(50)]\n results = await asyncio.gather(*tasks)\n healthy = sum(1 for r in results if r['status'] == 'ok')\n return {'healthy': healthy, 'total': 50}\n\nprint(asyncio.run(check_all()))"
}
},
{
"type": "tool_use",
"id": "toolu_def456",
"name": "check_status",
"input": {"server": "server_0"},
"caller": {
"type": "code_execution_20250825",
"tool_id": "srvtoolu_abc123"
}
}
],
"container": {
"id": "container_xyz789",
"expires_at": "2025-01-15T14:30:00Z"
},
"stop_reason": "tool_use"
}
Beachten Sie das Feld caller im Tool-Use-Block: Es zeigt, dass dieser Aufruf aus der Code-Execution-Umgebung stammt und nicht aus Claudes normalem Tool-Use-Pfad. Ihre Anwendung gibt das Tool-Ergebnis zurück, die Ausführung läuft weiter, und Claude erhält am Ende nur die fertig verarbeitete Ausgabe.
Wichtig: PTC garantiert keine parallele Ausführung. Das Skript kann Parallelität ausdrücken (über
asyncio.gather()wie oben gezeigt), aber ob die Tool-Aufrufe tatsächlich gleichzeitig laufen, hängt allein davon ab, wie Ihre Host-Anwendung die abgesetzten Anfragen behandelt. Der Hauptgewinn von PTC liegt in der Lokalität von Kontext und Token: Die Orchestrierungslogik steckt in Code statt in Gesprächsrunden, selbst wenn die Ausführung letztlich sequenziell abläuft. Wenn Sie viele Tool-Aufrufe schnell hintereinander absetzen, denken Sie auch an die Rate Limits der aufgerufenen Dienste.
Ein Hinweis zur Versionierung
In diesem Artikel begegnen Ihnen immer wieder Bezeichner wie:
code_execution_20250825advanced-tool-use-2025-11-20claude-sonnet-4-5
Das sind die aktuellen Beta-Bezeichner mit Stand Jänner 2026. Anthropic hat ähnliche Bezeichner in der Vergangenheit ohne lange Deprecation-Fristen umbenannt oder ersetzt. Betrachten Sie sie als Illustration der aktuellen Implementierung, nicht als stabile öffentliche Zusagen. Prüfen Sie vor jedem Deployment in die Produktion die aktuellen Werte in der offiziellen Dokumentation.
Voraussetzungen
Bevor Sie PTC umsetzen, sollten Sie Folgendes haben:
- Claude Code CLI installiert (
npm install -g @anthropic-ai/claude-code) - Python 3.10+ mit
uvoderpipfür die Paketverwaltung - MCP Python SDK (
pip install mcpoderuv add mcp) - Zugang zur Anthropic API mit dem passenden Beta-Header (derzeit
advanced-tool-use-2025-11-20)
Einen PTC-kompatiblen MCP-Server bauen
Bauen wir ein praktisches Beispiel: einen Finanz-Tool-Server, der Aktienkurse abruft. Wir strukturieren ihn so, dass programmatische Aufrufe möglich sind. Claude kann dann die Kurse mehrerer Ticker in einem einzigen Ausführungsdurchlauf gesammelt abrufen.
Projekt aufsetzen
mkdir finance-mcp-server
cd finance-mcp-server
uv init
uv add mcp httpx
Server-Implementierung
Legen Sie server.py an:
from mcp.server.fastmcp import FastMCP
import asyncio
import random
mcp = FastMCP("Finance-Tools")
async def fetch_price_from_api(ticker: str) -> float:
"""Simulate external API call with network latency."""
await asyncio.sleep(0.3) # Realistic API delay
# In production: httpx.get(f"https://api.example.com/price/{ticker}")
return round(random.uniform(50, 500), 2)
@mcp.tool(
name="get_stock_price",
description="Fetch current stock price for a ticker symbol. "
"Efficient for batch operations (parallelized when runner supports it).",
)
async def get_stock_price(ticker: str) -> dict:
"""
Fetch the current price of a stock.
Args:
ticker: Stock symbol (e.g., AAPL, MSFT, GOOGL)
Returns:
Dictionary with ticker and current price
"""
price = await fetch_price_from_api(ticker)
return {"ticker": ticker, "price": price, "currency": "USD"}
@mcp.tool(
name="get_company_info",
description="Fetch company information including sector and market cap.",
)
async def get_company_info(ticker: str) -> dict:
"""
Fetch company metadata.
Args:
ticker: Stock symbol
Returns:
Company information dictionary
"""
await asyncio.sleep(0.2)
# Simulated data
companies = {
"AAPL": {"name": "Apple Inc.", "sector": "Technology", "market_cap": "3.0T"},
"MSFT": {"name": "Microsoft Corporation", "sector": "Technology", "market_cap": "2.8T"},
"GOOGL": {"name": "Alphabet Inc.", "sector": "Technology", "market_cap": "1.9T"},
}
return companies.get(ticker, {"name": "Unknown", "sector": "Unknown", "market_cap": "N/A"})
if __name__ == "__main__":
mcp.run()
Die Konfiguration von allowed_callers
Jetzt wird es wichtig. Der FastMCP-Decorator stellt allowed_callers derzeit nicht in allen SDK-Versionen direkt bereit. Sie müssen dafür sorgen, dass die an Claude geschickte Tool-Definition dieses Feld enthält. Dafür gibt es drei Ansätze, jeder mit eigenen Kompromissen:
Option 1: SDK-Unterstützung prüfen
Neuere Versionen des MCP SDK (Ende 2025) unterstützen das möglicherweise direkt:
@mcp.tool(
name="get_stock_price",
allowed_callers=["code_execution_20250825"] # If supported
)
async def get_stock_price(ticker: str) -> dict:
...
Das ist der sauberste Weg, sofern verfügbar. Sehen Sie in der Dokumentation Ihrer SDK-Version nach.
Option 2: Server-Definition auf niedriger Ebene
Wenn der Decorator das nicht unterstützt, nehmen Sie die tiefer liegende Klasse Server:
from mcp.server import Server
from mcp.types import Tool, TextContent
import json
server = Server("Finance-Tools")
@server.list_tools()
async def list_tools():
return [
Tool(
name="get_stock_price",
description="Fetch current stock price for a ticker symbol.",
inputSchema={
"type": "object",
"properties": {
"ticker": {"type": "string", "description": "Stock symbol"}
},
"required": ["ticker"]
},
# This is the critical field for PTC
allowed_callers=["code_execution_20250825"]
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "get_stock_price":
ticker = arguments["ticker"]
price = await fetch_price_from_api(ticker)
return [TextContent(type="text", text=json.dumps({
"ticker": ticker,
"price": price,
"currency": "USD"
}))]
Ausführlicher, dafür haben Sie die volle Kontrolle über das Tool-Schema.
Option 3: Tool-Definitionen nachbearbeiten
Fangen Sie die Tool-Liste ab, bevor sie verschickt wird, und fügen Sie das Feld ein:
# Monkey-patch approach — use with caution
original_list_tools = mcp._list_tools_handler
async def patched_list_tools():
tools = await original_list_tools()
for tool in tools:
if tool.name in ["get_stock_price", "get_company_info"]:
tool.allowed_callers = ["code_execution_20250825"]
return tools
mcp._list_tools_handler = patched_list_tools
Das ist fragil, weil es von der internen SDK-Struktur abhängt, die sich ändern kann. Nutzen Sie es als Notlösung, bis es richtige SDK-Unterstützung gibt, nicht als Dauerlösung.
Welcher Ansatz der richtige ist, hängt von Ihrer SDK-Version ab. Die aktuellen Empfehlungen finden Sie in der offiziellen MCP-Dokumentation.
Was ist mit Nutzern von Claude Desktop?
Seit November 2025 gibt es Claude Code direkt in der Claude-Desktop-App. Das ist eine wichtige Änderung: Für die agentischen Fähigkeiten von Claude Code brauchen Sie kein Terminal mehr. Nutzer mit Max, Pro, Team und Enterprise können über die Desktop-Oberfläche mehrere Claude-Code-Sitzungen parallel laufen lassen: eine behebt Bugs, eine andere recherchiert auf GitHub, eine dritte aktualisiert die Dokumentation.
Allerdings ist Programmatic Tool Calling über Claude Code noch nicht verfügbar, egal ob Sie es im Terminal oder in der Desktop-App verwenden. Mit Stand Jänner 2026 gibt es einen offenen Feature Request (GitHub-Issue #12836), der Anthropic bittet, Claude Code um das Flag allowed_callers und die zugehörigen PTC-Betas zu erweitern. Das Issue hat viel Rückhalt in der Community, umgesetzt ist es aber nicht.
So sieht der aktuelle Stand aus:
| Zugang | MCP-Unterstützung | PTC-Unterstützung |
|---|---|---|
| Claude API (direkt) | Ja | Ja (Beta) |
| Claude Code CLI | Ja | Noch nicht |
| Claude Code in Desktop | Ja | Noch nicht |
| Claude Desktop (Chat-Modus) | Ja | Nein |
Was das für Endnutzer bedeutet:
- Wenn Sie Claude Code über die Desktop-App mit MCP-Servern nutzen, bekommen Sie normales Tool Calling, das für die meisten Workflows schon leistungsfähig genug ist.
- Das Feld
allowed_callersIhrer MCP-Server wird ignoriert; Claude Code gibt es derzeit nicht mit dem nötigen Beta-Header an die API weiter. - Bei Batch-Operationen, bei denen PTC glänzen würde, erreichen die vorhandenen Fähigkeiten von Claude Code (Bash-Befehle ausführen, Code iterativ bearbeiten, parallele Sitzungen über Git Worktrees) oft ähnliche praktische Ergebnisse, nur über andere Mechanismen.
Wenn Sie PTC heute brauchen, bleibt nur die direkte API-Integration. In der Regel heißt das, eine eigene Anwendung zu bauen, die in ihren Anfragen sowohl das Tool code_execution_20250825 als auch den Beta-Header advanced-tool-use-2025-11-20 mitschickt.
Die gute Nachricht: Anthropic weiß offensichtlich, dass PTC in Claude Code gefragt ist. Da die Infrastruktur auf API-Ebene existiert, darf man erwarten, dass diese Fähigkeit irgendwann auch in Claude Code ankommt, womit sie automatisch auch in der Desktop-App verfügbar wäre. Behalten Sie die Release Notes im Auge.
Claude Code konfigurieren
Die Konfiguration von MCP-Servern unterscheidet sich zwischen Claude Code (CLI) und Claude Desktop. Da es in diesem Artikel um Claude Code geht, behandeln wir den CLI-Workflow, aber der Vollständigkeit halber nenne ich auch den Weg über Desktop.
Claude Code (CLI)
Verwenden Sie den MCP-Assistenten:
claude mcp add
Geben Sie ein:
- Name:
finance-tools - Befehl:
uv - Argumente:
run server.py
Das legt eine Datei .mcp.json in Ihrem Projektverzeichnis an oder aktualisiert sie (oder die Konfiguration auf Benutzerebene). Sie können die Datei auch direkt bearbeiten:
{
"mcpServers": {
"finance-tools": {
"command": "uv",
"args": ["run", "server.py"],
"cwd": "/path/to/finance-mcp-server"
}
}
}
Für eine Konfiguration auf Benutzerebene (in allen Projekten verfügbar) verwenden Sie claude mcp add --scope user.
Claude Desktop (zum Nachschlagen)
Wenn Sie stattdessen Claude Desktop verwenden, ist es eine andere Konfigurationsdatei:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Die JSON-Struktur ist ähnlich, aber Claude Code CLI liest diese Datei nicht: Es sind zwei getrennte Konfigurationssysteme.
Konfiguration prüfen
Starten Sie Claude Code und prüfen Sie den MCP-Status:
claude
> /mcp
Sie sollten finance-tools: connected sehen. Testen Sie das einfache Tool:
> Get the stock price for AAPL
Claude sollte get_stock_price aufrufen und ein Ergebnis liefern.
Programmatic Tool Calling auslösen
PTC greift, wenn Claude zu dem Schluss kommt, dass eine Orchestrierung per Code effizienter wäre. Mit ausdrücklichen Prompts können Sie nachhelfen:
> Get the current stock price for these 10 tickers: AAPL, MSFT, GOOGL, AMZN,
> TSLA, NVDA, META, NFLX, AMD, INTC. Compare them and tell me which has the
> highest price. Use code execution to fetch them efficiently.
Ohne PTC sehen Sie im Gespräch zehn aufeinanderfolgende Tool-Aufrufe, jeder als eigenes Ereignis Tool Use: get_stock_price.
Mit PTC sehen Sie:
- Einen einzigen
code_execution-Block mit einem Skript - Tool-Aufrufe aus diesem Skript heraus (in den Debug-Logs sichtbar)
- Dass Claude nur das fertig verarbeitete Endergebnis erhält
Der sichtbare Hinweis in Claude Code ist unauffällig: Achten Sie auf den Status „Running code…“ oder auf ein einzelnes Tool-Use-Ereignis, das mehrere darunterliegende Aufrufe umfasst.
PTC mit der reinen API verwenden
Wenn Sie einen eigenen Agenten bauen, statt Claude Code zu nutzen, aktivieren Sie PTC in den API-Aufrufen so:
from anthropic import Anthropic
client = Anthropic()
response = client.beta.messages.create(
model="claude-sonnet-4-5", # Check current model strings
betas=["advanced-tool-use-2025-11-20"], # Check current beta header
max_tokens=4096,
messages=[
{
"role": "user",
"content": "Get stock prices for AAPL, MSFT, and GOOGL"
}
],
tools=[
# Enable code execution
{
"type": "code_execution_20250825", # Check current version
"name": "code_execution"
},
# Your PTC-enabled tool
{
"name": "get_stock_price",
"description": "Fetch current stock price. Efficient for batch operations.",
"input_schema": {
"type": "object",
"properties": {
"ticker": {"type": "string", "description": "Stock symbol"}
},
"required": ["ticker"]
},
"allowed_callers": ["code_execution_20250825"]
}
]
)
Prüfen Sie beim Verarbeiten der Antwort, ob Tool-Aufrufe ein Feld caller haben. Diese müssen ausgeführt und ihre Ergebnisse in den Code-Execution-Kontext zurückgegeben werden, nicht direkt an Claude.
Häufige Probleme beheben
„Claude ruft die Tools immer noch einzeln auf“
Ursache: In der Tool-Definition fehlt das Feld allowed_callers.
Diagnose: Prüfen Sie das mit dem MCP Inspector:
npx @modelcontextprotocol/inspector
Verbinden Sie sich mit Ihrem Server und sehen Sie sich die Ausgabe von list_tools an. Suchen Sie nach:
{
"name": "get_stock_price",
"allowed_callers": ["code_execution_20250825"]
}
Fehlt allowed_callers, überprüfen Sie Ihre Server-Implementierung.
Workaround: Weisen Sie Claude ausdrücklich an: „Verwende Code Execution, um diese Aufrufe effizient abzuarbeiten.“
„Versions-String nicht erkannt“
Ursache: Der Versionsbezeichner hat sich geändert, seit dieser Artikel geschrieben wurde.
Lösung: Den aktiven Versions-String finden Sie in der aktuellen API-Dokumentation. Diese Bezeichner gelten nur für die Beta und können sich ändern.
„Code Execution nicht verfügbar“
Ursache: Das Code Execution Tool ist in Ihrer Anfrage nicht aktiviert.
Lösung: Nehmen Sie sowohl das Code Execution Tool als auch den Beta-Header auf:
tools=[
{"type": "code_execution_20250825", "name": "code_execution"},
# ... your other tools
]
betas=["advanced-tool-use-2025-11-20"]
„Container abgelaufen“
Ursache: Code-Execution-Container haben eine TTL. Wenn Sie zwischen dem Übermitteln der Tool-Ergebnisse zu lange warten, läuft der Container ab.
Lösung: Verarbeiten Sie Tool-Ergebnisse zügig. Bei lang laufenden Operationen sollten Sie die Arbeit in kleinere Ausführungsblöcke aufteilen.
Sicherheitsaspekte
Bei PTC schreibt Claude Programmcode und führt ihn aus. Das schafft Angriffsfläche für Prompt Injection und unbeabsichtigtes Verhalten.
Eingabevalidierung: Ihre Tools müssen Eingaben prüfen. Wenn Claude aus dem Skript fehlerhafte Daten übergibt, sollte Ihr Tool kontrolliert und mit klaren Fehlermeldungen scheitern.
Ausgabebereinigung: Tool-Ergebnisse, die in die Code Execution zurückfließen, können die weitere Code-Generierung beeinflussen. Geben Sie keine Daten zurück, die als ausführbarer Code oder als Steuerzeichen interpretiert werden könnten.
State Leakage innerhalb der Ausführung: Dieses Risiko übersehen viele Artikel. Innerhalb eines PTC-Ausführungsblocks bleiben Zwischenvariablen bestehen. Bösartige oder fehlerhafte Tool-Ausgaben eines frühen Aufrufs können spätere Schritte vergiften: Die Variablen bleiben im Scope, und Claudes generierter Code kann sie auf unerwartete Weise referenzieren oder verändern. PTC vergrößert den Schadensradius einer einzelnen schlechten Tool-Antwort gegenüber dem normalen Aufruf, bei dem jede Antwort isoliert im Gesprächskontext steht.
Berechtigungsgrenzen: PTC umgeht das Berechtigungssystem von Claude Code nicht. Auch innerhalb eines Skripts halten Tool-Aufrufe, die eine Genehmigung brauchen, die Ausführung an.
Container-Isolation: Code Execution läuft in einem Container mit Sandbox. Von dort gibt es keinen direkten Zugriff auf Ihr Dateisystem, das Netzwerk (außer über definierte Tools) oder andere Systemressourcen. Der Container selbst bleibt jedoch über die Tool-Aufrufe eines Ausführungsblocks hinweg bestehen: Das ist der oben erwähnte Weg für State Leakage.
Wann PTC vielleicht nicht die richtige Wahl ist
PTC ist dem normalen Tool Calling nicht grundsätzlich überlegen. Wägen Sie ab:
Undurchsichtiges Debugging: Wenn bei einer PTC-Ausführung etwas schiefgeht, debuggen Sie generierten Code. Die Orchestrierungslogik, die sonst als Überlegung im Gespräch sichtbar wäre, steckt jetzt in einem Skript, das Sie nicht geschrieben haben. Fehler lassen sich schwerer lokalisieren.
Lücken in der Beobachtbarkeit: Normales Tool Calling hinterlässt einen klaren Audit Trail: Jeder Aufruf erscheint im Gespräch, dazwischen sind Claudes Überlegungen sichtbar. PTC verdichtet das auf einen Codeblock und die Endausgabe. Bei Compliance-sensiblen Workflows kann das ein Problem sein.
Reibung bei Human in the Loop: Wenn Ihr Workflow in Zwischenschritten eine menschliche Freigabe verlangt, passt normales Tool Calling besser. PTC will bis zum Ende durchlaufen; eine Unterbrechung mitten in der Ausführung bedeutet, die Container-Sitzung abzubrechen.
Einfache Aufgaben: Der Mehraufwand von PTC (Skript-Generierung, Container-Verwaltung, Ausführungszustand) lohnt sich bei Batch-Operationen, nicht für das Wetter in einer einzelnen Stadt. Wenn Sie ein Tool nur einmal aufrufen, ist der normale Aufruf einfacher und genauso schnell.
Unberechenbares Tool-Verhalten: Wenn Ihre Tools Nebenwirkungen haben, die eine sorgfältige Reihenfolge oder Rollback-Möglichkeiten verlangen, gibt Ihnen die explizite Orchestrierung im Gespräch mehr Kontrollpunkte.
Fortgeschrittenes Muster: Orchestrierung mehrerer Tools
Besonders stark wird PTC, wenn mehrere Tools orchestriert werden:
> For each of these companies (AAPL, MSFT, GOOGL), get both the stock price
> and company info. Calculate a "value score" as (price / market_cap_billions)
> and rank them. Use code execution to handle this efficiently.
Claude könnte etwa Folgendes generieren:
import asyncio
async def analyze_companies(tickers):
results = []
for ticker in tickers:
# Tools are exposed as async functions in the execution environment
price_data = await get_stock_price(ticker)
info = await get_company_info(ticker)
# Parse market cap (e.g., "3.0T" -> 3000)
cap_str = info["market_cap"]
if cap_str.endswith("T"):
cap_billions = float(cap_str[:-1]) * 1000
elif cap_str.endswith("B"):
cap_billions = float(cap_str[:-1])
else:
cap_billions = 1 # fallback
value_score = price_data["price"] / cap_billions
results.append({
"ticker": ticker,
"price": price_data["price"],
"market_cap": info["market_cap"],
"value_score": round(value_score, 6)
})
# Sort by value score descending
results.sort(key=lambda x: x["value_score"], reverse=True)
return results
tickers = ["AAPL", "MSFT", "GOOGL"]
rankings = asyncio.run(analyze_companies(tickers))
print(rankings)
Sechs Tool-Aufrufe, Datentransformation, sortierte Ausgabe, alles in einem Ausführungsblock. In Claudes Kontext landen nur die fertigen Rankings, nicht sechs einzelne Tool-Ergebnisse samt Überlegungen, wie sie zu kombinieren sind.
Fazit
Programmatic Tool Calling ändert, wie Claude mit externen Tools arbeitet: Aus dem Hin und Her im Gespräch wird eine Orchestrierung per Code. In der Praxis kann PTC Latenz und Tokenverbrauch bei Batch-Operationen und komplexen Workflows mit mehreren Tools deutlich senken, wobei der Nutzen stark von der Art der Aufgabe und den Details der Implementierung abhängt.
Die Umsetzung verlangt Sorgfalt: Das Feld allowed_callers muss richtig gesetzt sein, Code Execution und der passende Beta-Header müssen aktiviert sein, und die Tools müssen so entworfen sein, dass sie von Batch-Ausführung profitieren. Die Nachteile bei Debugging und Beobachtbarkeit sind real, und PTC ist nicht für jeden Workflow die richtige Wahl.
Für Entwickler, die mit Claude Code bauen, ist PTC bereits über MCP-Server verfügbar, die ihre Kompatibilität ausweisen. Für alle, die eigene Agenten auf der API bauen, ist es ein Beta-Feature, mit dem sich Experimente lohnen, besonders bei datenintensiven Operationen, bei denen das Kontextmanagement zum Engpass wird.
Der Agent ruft Ihre Tools nicht nur auf. Er schreibt Code, der sie orchestriert. Ob das die richtige Architektur für Ihren Anwendungsfall ist, hängt davon ab, worauf Sie optimieren.
Aus dem Englischen übersetzt: zum Originalbeitrag