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 à 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 d'assistant. La manière dont vous exécutez ces appels est 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 dans toute combinaison qui convient à vos outils.
Choisissez la stratégie en fonction de ce que font vos outils. Les opérations indépendantes et en lecture seule peuvent généralement être exécutées en parallèle en toute sécurité pour une « latency » (latence) plus faible. Les outils avec des effets de bord, un état partagé ou des exigences d'ordonnancement peuvent être mieux exécutés séquentiellement.
Quelle que soit la stratégie que vous utilisez, retournez un tool_result pour chaque bloc tool_use, tous ensemble 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é), retournez quand 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."
}Le script suivant envoie une requête qui devrait déclencher des appels d'outils parallèles, 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"],
},
},
]
# Tester la conversation avec des 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-5", 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-5", 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 reformulent les deux règles de formatage qui maintiennent le parallélisme en fonctionnement : chaque résultat d'outil est retourné 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 et ultérieurs effectuent des appels d'outils parallèles 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 parallèles 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 à l'intérieur de 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 en surbrillance sont le seul changement par rapport à une requête d'utilisation d'outils standard :
client = Anthropic()
response = client.messages.create(
model="claude-opus-5",
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-5",
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 parallèles lorsque c'est attendu, vérifiez ces problèmes courants :
1. Formatage incorrect des résultats d'outils
Le problème le plus courant est le formatage incorrect des résultats d'outils dans l'historique de la conversation. Cela « apprend » à Claude à éviter les appels parallèles.
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 faible
Le prompting par défaut peut ne pas être suffisant. Utilisez l'invite système plus forte de 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 parallèles 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 : retournez 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é, retournez 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ûreté 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?