+170 XP

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

Un client demande à votre bot d'agence de voyage de « réserver le vol le moins cher pour Boston vendredi prochain », et il 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 a l'air correct » et « ce qui s'est réellement passé », c'est là que se joue le débogage des agents. On ne peut pas corriger 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 « rechercher 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 transmis, ce qui est revenu, et la réponse finale. Voyez cela comme une boîte noire pour une seule tâche d'agent.

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

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

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 transmis un simple nom de ville sans jamais lever l'ambiguïté. Il n'y a pas d'étape « resolve_airport ». Le modèle n'a pas échoué dans son raisonnement ; il manquait une étape dans le workflow.

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

Lire une trace : ce qu'il faut chercher

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

  • Mauvais tool, ou pas de tool du tout. 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. Le bon tool, les 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 précoce. Il a donné une réponse finale avant d'avoir terminé la tâche.

La plupart des défaillances d'agents relèvent de l'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 l'ensemble des fournisseurs.

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

Voici à quoi ressemble l'émission d'une trace en pseudocode indépendant du fournisseur. Remarquez que la boucle se résume à : réfléchir, appeler un tool, réinjecter 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)   # réinjecte le résultat dans le 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 ensuite.

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

Une fois que vous avez lu quelques dizaines de traces, les schémas se répètent. Voici les principaux et le correctif habituel.

Usage d'outil 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 à propos d'une commande ») et, si le framework le permet, forcer un appel de tool à cette étape.

Mauvais format d'argument

Le tool attend une date du type 2026-01-16 mais l'agent envoie « next Friday ». 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 incorrecte et demande au modèle de réessayer.

Perte de fil 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 un bref rappel de l'« objectif en cours » à chaque étape.

Appels d'outils 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 est presque toujours l'une de ces trois choses : une description de tool plus claire, une instruction plus claire, ou un garde-fou (une limite ou un contrôle de validation). 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 de 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'exemples d'entrées dont on connaît le bon résultat. 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 réussite/échec.
  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é d'échec à réussite ? Un cas est-il passé de réussite à échec ?

Cette dernière question détecte les régressions : un correctif qui casse discrètement quelque chose 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. Vérifiez que la trace a appelé cancel_booking une fois. C'est plus fiable que de contrôler 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 ces scores comme bruités, pas comme parole d'évangile. Contrôlez-en un échantillon.

Privilégiez 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. Selon la leçon, qu'est-ce qu'une trace d'agent ?

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

3. Quelle est l'idée centrale derrière la formule « On ne peut pas corriger 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 débogage

Voici le workflow complet, dans l'ordre. C'est l'habitude à prendre.

  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. Confirmez 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 qu'on saute, 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, ça compte aussi. Si vous corrigez l'étape aéroport *et* réécrivez les instructions *et* changez de modèle d'un coup, et que le score bouge, vous ne saurez pas quel changement en est responsable. 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 absence 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.
  • Privilégiez les vérifications comportementales à la comparaison de mots. Vérifiez 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.