Conversations multi-tours avec les outils
Quand Claude utilise des outils, une seule requete ne suffit pas toujours. Il faut mettre en place une boucle de conversation qui continue tant que Claude demande a utiliser des outils, et qui s’arrete quand il a sa reponse finale.
Detecter les demandes d’outils
Le champ stop_reason de la reponse indique pourquoi Claude a arrete de generer du texte. Quand il veut appeler un outil, ce champ vaut "tool_use" :
if response.stop_reason != "tool_use":
break # Claude a termine, plus besoin d'outils
C’est le signal cle : tant que stop_reason vaut "tool_use", il faut continuer la boucle.
La boucle de conversation
Le schema general est simple : on boucle indefiniment, on envoie les messages a Claude, on traite les outils demandes, et on recommence jusqu’a ce que Claude fournisse une reponse finale.
def run_conversation(messages):
while True:
response = chat(messages, tools=[get_current_datetime_schema])
add_assistant_message(messages, response)
print(text_from_message(response))
if response.stop_reason != "tool_use":
break
tool_results = run_tools(response)
add_user_message(messages, tool_results)
return messages
A chaque iteration :
- On appelle Claude avec les messages et les outils disponibles
- On ajoute la reponse de Claude a l’historique
- Si Claude ne demande pas d’outil, on sort de la boucle
- Sinon, on execute les outils et on renvoie les resultats
Gerer plusieurs appels d’outils en parallele
Claude peut demander plusieurs outils dans une seule reponse. Le contenu du message est une liste de blocs, et chaque bloc de type tool_use correspond a un appel distinct.
La fonction run_tools filtre ces blocs et traite chacun d’eux :
def run_tools(message):
tool_requests = [
block for block in message.content if block.type == "tool_use"
]
tool_result_blocks = []
for tool_request in tool_requests:
# Traiter chaque demande d'outil...
Les blocs de resultats
Chaque bloc tool_use doit recevoir un bloc tool_result correspondant. Le lien entre les deux se fait via l’identifiant (tool_use_id) :
tool_result_block = {
"type": "tool_result",
"tool_use_id": tool_request.id,
"content": json.dumps(tool_output),
"is_error": False
}
Les champs importants :
type: toujours"tool_result"tool_use_id: doit correspondre exactement a l’iddu bloctool_usecontent: le resultat serialise en JSONis_error:Truesi l’execution a echoue
Gestion des erreurs
Meme en cas d’erreur, il faut renvoyer un bloc de resultat a Claude pour qu’il puisse continuer la conversation :
try:
tool_output = run_tool(tool_request.name, tool_request.input)
tool_result_block = {
"type": "tool_result",
"tool_use_id": tool_request.id,
"content": json.dumps(tool_output),
"is_error": False
}
except Exception as e:
tool_result_block = {
"type": "tool_result",
"tool_use_id": tool_request.id,
"content": f"Error: {e}",
"is_error": True
}
En signalant is_error: True, Claude sait que l’outil a echoue et peut adapter sa reponse en consequence (retenter, demander des informations supplementaires, ou informer l’utilisateur).
Routage extensible des outils
Pour gerer plusieurs outils proprement, on cree une fonction de routage qui associe chaque nom d’outil a son implementation :
def run_tool(tool_name, tool_input):
if tool_name == "get_current_datetime":
return get_current_datetime(**tool_input)
elif tool_name == "another_tool":
return another_tool(**tool_input)
# Ajouter d'autres outils ici
Cette approche permet d’ajouter de nouveaux outils sans modifier la logique principale de la conversation.
Recapitulatif du flux complet
Le cycle complet d’une conversation multi-tours avec outils :
- Envoi du message utilisateur a Claude avec la liste des outils disponibles
- Reponse de Claude contenant du texte et/ou des demandes d’outils
- Execution de tous les outils demandes et creation des blocs de resultats
- Renvoi des resultats sous forme de message utilisateur
- Repetition jusqu’a ce que Claude fournisse une reponse finale (sans demande d’outil)
Ce mecanisme permet a Claude d’enchainer plusieurs outils sur plusieurs tours pour repondre a des questions complexes, tout en gardant le contexte complet de la conversation.