La chiamata programmatica degli strumenti consente a Claude di scrivere codice che chiama i tuoi strumenti in modo programmatico all'interno di un container di esecuzione del codice, invece di richiedere round trip attraverso il modello per ogni invocazione di strumento. Questo riduce la "latency" (latenza) per i flussi di lavoro multi-strumento e diminuisce il consumo di token consentendo a Claude di filtrare o elaborare i dati prima che raggiungano la finestra di contesto del modello. Nei benchmark di ricerca agentica come BrowseComp e DeepSearchQA, che testano la ricerca web multistep e il recupero di informazioni complesse, l'aggiunta della chiamata programmatica degli strumenti sopra gli strumenti di ricerca di base ha migliorato le prestazioni in media dell'11% utilizzando il 24% in meno di token di input (vedi Improved web search with dynamic filtering).
Considera la verifica della conformità al budget per 20 dipendenti: l'approccio tradizionale richiede 20 round trip separati del modello, portando migliaia di voci di spesa nel contesto lungo il percorso. Con la chiamata programmatica degli strumenti, un singolo script esegue tutte le 20 ricerche, filtra i risultati e restituisce solo i dipendenti che hanno superato i loro limiti, riducendo ciò su cui Claude deve ragionare da centinaia di kilobyte a una manciata di righe.
La chiamata programmatica degli strumenti richiede code_execution_20260120 o versioni successive, che è supportato sui seguenti modelli:
| Modello |
|---|
| 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 () |
Per la matrice completa delle versioni dello strumento di esecuzione del codice, vedi la tabella di compatibilità dei modelli dello strumento di esecuzione del codice. La chiamata programmatica degli strumenti è disponibile sulla Claude API, su Claude Platform on AWS e su Microsoft Foundry. Su Microsoft Foundry, la chiamata programmatica degli strumenti richiede un deployment Hosted on Anthropic. Non è attualmente disponibile su Amazon Bedrock o Google Cloud.
Ecco un esempio in cui Claude interroga programmaticamente un database più volte e aggrega i risultati:
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)La risposta si ferma con stop_reason: "tool_use", un ID container e un blocco tool_use per query_database il cui campo caller identifica l'esecuzione del codice che lo ha chiamato. Restituisci il risultato come mostrato nel Passo 3 del flusso di lavoro di esempio in modo che il codice possa terminare.
Quando configuri uno strumento in modo che sia chiamabile dall'esecuzione del codice e Claude decide di usare quello strumento:
tool_useQuesto approccio è particolarmente utile per:
allowed_callersIl campo allowed_callers specifica quali contesti possono invocare uno strumento:
{
"name": "query_database",
"description": "Execute a SQL query against the database",
"input_schema": {
// ...
},
"allowed_callers": ["code_execution_20260120"]
}Valori possibili:
["direct"] - Claude è guidato a chiamare questo strumento direttamente (predefinito se omesso)["code_execution_20260120"] - Claude è guidato a chiamare questo strumento solo dall'interno dell'esecuzione del codice["direct", "code_execution_20260120"] - Claude può chiamare questo strumento direttamente o dall'interno dell'esecuzione del codiceSia "code_execution_20260120" che "code_execution_20260521" sono accettati in allowed_callers e sono intercambiabili: una richiesta che utilizza una qualsiasi delle due versioni dello strumento di esecuzione del codice soddisfa gli strumenti che elencano uno dei due chiamanti. I blocchi di risposta etichettano sempre il chiamante come code_execution_20260120 indipendentemente dalla versione dichiarata nella richiesta.
caller nelle risposteOgni blocco di uso degli strumenti include un campo caller che indica come è stato invocato:
Invocazione diretta (uso degli strumenti tradizionale):
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": { "type": "direct" }
}Invocazione programmatica:
{
"type": "tool_use",
"id": "toolu_xyz789",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_abc123"
}
}Il tool_id è l'id del blocco server_tool_use di esecuzione del codice che ha effettuato la chiamata, quindi puoi abbinare ogni tool_use programmatico all'esecuzione del codice che lo ha prodotto.
La chiamata programmatica degli strumenti utilizza gli stessi container dell'esecuzione del codice:
container, insieme a un timestamp expires_atexpires_at ti dice quanto tempo rimane al container. I container inattivi vengono attualmente recuperati dopo circa 5 minuti, e nessun container può essere riutilizzato più di 30 giorni dopo la sua creazione.Ecco come funziona un flusso completo di chiamata programmatica degli strumenti:
Invia una richiesta con l'esecuzione del codice e uno strumento che consente la chiamata programmatica. Per abilitare la chiamata programmatica, aggiungi il campo allowed_callers alla definizione del tuo strumento.
La forma della richiesta è identica all'esempio di Avvio rapido: includi code_execution nella tua lista di strumenti, aggiungi allowed_callers: ["code_execution_20260120"] a qualsiasi strumento che vuoi che Claude invochi dal codice e invia il tuo messaggio utente. I passi rimanenti in questo flusso di lavoro utilizzano il messaggio utente "Query customer purchase history from the last quarter and identify our top 5 customers by revenue".
Claude scrive codice che chiama il tuo strumento. L'API si mette in pausa e restituisce:
{
"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"
}Invia la cronologia completa della conversazione più il risultato del tuo strumento. Tre dettagli sono importanti in questa richiesta:
tool_result. Vedi Restrizioni di formattazione dei messaggi.container dalla risposta in pausa. L'API rifiuta una continuazione che ha chiamate programmatiche di strumenti in sospeso ma nessun ID del container.tools della richiesta originale. Lo strumento di esecuzione del codice deve essere ancora presente affinché il codice in pausa riprenda, e gli strumenti che invii in questa richiesta sono le definizioni che Claude e il codice in esecuzione possono usare per il resto del turno.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}, ...]',
}
],
},
],
# Stesso array di strumenti della richiesta originale
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)Il codice riprende da dove si era fermato ed elabora il tuo risultato. Ogni risposta di continuazione si mette nuovamente in pausa con altri blocchi tool_use programmatici, oppure completa l'esecuzione del codice e consente a Claude di continuare il turno (Passo 5). Controlla stop_reason e il caller di ogni blocco tool_use per distinguere i due casi: una risposta che si mette in pausa per te ha stop_reason: "tool_use" e un blocco tool_use il cui caller indica una versione di esecuzione del codice, e tu ripeti il Passo 3 con un tool_result per ogni chiamata programmatica in sospeso in un unico messaggio utente.
Una volta completata l'esecuzione del codice, Claude fornisce la risposta finale:
{
"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 può scrivere codice che elabora più elementi in modo efficiente:
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)
# Elabora i risultati in modo programmatico
top_region = max(results.items(), key=lambda x: x[1])
print(f"Top region: {top_region[0]} with ${top_region[1]:,} in revenue")Questo pattern:
Claude può interrompere l'elaborazione non appena i criteri di successo sono soddisfatti:
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)Quando l'esecuzione del codice chiama uno strumento:
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_xyz789"
}
}Il risultato del tuo strumento viene passato indietro al codice in esecuzione:
{
"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}, ...]"
}
]
}Quando tutte le chiamate degli strumenti sono soddisfatte e il codice è completato:
{
"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": []
}
}| Errore | Dove appare | Descrizione | Soluzione |
|---|---|---|---|
invalid_tool_input | error_code sul blocco di errore code_execution_tool_result nella risposta | Parametri non validi sono stati passati allo strumento di esecuzione del codice | Vedi gli errori dello strumento di esecuzione del codice |
invalid_request_error (su tool_choice) | Risposta di errore HTTP 400 | tool_choice indica uno strumento il cui allowed_callers non include "direct" | Aggiungi "direct" agli allowed_callers di quello strumento, oppure rimuovi lo strumento da tool_choice e lascia che Claude lo invochi dal codice |
Se il risultato del tuo strumento non arriva entro circa 4 minuti, la chiamata in sospeso solleva un TimeoutError all'interno del codice in esecuzione di Claude. Claude vede l'errore in stderr e tipicamente riprova la chiamata:
{
"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": []
}
}Per prevenire i timeout:
expires_at nelle risposteSe il tuo strumento restituisce un errore:
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "Error: Query timeout - table lock exceeded 30 seconds"
}Il codice di Claude riceve questo errore e può gestirlo in modo appropriato.
strict: true non sono supportati con la chiamata programmaticatool_choicedisable_parallel_tool_use: true non è supportato con la chiamata programmaticaGli strumenti personalizzati il cui input_schema contiene un $ref ricorsivo (un ciclo di riferimento, come uno schema che fa riferimento a se stesso) non possono essere abilitati per la chiamata programmatica. Includere una versione dello strumento di esecuzione del codice in allowed_callers per un tale strumento causa il fallimento della richiesta con un 400 invalid_request_error il cui messaggio contiene Circular $ref detected. Lo stesso schema è accettato per la chiamata diretta degli strumenti.
Per aggirare questo problema, fai una delle seguenti cose:
allowed_callers (o impostandolo su ["direct"]). Gli altri strumenti nella stessa richiesta possono comunque usare la chiamata programmatica.description del livello più interno, oppure sostituisci la proprietà ricorsiva con un semplice {"type": "object"} la cui description spiega la forma prevista.I seguenti strumenti non possono essere chiamati in modo programmatico:
Quando rispondi a chiamate programmatiche degli strumenti, ci sono requisiti di formattazione rigorosi:
Risposte con solo risultati degli strumenti: Se ci sono chiamate programmatiche di strumenti in sospeso in attesa di risultati, il tuo messaggio di risposta deve contenere solo blocchi tool_result. Non puoi includere alcun contenuto testuale, nemmeno dopo i risultati degli strumenti.
Non valido - Non è possibile includere testo quando si risponde a chiamate programmatiche degli strumenti:
{
"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?" }
]
}Valido - Solo risultati degli strumenti quando si risponde a chiamate programmatiche degli strumenti:
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
}
]
}Questa restrizione si applica solo quando si risponde a chiamate programmatiche (esecuzione del codice) degli strumenti. Per le normali chiamate di strumenti lato client, puoi includere contenuto testuale dopo i risultati degli strumenti.
Contenuto del risultato dello strumento solo testuale: Il content di ogni tool_result che risponde a una chiamata programmatica deve essere una stringa o blocchi text. I tipi di blocco di contenuto immagine, documento e altri vengono rifiutati.
Le chiamate programmatiche degli strumenti sono soggette agli stessi limiti di velocità delle normali chiamate degli strumenti. Ogni chiamata di strumento dall'esecuzione del codice conta come un'invocazione separata.
Quando implementi strumenti definiti dall'utente che verranno chiamati in modo programmatico:
La chiamata programmatica degli strumenti riduce il consumo di token in tre modi:
Ad esempio, chiamare 10 strumenti direttamente utilizza circa 10 volte i token rispetto a chiamarli in modo programmatico e restituire un riepilogo.
Nelle valutazioni interne di Anthropic su un modello Claude di produzione:
tools contiene da 10 a 49 definizioni di strumenti vedono risparmi tipici di token dal 20% al 40% con la chiamata programmatica degli strumenti abilitata.I risparmi effettivi variano con la forma del carico di lavoro. Vedi Quando usare la chiamata programmatica.
La chiamata programmatica degli strumenti utilizza gli stessi prezzi dell'esecuzione del codice. Vedi i prezzi dell'esecuzione del codice per i dettagli.
La chiamata programmatica degli strumenti scambia un piccolo overhead fisso (avvio del container, generazione dello script) con grandi risparmi sui token dei risultati degli strumenti e sui round trip del modello. Se questo scambio conviene dipende dalla forma del carico di lavoro.
Adatto:
Poco adatto:
Se non sei sicuro, misura i token di input fatturati con e senza allowed_callers su un campione rappresentativo del tuo traffico prima di abilitarlo su larga scala.
invalid_request_error quando si imposta tool_choice
tool_choice non può indicare uno strumento il cui allowed_callers omette "direct". Aggiungi "direct" agli allowed_callers di quello strumento, oppure rimuovi lo strumento da tool_choice e lascia che Claude lo invochi dal codice.Scadenza del container
expires_at della risposta in pausa. Il codice di Claude smette di attendere un risultato dopo circa 4 minuti, e i container inattivi vengono attualmente recuperati dopo circa 5 minuti.Risultato dello strumento non analizzato correttamente
caller per confermare l'invocazione programmaticaClaude è addestrato su grandi quantità di codice, quindi presentare gli strumenti come funzioni Python chiamabili gli consente di sfruttare questo punto di forza:
La chiamata programmatica degli strumenti è un pattern generalizzabile che può anche essere implementato sulla tua infrastruttura. Ecco come si confrontano gli approcci:
Fornisci a Claude uno strumento di esecuzione del codice e descrivi quali funzioni sono disponibili in quell'ambiente. Quando Claude invoca lo strumento con il codice, la tua applicazione lo esegue localmente dove quelle funzioni sono definite.
Vantaggi:
Svantaggi:
Usalo quando: La tua applicazione può eseguire in sicurezza codice arbitrario, vuoi l'implementazione più piccola e l'offerta gestita di Anthropic non soddisfa le tue esigenze.
Stesso approccio dal punto di vista di Claude, ma il codice viene eseguito in un container sandbox con restrizioni di sicurezza (ad esempio, nessun egress di rete). Se i tuoi strumenti richiedono risorse esterne, avrai bisogno di un protocollo per eseguire le chiamate degli strumenti al di fuori della sandbox.
Vantaggi:
Svantaggi:
Usalo quando: La sicurezza è critica e la soluzione gestita di Anthropic non soddisfa i tuoi requisiti.
La chiamata programmatica degli strumenti di Anthropic è una versione gestita dell'esecuzione sandbox con un ambiente Python opinionato ottimizzato per Claude. Anthropic gestisce la gestione dei container, l'esecuzione del codice e la comunicazione sicura delle invocazioni degli strumenti.
Vantaggi:
Considera l'uso della soluzione gestita di Anthropic se stai usando la Claude API, Claude Platform on AWS o Microsoft Foundry. Su Microsoft Foundry, la chiamata programmatica degli strumenti richiede un deployment Hosted on Anthropic.
La chiamata programmatica degli strumenti è costruita sull'infrastruttura di esecuzione del codice e utilizza gli stessi container sandbox. I dati del container, inclusi gli artefatti di esecuzione e gli output, vengono conservati per un massimo di 30 giorni.
Per l'idoneità ZDR in tutte le funzionalità, vedi API e conservazione dei dati.
Esegui lo streaming degli input degli strumenti senza buffering JSON lato server per applicazioni sensibili alla latency.
Esegui codice Python e bash in un container sandbox per analizzare dati, generare file e iterare sulle soluzioni.
Connetti Claude a strumenti e API esterni. Scopri dove vengono eseguiti gli strumenti, quando Claude li chiama e quale strumento si adatta al tuo compito.
Specifica gli schemi degli strumenti, scrivi descrizioni efficaci e controlla quando Claude chiama i tuoi strumenti.
Was this page helpful?