Par défaut, Claude peut appeler plusieurs outils dans une seule réponse. Cette page explique comment exécuter ces appels, comment formater l'historique des messages pour que le parallélisme continue de fonctionner, et comment désactiver l'utilisation d'outils en parallèle lorsque vous en avez besoin. Pour le flux d'appel unique, consultez Gérer les appels d'outils.
Lorsque Claude appelle des outils, la réponse a un stop_reason de tool_use et peut contenir plusieurs blocs tool_use dans un seul tour de l'assistant. La manière dont vous exécutez ces appels relève de votre décision. L'API ne prescrit pas d'ordre d'exécution : vous pouvez exécuter les appels de manière concurrente (Promise.all, asyncio.gather), séquentiellement dans l'ordre où ils apparaissent, ou selon toute combinaison adaptée à vos outils.
Choisissez la stratégie en fonction de ce que font vos outils. Les opérations indépendantes en lecture seule peuvent généralement être exécutées en parallèle sans risque pour réduire la « latency » (latence). Les outils ayant des effets de bord, un état partagé ou des exigences d'ordonnancement gagneront peut-être à être exécutés séquentiellement.
Quelle que soit la stratégie utilisée, renvoyez un tool_result pour chaque bloc tool_use, tous regroupés dans le message utilisateur suivant. Associez chaque résultat à son appel avec tool_use_id, et placez chaque bloc tool_result avant tout contenu textuel dans ce message. Consultez Gérer les appels d'outils pour les règles de formatage complètes. Si vous choisissez de ne pas exécuter un appel particulier (par exemple, parce que vous avez exécuté le lot séquentiellement et qu'un appel précédent a échoué), renvoyez tout de même un tool_result pour celui-ci avec is_error: true et une brève explication.
{
"type": "tool_result",
"tool_use_id": "toolu_02",
"is_error": true,
"content": "Not executed: the preceding write_file call failed."
}Utilisez le Tool Runner pour la plupart des applications : le Tool Runner du SDK gère les réponses contenant plusieurs appels d'outils et formate les résultats pour vous, de sorte que vous n'avez pas à écrire cette gestion vous-même. Utilisez le modèle manuel présenté sur cette page lorsque vous avez besoin d'un contrôle direct sur la manière dont les appels s'exécutent, comme le regroupement personnalisé, l'ordonnancement ou la gestion des erreurs.
Le script suivant envoie une requête qui devrait déclencher des appels d'outils en parallèle, vérifie que la réponse les contient, et formate les résultats d'outils pour que le parallélisme continue de fonctionner. Exécutez-le avec ANTHROPIC_API_KEY défini dans votre environnement :
client = Anthropic()
# Définir les outils
tools = [
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
},
{
"name": "get_time",
"description": "Get the current time in a given timezone",
"input_schema": {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"description": "The timezone, e.g. America/New_York",
}
},
"required": ["timezone"],
},
},
]
# Conversation de test avec appels d'outils parallèles
messages = [
{
"role": "user",
"content": "What's the weather in SF and NYC, and what time is it there?",
}
]
# Effectuer la requête initiale
print("Requesting parallel tool calls...")
response = client.messages.create(
model="claude-opus-4-8", max_tokens=1024, messages=messages, tools=tools
)
# Vérifier les appels d'outils parallèles
tool_uses = [block for block in response.content if block.type == "tool_use"]
print(f"\n✓ Claude made {len(tool_uses)} tool calls")
if len(tool_uses) > 1:
print("✓ Parallel tool calls detected!")
for tool in tool_uses:
print(f" - {tool.name}: {tool.input}")
else:
print("✗ No parallel tool calls detected")
# Simuler l'exécution des outils et formater correctement les résultats
tool_results = []
for tool_use in tool_uses:
if tool_use.name == "get_weather":
if "San Francisco" in str(tool_use.input):
result = "San Francisco: 68°F, partly cloudy"
else:
result = "New York: 45°F, clear skies"
else: # get_time
if "Los_Angeles" in str(tool_use.input):
result = "2:30 PM PST"
else:
result = "5:30 PM EST"
tool_results.append(
{"type": "tool_result", "tool_use_id": tool_use.id, "content": result}
)
# Poursuivre la conversation avec les résultats des outils
messages.extend(
[
{"role": "assistant", "content": response.content},
{"role": "user", "content": tool_results}, # All results in one message!
]
)
# Obtenir la réponse finale
print("\nGetting final response...")
final_response = client.messages.create(
model="claude-opus-4-8", max_tokens=1024, messages=messages, tools=tools
)
final_text = next(
block.text for block in final_response.content if block.type == "text"
)
print(f"\nClaude's response:\n{final_text}")
# Vérifier le formatage
print("\n--- Verification ---")
print(f"✓ Tool results sent in single user message: {len(tool_results)} results")
print("✓ No text before tool results in content array")
print("✓ Conversation formatted correctly for future parallel tool use")Les lignes de résumé à la fin rappellent les deux règles de formatage qui permettent au parallélisme de continuer à fonctionner : chaque résultat d'outil est renvoyé dans un seul message utilisateur, et aucun contenu textuel n'apparaît avant les résultats d'outils dans ce message.
Les modèles Claude 4 effectuent des appels d'outils en parallèle par défaut lorsqu'une requête bénéficie de plusieurs outils. Pour tous les modèles, vous pouvez augmenter la probabilité d'appels d'outils en parallèle avec un prompting ciblé :
L'utilisation d'outils en parallèle est activée par défaut. Pour la désactiver, définissez disable_parallel_tool_use: true dans l'objet tool_choice. Ce n'est pas un paramètre de requête de premier niveau. L'effet dépend du type de tool_choice.
Lorsque le type de tool_choice est auto (la valeur par défaut), définir disable_parallel_tool_use: true signifie que Claude appelle au plus un outil par réponse. Claude peut toujours répondre en texte brut sans appeler aucun outil. Les lignes mises en évidence constituent le seul changement par rapport à une requête d'utilisation d'outils standard :
client = Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
}
],
tool_choice={"type": "auto", "disable_parallel_tool_use": True},
messages=[
{
"role": "user",
"content": "What is the weather in San Francisco and New York?",
}
],
)
print(response.content)Lorsque le type de tool_choice est any ou tool, définir disable_parallel_tool_use: true signifie que Claude appelle exactement un outil. L'exemple suivant utilise any. Le même champ fonctionne avec tool :
client = Anthropic()
response = client.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "Get the current weather in a given location",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA",
}
},
"required": ["location"],
},
}
],
tool_choice={"type": "any", "disable_parallel_tool_use": True},
messages=[
{
"role": "user",
"content": "What is the weather in San Francisco and New York?",
}
],
)
print(response.content)Si Claude n'effectue pas d'appels d'outils en parallèle alors que vous vous y attendez, vérifiez ces problèmes courants :
1. Formatage incorrect des résultats d'outils
Le problème le plus courant est un formatage incorrect des résultats d'outils dans l'historique de conversation. Cela « apprend » à Claude à éviter les appels en parallèle.
Spécifiquement pour l'utilisation d'outils en parallèle :
// Wrong: separate user messages reduce parallel tool use
[
{"role": "assistant", "content": [tool_use_1, tool_use_2]},
{"role": "user", "content": [tool_result_1]},
{"role": "user", "content": [tool_result_2]} // Separate message
]
// Correct: one user message with all results maintains parallel tool use
[
{"role": "assistant", "content": [tool_use_1, tool_use_2]},
{"role": "user", "content": [tool_result_1, tool_result_2]} // Single message
]Consultez Gérer les appels d'outils pour les autres règles de formatage.
2. Prompting insuffisant
Le prompting par défaut peut ne pas être suffisant. Utilisez l'invite système plus forte de la section Maximiser l'utilisation d'outils en parallèle.
3. Mesurer l'utilisation d'outils en parallèle
Pour vérifier que les appels d'outils en parallèle fonctionnent :
messages = [] # Message objects returned by client.messages.create across your run
tool_call_messages = [
msg for msg in messages if any(block.type == "tool_use" for block in msg.content)
]
total_tool_calls = sum(
len([block for block in msg.content if block.type == "tool_use"])
for msg in tool_call_messages
)
avg_tools_per_message = (
total_tool_calls / len(tool_call_messages) if tool_call_messages else 0.0
)
print(f"Average tools per message: {avg_tools_per_message}")
# Devrait être > 1.0 si les appels parallèles fonctionnent4. Les appels d'un lot semblent dépendre les uns des autres
L'ordre d'exécution est votre choix. Si vos outils ont des dépendances d'ordonnancement, exécuter le lot séquentiellement et s'arrêter au premier échec est une stratégie valide : renvoyez is_error: true pour tout appel que vous n'avez pas exécuté. Si vous exécutez en parallèle et qu'un appel échoue parce que son prérequis n'était pas terminé, renvoyez is_error: true avec le message d'erreur naturel. Claude réémettra l'appel au tour suivant. Pour réduire l'apparition conjointe d'appels dépendants, ajoutez ceci à votre invite système : « Only batch tool calls that are independent of each other. »
Utilisez l'abstraction Tool Runner du SDK pour gérer automatiquement la boucle agentique, l'encapsulation des erreurs et la sécurité des types.
Analysez les blocs tool_use, formatez les réponses tool_result et gérez les erreurs avec is_error.
Spécifiez les schémas d'outils, rédigez des descriptions efficaces et contrôlez quand Claude appelle vos outils.
Was this page helpful?