Gérer les réponses tool use
Sur cette page
Fonction prête, schéma prêt : envoyons le tout à Bedrock et regardons ce qui revient. Quand Claude décide d’utiliser un outil, sa réponse a une forme particulière qu’il faut savoir lire avant d’écrire la boucle d’exécution.
Déclarer les outils : toolConfig
Avec l’API Converse, les outils passent dans le paramètre toolConfig, sous la clé tools. Le champ facultatif toolChoice règle l’obligation d’appeler un outil :
toolChoice | Comportement |
|---|---|
{"auto": {}} | Claude décide s’il appelle un outil (par défaut) |
{"any": {}} | Claude doit appeler au moins un outil, de son choix |
{"tool": {"name": "..."}} | Claude doit appeler l’outil nommé |
Forcer un outil précis est utile pour tester le chemin de code que vous venez d’écrire. Mais tous les modèles ne l’acceptent pas : selon la documentation AWS, Claude Opus 5.5, Fable 5.1 et Mythos 5.1 refusent any et tool avec une ValidationException, et la fiche de Sonnet 5.5 n’autorise que auto et none. Claude Haiku 5.5, le modèle du cours, les accepte ; un appel forcé se fait alors sans réflexion préalable.
Des utilitaires plus souples
Les messages vont désormais contenir des listes de blocs, plus seulement du texte. Rendons les utilitaires flexibles, comme le cours officiel :
def add_user_message(messages, content):
if isinstance(content, str):
content = [{"text": content}]
messages.append({"role": "user", "content": content})
def add_assistant_message(messages, content):
if isinstance(content, str):
content = [{"text": content}]
messages.append({"role": "assistant", "content": content})
Une chaîne est emballée comme avant ; une liste de blocs passe telle quelle. La fonction chat accepte les outils et renvoie le texte et la liste complète des blocs :
def chat(messages, system=None, tools=None, tool_choice=None):
params = {"modelId": model_id, "messages": messages}
if system:
params["system"] = [{"text": system}]
if tools:
params["toolConfig"] = {"tools": tools}
if tool_choice:
params["toolConfig"]["toolChoice"] = {"tool": {"name": tool_choice}}
response = client.converse(**params)
parts = response["output"]["message"]["content"]
text = "\n".join(part["text"] for part in parts if "text" in part)
return text, parts
Le cours officiel lit encore content[0]["text"] à cet endroit. Or une réponse à outil peut commencer par un bloc de réflexion, ou ne contenir aucun texte du tout : on filtre donc les blocs de texte. Et on renvoie parts, la réponse brute, car c’est elle que la suite devra archiver et traiter.
Une réponse en plusieurs blocs
messages = []
add_user_message(messages, "Quelle heure est-il ?")
text, parts = chat(messages, tools=[get_current_datetime_schema])
Quand Claude veut un outil, la liste parts contient en général :
- un bloc
reasoningContent, la trace de sa réflexion, avec Haiku 5.5 ; - souvent un bloc
text, une phrase pour l’humain, du type « Je regarde l’heure » ; - un ou plusieurs blocs
toolUse, pour votre code.
Un bloc toolUse contient trois champs :
toolUseId: l’identifiant de la demande, à renvoyer avec le résultat. Pour les outils déclarés danstoolConfig, Bedrock le génère : il commence partooluse_;name: le nom de l’outil, tel que déclaré dans le schéma ;input: le dictionnaire des arguments.
L’historique et la raison d’arrêt
Le déroulé complet est le suivant : message utilisateur, réponse de Claude avec la demande d’outil, message utilisateur avec le résultat, réponse finale. Gardez la réponse de Claude telle quelle dans l’historique, blocs de réflexion compris : la documentation d’Anthropic demande de renvoyer ces blocs sans modification avec les résultats d’outils.
Enfin, le champ stopReason de la réponse vaut tool_use quand Claude attend un résultat d’outil au lieu de répondre. Notre chat ne le renvoie pas encore ; pour l’instant, repérez simplement un bloc qui contient la clé toolUse. La leçon 28 ajoutera stopReason au retour.
À vous de jouer
Lire une demande d’outil. Posez « Quelle heure est-il ? » avec l’outil, puis affichez chaque bloc de parts avec print(json.dumps(part, indent=2, ensure_ascii=False)). Repérez le toolUseId, le nom et les arguments. Recommencez avec tool_choice="get_current_datetime" et la question « Bonjour ! » : que change le choix forcé ?
Sources officielles : Handling tool use responses (Claude Academy) · Use a tool to complete an Amazon Bedrock model response et Anthropic Claude tool use (documentation AWS)
Points clés à retenir
- Les outils passent dans
toolConfig.tools;toolChoicevautautopar défaut. - Forcer un outil (
any,tool) n’est pas accepté par tous les modèles ; Haiku 5.5 l’accepte. - Une réponse à outil contient plusieurs blocs : réflexion, texte éventuel,
toolUse(identifiant, nom, arguments). - Lisez le texte en filtrant les blocs, jamais
content[0]["text"]. - Gardez la réponse de Claude intacte dans l’historique ;
stopReasonvauttool_usequand un résultat est attendu.