+170 XP

Évaluer et débugger les agents : traces, evals et modes de défaillance

# Évaluer et débugger les agents : traces, evals et modes de défaillance

Un client demande à votre agent de voyage de « réserver le vol le moins cher pour Boston vendredi prochain », et le bot réserve avec assurance un vol pour Boston, dans le Lincolnshire, au Royaume-Uni. Le client voulait Boston, Massachusetts. La réponse semble correcte jusqu'à ce que vous voyiez ce que l'agent a réellement fait : il n'a jamais appelé l'outil qui résout les codes aéroport, donc il a deviné.

Cet écart entre « ça semble correct » et « ce qui s'est réellement passé », c'est là que se joue le debug des agents. On ne corrige pas ce qu'on ne voit pas.

Ce qu'est une trace

Un agent est un système d'IA capable d'agir, pas seulement de discuter. Il appelle des tools (des fonctions comme « chercher des vols », « lire un fichier » ou « envoyer un email »), lit les résultats et décide de la suite.

Une trace est le journal enregistré, étape par étape, d'une exécution : chaque prompt vu par le modèle, chaque tool appelé, les arguments passés, ce qui est revenu, et la réponse finale. Voyez-la comme la boîte noire d'une seule tâche d'agent.

Sans trace, débugger revient à deviner. Avec une trace, la défaillance saute généralement aux yeux.

Voici une trace simplifiée de la réservation Boston, en langage clair :

RUN #4471  |  user: "book the cheapest flight to Boston next Friday"

Step 1  LLM thinks: "User wants a flight. I'll search."
Step 2  TOOL CALL: search_flights(city="Boston", date="2026-01-16")
Step 3  TOOL RESULT: 3 flights returned  [destination code: BZZ, UK]
Step 4  LLM thinks: "Cheapest is £48. Booking it."
Step 5  TOOL CALL: book_flight(flight_id="BZZ-2231")
Step 6  TOOL RESULT: {"status": "confirmed"}
Step 7  LLM final: "Booked! £48 to Boston next Friday."

Le bug est à l'étape 2. L'agent a passé un simple nom de ville sans jamais le désambiguïser. Il n'y a pas d'étape « resolve_airport ». Le modèle n'a pas échoué sur le raisonnement ; il manquait une étape dans le workflow.

C'est tout l'intérêt du tracing : il vous dit *où* ça a cassé, donc *quoi* corriger.

Lire une trace : que chercher

Quand vous ouvrez la trace d'une mauvaise exécution, cherchez ceci :

  • Mauvais tool, ou pas de tool. L'agent a-t-il répondu de mémoire alors qu'il aurait dû appeler un tool ? (Une cause classique de « faits » inventés.)
  • Mauvais arguments. Bon tool, mauvaises entrées. Comme city="Boston" sans pays.
  • Résultats ignorés. Le tool a renvoyé les bonnes données, mais l'étape suivante du modèle les a ignorées.
  • Boucles. L'agent appelle le même tool encore et encore sans progresser.
  • Arrêt trop tôt. Il a donné une réponse finale avant d'avoir terminé la tâche.

La plupart des défaillances d'agents relèvent d'un de ces cinq cas. Pas besoin de lire du code pour les repérer ; vous lisez la trace comme une histoire et vous trouvez la phrase qui n'a plus de sens.

D'où viennent les traces

Vous ne construisez pas vous-même un visualiseur de traces. Les frameworks d'agents modernes émettent des traces automatiquement, et les outils d'observabilité les affichent sous forme de timelines cliquables. Parmi les options ouvertes et gratuites : Langfuse et Arize Phoenix, qui supportent tous deux le standard OpenTelemetry et fonctionnent donc avec tous les fournisseurs.

Le SDK d'agents de chaque éditeur (OpenAI Agents SDK, Claude Agent SDK, ADK de Google) intègre aussi son propre tracing. Le concept est identique partout ; seuls les boutons changent. Voyez les blocs d'approfondissement par fournisseur pour la configuration exacte.

Voici à quoi ressemble l'émission d'une trace en pseudocode neutre. Remarquez que la boucle se résume à : réfléchir, appeler un tool, renvoyer le résultat, recommencer.

python
trace = []

while not done:
    response = model.generate(messages, tools=my_tools)
    trace.append({"step": "llm", "output": response})

    if response.tool_call:
        result = run_tool(response.tool_call)
        trace.append({"step": "tool",
                      "name": response.tool_call.name,
                      "args": response.tool_call.args,
                      "result": result})
        messages.append(result)   # renvoie le résultat au modèle
    else:
        done = True

save(trace)   # vous pourrez inspecter cette exécution plus tard

Les lignes trace.append sont toute l'astuce. Enregistrez chaque étape au fil de l'eau, et vous pourrez rejouer n'importe quelle exécution après coup.

Modes de défaillance courants (et ce qui les corrige)

Après quelques dizaines de traces lues, les motifs se répètent. Voici les principaux et le correctif habituel.

Usage de tool halluciné

L'agent dit « j'ai vérifié la base de données » mais la trace ne montre aucun appel de tool. Correctif : renforcer l'instruction (« Vous devez appeler lookup_order avant de répondre à toute question sur une commande ») et, si le framework le permet, forcer un appel de tool à cette étape.

Format d'argument incorrect

Le tool attend une date au format 2026-01-16 mais l'agent envoie « vendredi prochain ». Correctif : décrire clairement le format de l'argument dans la description du tool, et ajouter une étape de validation qui rejette une entrée invalide et demande au modèle de réessayer.

Se perdre sur les tâches longues

Sur une tâche de 15 étapes, l'agent oublie ce qu'il faisait à l'étape 10. Correctif : découper la tâche en sous-tâches plus petites, ou ajouter à chaque étape un bref rappel de l'« objectif courant ».

Appels de tools excessifs

L'agent lance cinq recherches web pour une seule question, ce qui coûte du temps et de l'argent. Correctif : fixer une limite d'étapes et lui demander de résumer ce qu'il sait déjà avant de relancer une recherche.

Le correctif se résume presque toujours à trois choses : une description de tool plus claire, une instruction plus claire, ou un garde-fou (une limite ou une vérification). Vous avez rarement besoin d'un modèle plus gros.

How to Debug AI Agents with Tracing

Watch on YouTube

Evals : savoir si un changement a vraiment aidé

Vous avez trouvé le bug Boston. Vous avez ajouté une étape « resolve_airport ». Est-ce que ça a marché ? Et est-ce que ça a cassé autre chose ?

C'est là qu'interviennent les evals. Un eval (pour evaluation) est un test reproductible de votre agent sur un ensemble d'entrées d'exemple dont on connaît les bons résultats. C'est l'équivalent, pour un agent, de la checklist qu'un pilote déroule avant chaque vol.

L'idée centrale est l'eval set : une petite collection de cas de test que vous exécutez à chaque modification de l'agent. Chaque cas a une entrée et un moyen de vérifier la sortie.

Commencez avec un simple tableur ou un fichier. Dix à vingt cas suffisent largement pour démarrer.

case_id | input                                    | check
--------|------------------------------------------|----------------------------
1       | "cheapest flight to Boston next Friday"  | destination country == "US"
2       | "flight to Paris"                        | asks which Paris OR picks FR
3       | "cancel my last booking"                 | calls cancel_booking exactly once
4       | "book London to Boston"                  | resolves BOTH cities
5       | "what's the weather"                     | does NOT call book_flight

Remarquez que les vérifications sont concrètes. Certaines sont exactes (« destination country == US »), d'autres comportementales (« n'appelle pas book_flight »). Le cas 5 est un test négatif : il s'assure que l'agent ne fait *pas* quelque chose de faux.

Comment exécuter un eval set

La boucle est simple :

1. Exécutez tous les cas sur l'agent actuel. Notez pass/fail.

2. Faites un seul changement (ajouter l'étape aéroport).

3. Réexécutez tous les cas.

4. Comparez. Le cas 1 est-il passé de fail à pass ? Un cas est-il passé de pass à fail ?

Cette dernière question attrape les régressions : un correctif qui casse discrètement ce qui fonctionnait. Sans eval set, vous livreriez le correctif et l'apprendriez d'un client mécontent.

Vérifier des sorties qu'on ne peut pas comparer à l'identique

Beaucoup de sorties d'agents ne sont pas des chaînes exactes. « Bien sûr, j'ai annulé votre réservation » et « C'est fait, votre réservation est annulée » passent toutes les deux. Pour ces cas, deux approches courantes :

  • Vérifier le comportement, pas les mots. Affirmez que la trace a appelé cancel_booking une fois. C'est plus fiable que de vérifier la formulation.
  • LLM-as-judge. Utilisez un second appel de modèle pour noter la réponse selon une grille (« La réponse a-t-elle confirmé l'annulation ? oui/non »). Utile, mais traitez ses scores comme bruités, pas comme parole d'évangile. Faites des contrôles par sondage.

Préférez les vérifications comportementales quand c'est possible. Elles coûtent moins cher et sont bien plus stables que le jugement de texte.

Vérification des acquis

1. D'après la leçon, qu'est-ce qu'une trace d'agent ?

2. Dans l'exemple de la réservation Boston, pourquoi l'agent a-t-il échoué ?

3. Quelle est l'idée centrale derrière la phrase « On ne corrige pas ce qu'on ne voit pas » ?

CHOIX MULTIPLES

4. Sélectionnez TOUTES les bonnes réponses. Que capture généralement une trace pour une exécution d'agent ?

Sélectionnez toutes les réponses correctes.

CHOIX MULTIPLES

5. Sélectionnez TOUTES les bonnes réponses. Quelles affirmations reflètent la distinction faite dans la leçon entre un agent et un simple chatbot ?

Sélectionnez toutes les réponses correctes.

Mise en pratique : la boucle de debug

Voici tout le workflow dans l'ordre. C'est l'habitude à installer.

1. Une exécution échoue. Un utilisateur signale une mauvaise réponse, ou un cas d'eval échoue.

2. Ouvrez la trace. Lisez-la comme une histoire. Trouvez l'étape qui n'a plus de sens.

3. Nommez le mode de défaillance. Mauvais tool ? Mauvais arguments ? Résultat ignoré ? Boucle ?

4. Faites un seul changement. Instruction plus claire, description de tool plus claire, ou garde-fou.

5. Exécutez l'eval set. Vérifiez que le cas visé passe et que rien d'autre n'a régressé.

6. Ajoutez le cas en échec à votre eval set pour qu'il ne régresse plus jamais en silence.

L'étape 6 est celle que les gens sautent, et c'est la plus précieuse. Chaque bug corrigé devient un test permanent. En quelques mois, votre eval set devient un vrai filet de sécurité, entièrement construit à partir de défaillances réelles.

Un changement à la fois compte aussi. Si vous corrigez l'étape aéroport *et* réécrivez les instructions *et* changez de modèle en même temps, et que le score bouge, vous ne saurez pas quel changement en est la cause. Changez une chose, lancez les evals, recommencez.

Points clés

  • Une trace est votre boîte noire. Quand un agent échoue, ouvrez la trace avant de toucher à quoi que ce soit. Le bug est en général une étape visible : un appel de tool manquant, un mauvais argument, ou un résultat ignoré.
  • Apprenez les cinq modes de défaillance. Mauvais tool ou pas de tool, mauvais arguments, résultats ignorés, boucles et arrêt trop précoce couvrent la grande majorité des bugs d'agents. Nommer le mode vous oriente vers le correctif.
  • Construisez un petit eval set maintenant, pas plus tard. Dix à vingt cas dans un tableur suffisent à savoir si un changement a aidé ou cassé discrètement autre chose.
  • Préférez les vérifications comportementales à la comparaison de mots. Affirmez quels tools ont été appelés et combien de fois. C'est plus stable que de noter la formulation exacte, et ça attrape les vraies erreurs.
  • Chaque bug corrigé devient un test. Ajoutez chaque cas en échec à votre eval set pour qu'il ne puisse jamais régresser en silence. Changez une chose à la fois, puis relancez.

Articles liés

Les articles récents du blog qui s'appuient sur cette leçon.