Accueil → Aide
400 sur un appel d'outil : chaque tool_use a besoin de son tool_result
Chaque bloc tool_use d'un message de l'assistant doit recevoir une réponse sous la forme d'un bloc tool_result portant le même id, dans le message utilisateur immédiatement suivant, avant tout autre contenu. Oubliez-en un parmi plusieurs, changez leur ordre ou placez du texte avant, et la requête suivante est refusée.
Ce que vous voyez
messages.N: tool_use ids were found without tool_result blocks immediately afterEach tool_result block must have a corresponding tool_use block in the previous messageThe first tool call succeeds and the next request failsWorks with one tool, breaks when the model calls two in a single turn
Pourquoi cela arrive
La conversation est rejouée en entier à chaque appel, donc l'API valide toute la structure à chaque fois, y compris des tours acceptés auparavant. C'est pourquoi l'erreur désigne un message plus ancien que celui que vous venez d'envoyer.
Les appels d'outils parallèles sont le déclencheur habituel. Un modèle peut émettre plusieurs blocs tool_use dans un même tour, et un code de traitement écrit pour un seul appel répond au premier et ignore les autres.
Un outil qui échoue produit quand même un résultat. Omettre le bloc parce que votre fonction a levé une exception est exactement la forme que l'API refuse : renvoyez plutôt un tool_result contenant le texte de l'erreur.
Comment le corriger
- Répondez à chaque id, dans l'ordreRécupérez les id tool_use du tour de l'assistant, exécutez-les et émettez un tool_result par id, dans le même ordre, au début du message utilisateur suivant.
- Renvoyez les erreurs comme des résultatsQuand un outil lève une exception, envoyez un tool_result avec le message d'erreur comme contenu. Le modèle s'en accommode très bien ; d'un bloc manquant, non.
- Placez le texte après les résultatsSi vous voulez ajouter une note utilisateur dans le même tour, placez-la après tous les blocs tool_result, jamais avant.
Sur APICLAN, le trafic d'appels d'outils est facturé comme des tokens d'entrée et de sortie ordinaires. Une requête refusée ne s'exécute jamais, elle n'est donc pas facturée, mais la relance, si. C'est pourquoi corriger l'appariement vaut mieux que le contourner à coups de relances.
Voir aussi
Dernière vérification le 2026-10-01. Rédigé à partir de problèmes diagnostiqués sur une passerelle
compatible OpenAI en production, pas compilé à partir d'autres sites.