Was this page helpful?
L'appel d'outils programmatique permet à Claude d'écrire du code qui appelle vos outils de manière programmatique dans un conteneur d'exécution de code, plutôt que de nécessiter des allers-retours via le modèle pour chaque invocation d'outil. Cela réduit la latence pour les flux de travail multi-outils et diminue la consommation de tokens en permettant à Claude de filtrer ou de traiter les données avant qu'elles n'atteignent la fenêtre de contexte du modèle. Sur des benchmarks de recherche agentique comme BrowseComp et DeepSearchQA, qui testent la recherche web en plusieurs étapes et la récupération d'informations complexes, l'ajout de l'appel d'outils programmatique par-dessus les outils de recherche de base a été le facteur clé qui a pleinement libéré les performances des agents.
La différence s'amplifie rapidement dans les flux de travail réels. Considérez la vérification de la conformité budgétaire pour 20 employés : l'approche traditionnelle nécessite 20 allers-retours séparés avec le modèle, en extrayant des milliers de lignes de dépenses dans le contexte au passage. Avec l'appel d'outils programmatique, un seul script effectue les 20 recherches, filtre les résultats et ne renvoie que les employés ayant dépassé leurs limites, réduisant ce que Claude doit analyser de centaines de kilo-octets à quelques lignes.
Pour un examen plus approfondi des coûts d'inférence et de contexte que l'appel d'outils programmatique résout, voir Advanced tool use.
Cette fonctionnalité nécessite que l'outil d'exécution de code soit activé.
This feature is not eligible for Zero Data Retention (ZDR). Data is retained according to the feature's standard retention policy.
Pour les détails de compatibilité des modèles et des versions d'outils, voir la Référence des outils. L'appel d'outils programmatique est disponible via l'API Claude et Microsoft Foundry.
Voici un exemple simple où Claude interroge programmatiquement une base de données plusieurs fois et agrège les résultats :
Lorsque vous configurez un outil pour qu'il soit appelable depuis l'exécution de code et que Claude décide d'utiliser cet outil :
tool_useCette approche est particulièrement utile pour :
Les outils personnalisés sont convertis en fonctions Python asynchrones pour prendre en charge l'appel d'outils en parallèle. Lorsque Claude écrit du code qui appelle vos outils, il utilise await (par exemple, result = await query_database("<sql>")) et inclut automatiquement la fonction wrapper asynchrone appropriée.
Le wrapper asynchrone est omis des exemples de code dans cette documentation pour plus de clarté.
allowed_callersLe champ allowed_callers spécifie quels contextes peuvent invoquer un outil :
{
"name": "query_database",
"description": "Execute a SQL query against the database",
"input_schema": {
// ...
},
"allowed_callers": ["code_execution_20260120"]
}Valeurs possibles :
["direct"] - Seul Claude peut appeler cet outil directement (valeur par défaut si omis)["code_execution_20260120"] - Uniquement appelable depuis l'exécution de code["direct", "code_execution_20260120"] - Appelable à la fois directement et depuis l'exécution de codeChoisissez soit ["direct"] soit ["code_execution_20260120"] pour chaque outil plutôt que d'activer les deux, car cela fournit des indications plus claires à Claude sur la meilleure façon d'utiliser l'outil.
caller dans les réponsesChaque bloc d'utilisation d'outil inclut un champ caller indiquant comment il a été invoqué :
Invocation directe (utilisation traditionnelle des outils) :
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": { "type": "direct" }
}Invocation programmatique :
{
"type": "tool_use",
"id": "toolu_xyz789",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_abc123"
}
}Le tool_id fait référence à l'outil d'exécution de code qui a effectué l'appel programmatique.
L'appel d'outils programmatique utilise les mêmes conteneurs que l'exécution de code :
containerLorsqu'un outil est appelé de manière programmatique et que le conteneur attend le résultat de votre outil, vous devez répondre avant l'expiration du conteneur. Surveillez le champ expires_at. Si le conteneur expire, Claude peut traiter l'appel d'outil comme ayant expiré et le réessayer.
Voici comment fonctionne un flux complet d'appel d'outils programmatique :
Envoyez une requête avec l'exécution de code et un outil qui autorise l'appel programmatique. Pour activer l'appel programmatique, ajoutez le champ allowed_callers à la définition de votre outil.
Fournissez des descriptions détaillées du format de sortie de votre outil dans la description de l'outil. Si vous spécifiez que l'outil renvoie du JSON, Claude tente de désérialiser et de traiter le résultat dans le code. Plus vous fournissez de détails sur le schéma de sortie, mieux Claude peut gérer la réponse de manière programmatique.
La forme de la requête est identique à l'exemple du Démarrage rapide : incluez code_execution dans votre liste d'outils, ajoutez allowed_callers: ["code_execution_20260120"] à tout outil que vous souhaitez que Claude invoque depuis le code, et envoyez votre message utilisateur.
Claude écrit du code qui appelle votre outil. L'API s'interrompt et renvoie :
{
"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": "results = await query_database('<sql>')\ntop_customers = sorted(results, 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": "2025-01-15T14:30:00Z"
},
"stop_reason": "tool_use"
}Incluez l'historique complet de la conversation ainsi que le résultat de votre outil :
L'exécution du code continue et traite les résultats. Si des appels d'outils supplémentaires sont nécessaires, répétez l'étape 3 jusqu'à ce que tous les appels d'outils soient satisfaits.
Une fois l'exécution du code terminée, Claude fournit la réponse finale :
{
"content": [
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "Top 5 customers by revenue:\n1. Customer C1: $45,000\n2. Customer C2: $38,000\n3. Customer C5: $32,000\n4. Customer C8: $28,500\n5. Customer C3: $24,000",
"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 peut écrire du code qui traite plusieurs éléments efficacement :
async def _claude_code():
regions = ["West", "East", "Central", "North", "South"]
results = {}
for region in regions:
data = await query_database(f"<sql for {region}>")
results[region] = sum(row["revenue"] for row in data)
# Process results programmatically
top_region = max(results.items(), key=lambda x: x[1])
print(f"Top region: {top_region[0]} with ${top_region[1]:,} in revenue")
Ce modèle :
Claude peut arrêter le traitement dès que les critères de succès sont atteints :
async def _claude_code():
endpoints = ["us-east", "eu-west", "apac"]
for endpoint in endpoints:
status = await check_health(endpoint)
if status == "healthy":
print(f"Found healthy endpoint: {endpoint}")
break # Stop early, don't check remaining
async def _claude_code():
file_info = await get_file_info(path)
if file_info["size"] < 10000:
content = await read_full_file(path)
else:
content = await read_file_summary(path)
print(content)
async def _claude_code():
logs = await fetch_logs(server_id)
errors = [log for log in logs if "ERROR" in log]
print(f"Found {len(errors)} errors")
for error in errors[-10:]: # Only return last 10 errors
print(error)
Lorsque l'exécution du code appelle un outil :
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "query_database",
"input": { "sql": "<sql>" },
"caller": {
"type": "code_execution_20260120",
"tool_id": "srvtoolu_xyz789"
}
}Le résultat de votre outil est transmis au code en cours d'exécution :
{
"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}, ...]"
}
]
}Lorsque tous les appels d'outils sont satisfaits et que le code se termine :
{
"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": []
}
}| Erreur | Description | Solution |
|---|---|---|
invalid_tool_input | L'entrée de l'outil ne correspond pas au schéma | Validez le input_schema de votre outil |
tool_not_allowed | L'outil n'autorise pas le type d'appelant demandé | Vérifiez que allowed_callers inclut les bons contextes |
missing_beta_header | En-tête bêta requis non fourni (Bedrock et Vertex AI uniquement ; l'appel d'outil programmatique est en disponibilité générale sur l'API Claude de première partie) | Ajoutez les en-têtes bêta requis à votre requête |
Si votre outil met trop de temps à répondre, l'exécution du code reçoit une TimeoutError. Claude voit cela dans stderr et effectue généralement une nouvelle tentative :
{
"type": "code_execution_tool_result",
"tool_use_id": "srvtoolu_abc123",
"content": {
"type": "code_execution_result",
"stdout": "",
"stderr": "TimeoutError: Calling tool ['query_database'] timed out.",
"return_code": 0,
"content": []
}
}Pour éviter les délais d'expiration :
expires_at dans les réponsesSi votre outil renvoie une erreur :
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "Error: Query timeout - table lock exceeded 30 seconds"
}Le code de Claude reçoit cette erreur et peut la gérer de manière appropriée.
strict: true ne sont pas pris en charge avec l'appel programmatiquetool_choicedisable_parallel_tool_use: true n'est pas pris en charge avec l'appel programmatiqueLes outils suivants ne peuvent pas actuellement être appelés de manière programmatique, mais la prise en charge pourrait être ajoutée dans les versions futures :
Lors de la réponse aux appels d'outils programmatiques, des exigences de formatage strictes s'appliquent :
Réponses contenant uniquement des résultats d'outils : S'il y a des appels d'outils programmatiques en attente de résultats, votre message de réponse doit contenir uniquement des blocs tool_result. Vous ne pouvez pas inclure de contenu textuel, même après les résultats des outils.
Invalide - Impossible d'inclure du texte lors de la réponse aux appels d'outils programmatiques :
{
"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?" }
]
}Valide - Uniquement des résultats d'outils lors de la réponse aux appels d'outils programmatiques :
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_01",
"content": "[{\"customer_id\": \"C1\", \"revenue\": 45000}]"
}
]
}Cette restriction s'applique uniquement lors de la réponse aux appels d'outils programmatiques (exécution de code). Pour les appels d'outils côté client classiques, vous pouvez inclure du contenu textuel après les résultats des outils.
Les appels d'outils programmatiques sont soumis aux mêmes limites de débit que les appels d'outils classiques. Chaque appel d'outil provenant de l'exécution de code compte comme une invocation distincte.
Lors de l'implémentation d'outils définis par l'utilisateur qui seront appelés de manière programmatique :
L'appel d'outil programmatique peut réduire considérablement la consommation de tokens :
Par exemple, appeler 10 outils directement utilise environ 10 fois plus de tokens que de les appeler de manière programmatique et de renvoyer un résumé.
L'appel d'outil programmatique utilise la même tarification que l'exécution de code. Consultez la tarification de l'exécution de code pour plus de détails.
Comptage des tokens pour les appels d'outils programmatiques : Les résultats des outils provenant d'invocations programmatiques ne comptent pas dans votre utilisation de tokens d'entrée/sortie. Seul le résultat final de l'exécution du code et la réponse de Claude sont comptabilisés.
Bons cas d'utilisation :
Cas d'utilisation moins idéaux :
Erreur "Tool not allowed"
"allowed_callers": ["code_execution_20260120"]Expiration du conteneur
expires_at dans les réponsesRésultat de l'outil non analysé correctement
caller pour confirmer l'invocation programmatiqueLa formation de Claude inclut une exposition extensive au code, ce qui le rend efficace pour raisonner et enchaîner les appels de fonctions. Lorsque les outils sont présentés comme des fonctions appelables dans un environnement d'exécution de code, Claude peut tirer parti de cette force pour :
Cette approche permet des flux de travail qui seraient impraticables avec l'utilisation traditionnelle des outils (comme le traitement de fichiers de plus d'1 million de tokens) en permettant à Claude de travailler avec les données de manière programmatique plutôt que de tout charger dans le contexte de la conversation.
L'appel d'outil programmatique est un modèle généralisable qui peut être implémenté en dehors de l'exécution de code gérée par Anthropic. Voici un aperçu des approches :
Fournissez à Claude un outil d'exécution de code et décrivez les fonctions disponibles dans cet environnement. Lorsque Claude invoque l'outil avec du code, votre application l'exécute localement là où ces fonctions sont définies.
Avantages :
Inconvénients :
À utiliser lorsque : Votre application peut exécuter du code arbitraire en toute sécurité, vous souhaitez une solution simple, et l'offre gérée d'Anthropic ne correspond pas à vos besoins.
Même approche du point de vue de Claude, mais le code s'exécute dans un conteneur en bac à sable avec des restrictions de sécurité (par exemple, pas d'accès réseau sortant). Si vos outils nécessitent des ressources externes, vous aurez besoin d'un protocole pour exécuter les appels d'outils en dehors du bac à sable.
Avantages :
Inconvénients :
À utiliser lorsque : La sécurité est critique et la solution gérée d'Anthropic ne correspond pas à vos exigences.
L'appel d'outil programmatique d'Anthropic est une version gérée de l'exécution en bac à sable avec un environnement Python opinionné optimisé pour Claude. Anthropic gère la gestion des conteneurs, l'exécution du code et la communication sécurisée des invocations d'outils.
Avantages :
Envisagez d'utiliser la solution gérée d'Anthropic si vous utilisez l'API Claude.
L'appel d'outil programmatique est construit sur l'infrastructure d'exécution de code et utilise les mêmes conteneurs en bac à sable. Les données des conteneurs, y compris les artefacts d'exécution et les sorties, sont conservées jusqu'à 30 jours.
Pour l'éligibilité ZDR sur toutes les fonctionnalités, consultez API et conservation des données.
curl https://api.anthropic.com/v1/messages \
--header "x-api-key: $ANTHROPIC_API_KEY" \
--header "anthropic-version: 2023-06-01" \
--header "content-type: application/json" \
--data '{
"model": "claude-opus-4-6",
"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"]
}
]
}'ant messages create <<'YAML'
model: claude-opus-4-6
max_tokens: 4096
container: container_xyz789
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}, ...]
tools: [...]
YAML