Aller au contenu principal
Leçon 25 sur 67 · Claude sur Amazon Bedrock

Gérer les réponses tool use

Leçon 25 sur 67 Mis à jour le 5 novembre 2026 Développeur
Sur cette page
  1. Déclarer les outils : toolConfig
  2. Des utilitaires plus souples
  3. Une réponse en plusieurs blocs
  4. L’historique et la raison d’arrêt
  5. À vous de jouer
  6. Points clés à retenir

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 :

toolChoiceComportement
{"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])
Une réponse en plusieurs blocs Trois blocs dans la réponse : reasoningContent, la réflexion souvent vide ; text, une phrase pour l'humain ; toolUse, avec l'identifiant, le nom de l'outil et ses arguments. RÉPONSES TOOL USE Une réponse en plusieurs blocs 1 reasoningContent la réflexion, souvent vide 2 text une phrase pour l'humain 3 toolUse identifiant, nom, arguments stopReason vaut tool_use : Claude attend un résultat avant de répondre.
D'après la leçon « Handling tool use responses » (Claude Academy, Claude with Amazon Bedrock) et la référence de l'API Converse.

Quand Claude veut un outil, la liste parts contient en général :

  1. un bloc reasoningContent, la trace de sa réflexion, avec Haiku 5.5 ;
  2. souvent un bloc text, une phrase pour l’humain, du type « Je regarde l’heure » ;
  3. 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 dans toolConfig, Bedrock le génère : il commence par tooluse_ ;
  • 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 ; toolChoice vaut auto par 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 ; stopReason vaut tool_use quand un résultat est attendu.