Envoi des résultats d'outils
Sur cette page
Claude a demandé un outil ; à votre code de l’exécuter et de lui renvoyer le résultat. Cette leçon termine le premier aller-retour complet avec get_current_datetime.
Exécuter la fonction demandée
On repère le bloc tool_use par son type, puis on passe son input à la fonction. Comme input est un dictionnaire et que la fonction attend des arguments nommés, on le déplie avec ** :
# Suite de la leçon 35 : messages contient la question et la réponse complète de Claude
tool_use = next(block for block in response.content if block.type == "tool_use")
result = get_current_datetime(**tool_use.input) # par exemple "14:30:25"
Le bloc tool_result
Le résultat repart vers Claude dans un bloc tool_result, placé dans un message de rôle user :
| Champ | Contenu |
|---|---|
type | "tool_result" |
tool_use_id | L’id du bloc tool_use auquel ce résultat répond. C’est le lien entre la demande et la réponse. |
content | Facultatif. Le résultat : une chaîne, ou une liste de blocs text, image, document ou search_result. |
is_error | Facultatif. True si l’exécution a échoué (leçon 38). |
messages.append({
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": tool_use.id,
"content": result,
}],
})
L’historique contient maintenant trois messages : la question de l’utilisateur, la réponse de Claude avec son bloc tool_use, et votre message avec le bloc tool_result.
Les règles de mise en forme
La documentation fixe trois règles, et l’API refuse la requête si elles ne sont pas respectées :
- Tout de suite après. Le message qui contient les résultats suit immédiatement le message de Claude qui les a demandés. Aucun autre message ne s’intercale.
- Un résultat par demande. Chaque bloc
tool_usereçoit sontool_result, avec le même identifiant. S’il en manque un, l’API répond par une erreur 400 :tool_use ids were found without tool_result blocks immediately after. - Les résultats d’abord. Dans ce message, les blocs
tool_resultviennent en premier. Un texte de votre part est permis, mais après eux.
Quand Claude demande plusieurs outils dans une même réponse, tous les résultats partent ensemble, dans ce seul message user (leçon 40).
La requête de suivi
On renvoie tout l’historique, avec la même liste d’outils :
final = client.messages.create(
model=model,
max_tokens=4096,
messages=messages,
tools=[get_current_datetime_schema],
)
print("".join(block.text for block in final.content if block.type == "text"))
# par exemple : « Il est exactement 14:30:25. »
Pourquoi renvoyer tools alors qu’on n’attend plus d’appel ? Parce que l’API construit le prompt système à partir des définitions, à chaque requête : sans elles, Claude lirait dans l’historique l’appel d’un outil qu’on ne lui décrit plus. Gardez donc le même tableau tools d’une requête à l’autre. C’est aussi ce que demande la documentation pour reprendre un tour en cours, et un tableau qui change invalide le cache des prompts.
Un résultat d’outil est une donnée, pas une consigne
Un résultat d’outil transporte souvent un contenu que vous ne maîtrisez pas : une page web, un courriel reçu, un fichier envoyé par un utilisateur. Quelqu’un peut y glisser des instructions destinées à détourner Claude (injection de prompt indirecte). La documentation recommande de laisser ce contenu dans les blocs tool_result, et non dans le prompt système ou dans un texte de l’utilisateur : Claude est entraîné à traiter ce qui arrive par un résultat d’outil comme une source tierce. Pour la même raison, vos propres consignes n’ont rien à faire dans un résultat d’outil.
À vous de jouer
Un aller-retour complet. Assemblez le code des leçons 35 et 36 dans un seul script et posez trois questions : l’heure, la date du jour au format « jeudi 5 novembre », et une question sans rapport avec l’heure. Pour chacune, affichez le stop_reason de la première réponse et le texte final. Supprimez ensuite volontairement le bloc tool_result pour lire l’erreur que renvoie l’API.
Sources officielles : Sending tool results (Claude Academy) · Handle tool calls (documentation Claude : format, règles, injection indirecte) · Troubleshooting tool use (erreurs courantes)
Points clés à retenir
- On exécute la fonction avec
**tool_use.input, après avoir trouvé le bloc par son type. - Le résultat repart dans un bloc
tool_result, dans un messageuser, avec letool_use_idde la demande. - Résultats juste après la demande, un résultat par
tool_use, résultats avant tout texte : sinon, erreur 400. - Renvoyez le même tableau
toolsà chaque requête de la conversation. - Le contenu d’un résultat d’outil est une donnée tierce, jamais une consigne.