Tool Choice et contrôle des outils
Mis à jour le 29 juillet 2026
Objectifs
- Comprendre le paramètre
tool_choice - Contrôler quand et comment Claude utilise les outils
Le paramètre tool_choice
Par défaut, Claude arbitre seul : il examine la demande, la confronte aux outils déclarés et décide s’il en appelle un. Cette autonomie convient à la majorité des applications conversationnelles, mais elle devient un problème dès que votre chaîne de traitement attend un format précis ou qu’une action doit impérativement être déclenchée. Le paramètre tool_choice vous rend cet arbitrage. Il accepte trois valeurs.
| Valeur | Comportement |
|---|---|
{"type": "auto"} | Claude décide librement (défaut) |
{"type": "any"} | Claude doit utiliser un outil (n’importe lequel) |
{"type": "tool", "name": "nom_outil"} | Claude doit utiliser l’outil spécifié |
Mode auto (défaut)
Le mode auto correspond au comportement implicite ; l’écrire explicitement ne change rien mais documente l’intention dans le code. Posez une question de culture générale à un assistant équipé d’une calculatrice et d’une API météo : le modèle répond de lui-même, sans solliciter quoi que ce soit.
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1000,
tools=tools,
tool_choice={"type": "auto"}, # Optionnel, c'est le défaut
messages=[{"role": "user", "content": "Quelle est la capitale de la France ?"}]
)
# Claude répond directement sans outil (pas nécessaire)
Forcer l’utilisation d’un outil
Nommer un outil supprime toute latitude au modèle : il l’appellera, et il lui reste seulement à déterminer les paramètres. C’est le mode que vous avez employé pour l’analyse de sentiment, et c’est aussi celui qu’on utilise pour garantir qu’un calcul passe bien par la calculatrice plutôt que par l’arithmétique approximative du modèle.
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1000,
tools=tools,
tool_choice={"type": "tool", "name": "calculator"},
messages=[{"role": "user", "content": "Combien font 245 * 873 ?"}]
)
# Claude DOIT utiliser la calculatrice
Forcer l’utilisation de n’importe quel outil
Le mode any occupe une position intermédiaire : l’appel d’outil est obligatoire, mais le choix reste au modèle. On l’emploie dans les agents dont chaque tour doit produire une action — par exemple un routeur qui doit toujours orienter la demande vers l’un de ses services.
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=1000,
tools=tools,
tool_choice={"type": "any"},
messages=[{"role": "user", "content": "J'ai besoin d'aide"}]
)
# Claude DOIT utiliser au moins un outil
Résumons le critère de décision. Le mode auto convient au cas général, où l’on fait confiance au jugement du modèle. Le ciblage par nom s’impose quand vous savez d’avance quel outil est nécessaire, notamment pour forcer une sortie JSON structurée. Le mode any sert lorsque vous exigez qu’un outil soit appelé sans savoir lequel — et il demande davantage de prudence, comme le montre le quiz en fin de leçon.
Appels d’outils multiples
Une seule réponse de Claude peut contenir plusieurs demandes d’outils. Si un utilisateur demande la météo et les actualités du jour, le modèle n’attend pas d’avoir la première information pour réclamer la seconde : sa réponse comporte alors un bloc de texte introductif suivi de deux ToolUseBlock distincts, chacun avec son propre identifiant. Votre code doit itérer sur l’ensemble du contenu, exécuter chaque outil et rassembler tous les résultats dans une même liste, qui repartira dans un unique message user. Omettre l’un des résultats fait échouer la requête suivante.
# Claude peut répondre avec 2 demandes d'outils
# response.content = [
# TextBlock(text="Je vais chercher les infos..."),
# ToolUseBlock(id="toolu_1", name="get_weather", input={...}),
# ToolUseBlock(id="toolu_2", name="get_news", input={...})
# ]
# Vous devez renvoyer un résultat pour CHAQUE outil
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": str(result)
})
messages.append({"role": "user", "content": tool_results})
Bonnes pratiques
La qualité d’une intégration Tool Use se joue moins dans le code de la boucle que dans la façon dont vous décrivez vos outils. Une description précise, qui dit ce que fait l’outil mais aussi dans quelles circonstances y recourir, vaut mieux que dix lignes de system prompt correctives ; c’est la première chose à retravailler quand Claude choisit mal. Les noms suivent la même logique : search_customer_orders renseigne le modèle, tool3 ne lui apprend rien.
Sur le plan technique, vérifiez que chaque input_schema est un JSON Schema valide, faute de quoi l’API rejette la définition. Prévoyez également le chemin d’échec de vos fonctions : quand un outil tombe en erreur, ne laissez pas remonter une exception brute mais renvoyez à Claude un message explicite, du type « Aucun client trouvé pour cet identifiant ». Le modèle sait exploiter cette information pour reformuler sa demande ou expliquer la situation à l’utilisateur. Enfin, gardez la liste d’outils courte et pertinente : au-delà d’un certain nombre, les frontières entre outils s’estompent et le taux de mauvais choix augmente.
Un cas limite : any sans outil pertinent
Une dernière vérification avant de passer au chatbot complet. Que se passe-t-il si vous fixez tool_choice à {"type": "any"} alors qu’aucun outil disponible ne correspond à la question posée ?
Voir la réponse
Claude sera forcé d’utiliser un outil, même si aucun n’est pertinent. Il choisira l’outil le plus “proche” de la question et l’appellera avec des paramètres qui peuvent ne pas avoir de sens. C’est pourquoi le mode any doit être utilisé avec précaution.