Aller au contenu principal

Conversations multi-tours avec outils

Mis à jour le 30 juillet 2026

Le cycle manuel du Tool Use fonctionne ; reste à l’automatiser. Construire des conversations multi-tours avec le Tool Use nécessite de gérer différents types de réponses de Claude : parfois il a besoin d’un outil, parfois il répond directement — et votre code doit gérer les deux scénarios sans intervention humaine. C’est l’objet de cette leçon : la boucle conversationnelle qui rend le système autonome.

Le problème de l’intégration simple

Pourquoi une boucle intelligente plutôt qu’un enchaînement fixe ? Parce que si vous ajoutez systématiquement des résultats d’outils à chaque conversation, vous aurez des problèmes : quand Claude répond à une question simple comme « Combien font 1+1 ? », il n’a besoin d’aucun outil — et un code qui tente quand même de traiter des résultats d’outils ajoutera des messages vides à l’historique, cassant l’alternance des rôles au passage.

La solution : vérifier le stop_reason de chaque réponse de Claude, et laisser cette information piloter la suite.

Raisons d’arrêt

Claude peut s’arrêter pour plusieurs raisons, chacune appelant un traitement différent :

stop_reasonSignification
"tool_use"Le modèle veut appeler un outil
"end_turn"Le modèle a fini de générer sa réponse
"max_tokens"Limite de sortie atteinte
"stop_sequence"Séquence d’arrêt rencontrée

Pour notre boucle, le pivot est la distinction entre les deux premières : "tool_use" signifie « la conversation n’est pas finie, il me faut un résultat », "end_turn" signifie « voilà ma réponse ».

Améliorer la fonction chat

Pour piloter la boucle, la fonction chat doit remonter toutes les informations nécessaires — renvoyez un dictionnaire :

def chat(messages, tools=None, system=None, **kwargs):
    # ... code existant ...

    return {
        "parts": parts,
        "stop_reason": response["stopReason"],
        "text": "\n".join([p["text"] for p in parts if "text" in p])
    }

Trois clés, trois usages : parts porte la réponse brute (parties texte et ToolUse) à archiver dans l’historique, stop_reason pilote la décision de boucler, et text agrège les parties textuelles pour l’affichage. Cette signature enrichie servira dans tout le reste du cours.

Construire une boucle conversationnelle

def run_conversation(messages):
    while True:
        result = chat(messages, tools=[get_current_datetime_schema])

        add_assistant_message(messages, result["parts"])
        print(result["text"])

        if result["stop_reason"] != "tool_use":
            break

        tool_result_parts = run_tools(result["parts"])
        add_user_message(messages, tool_result_parts)

    return messages

Cette boucle continue tant que Claude demande des outils. À chaque itération :

  1. Envoyer les messages actuels à Claude
  2. Ajouter la réponse de Claude à l’historique
  3. Vérifier si Claude veut utiliser un outil
  4. Si oui : exécuter les outils et ajouter les résultats à la conversation
  5. Si non : sortir de la boucle

Notez l’ordre des opérations : la réponse est archivée avant le test de sortie — l’historique reste intègre quel que soit le chemin. Et la boucle ne borne pas le nombre de tours : Claude peut enchaîner deux, trois appels d’outils successifs, chacun nourri du résultat précédent — c’est précisément ce qui permettra les workflows où un calcul dépend d’un autre.

Tester l’implémentation

# Question nécessitant un outil
messages = []
add_user_message(messages, "Quelle heure est-il ?")
run_conversation(messages)

# Question simple
messages = []
add_user_message(messages, "Combien font 1+1 ?")
run_conversation(messages)

Pour la question sur l’heure, Claude utilisera l’outil datetime — un tour d’outil, puis la réponse. Pour le calcul, il répond directement — la boucle sort dès la première itération. Aucun des deux cas n’a demandé de traitement spécial : la boucle s’adapte automatiquement selon la raison d’arrêt de Claude.

Ce pattern se généralise bien quand vous ajoutez plus d’outils — la même boucle gère n’importe quelle combinaison d’utilisations d’outils et de réponses directes. C’est la dernière pièce d’infrastructure du Tool Use : à partir d’ici, étendre le système ne touchera plus jamais ce moteur.

Points clés à retenir

  • Le stop_reason pilote la boucle : "tool_use" = continuer, "end_turn" = réponse finale
  • chat renvoie un dictionnaire (parts, stop_reason, text) — la signature qui servira tout le cours
  • Archivez la réponse avant le test de sortie : l’historique reste intègre sur tous les chemins
  • La boucle non bornée autorise les enchaînements d’outils dépendants, sans code supplémentaire
  • Une seule boucle pour tous les cas : questions simples, un outil, ou séquences complexes