Évaluation des AI agents en production : des traces aux suites de tests

Traduction automatique Cet article a été traduit automatiquement depuis la version originale en anglais.

Mise à jour de l’article

Publié initialement le 10 juin 2026. Relu et mis à jour le 6 septembre 2026. Cette mise à jour couvre les nouveaux benchmarks d’agents, les révisions des graders et les éléments montrant comment l’infrastructure influe sur les scores.

Une réponse finale peut affirmer qu’un remboursement est terminé alors que sa trace montre que verify_identity n’a jamais été exécuté, que issue_refund a été relancé 17 fois, ou que l’agent a déclaré le succès avant la modification de la base de données. Une évaluation limitée à la réponse masque ces échecs.

Pour les ingénieurs qui exploitent des agents utilisant des outils en production, la solution consiste à transformer les traces reproductibles en cas de régression bornés : des contrôles déterministes imposent l’ordre des outils, les arguments, les boucles et les invariants ; des juges calibrés prennent en charge les décisions qui nécessitent une interprétation. On obtient ainsi une suite versionnée qui détecte le même échec avant la prochaine release.

Pour une comparaison rapide des outils, consultez Best AI Agent Evaluation Tools.


Pourquoi l’évaluation des agents est différente

Les évaluations classiques des LLM notent généralement une paire entrée-sortie : pertinence, fidélité, exactitude, sécurité, éventuellement style. Les agents ajoutent la planification, les tool calls, les relances et les contrôles de terminaison ; chaque étape devient donc un nouveau point de défaillance.

Prenons un agent de remboursement. La transcription peut bien se terminer alors que la trace est incorrecte :

lookup_order -> issue_refund -> final_answer

L’évaluation de la sortie réussit. Une évaluation de trajectoire devrait échouer, car verify_identity n’a jamais été exécuté avant issue_refund. Pour les agents utilisant des outils, les évaluations limitées à la réponse peuvent détecter des problèmes de qualité du contenu, mais elles ne peuvent pas établir que l’agent a suivi une trajectoire valide ou produit les effets de bord requis.

Un second problème se pose : les erreurs se cumulent. Si un workflow comporte 20 étapes obligatoires, que chacune réussit indépendamment et que chaque étape a la même fiabilité de 95 %, le taux de réussite de bout en bout tombe à environ 36 % :

0.95200.360.95^{20} \approx 0.36

L’agent peut donc sembler solide dans des contrôles isolés tout en échouant dans la majorité des exécutions complètes. La rupture se situe généralement quelque part au milieu ; pour la trouver, il faut une visibilité au niveau des composants, pas un nouvel examen de la réponse.

Une ligne ou un arbre : où se cachent les échecs des agentsUne ligne ou un arbre : où se cachent les échecs des agents

Deux équipes de recherche ont quantifié ce phénomène.

tau-bench fournit à un agent des tâches de service client dans les domaines aérien et retail. L’agent échange avec un utilisateur simulé, appelle des APIs et doit respecter la politique du domaine. Après la conversation, le grader vérifie que la base de données a atteint l’état cible annoté. Une transcription plausible avec les mauvaises lignes échoue tout de même.

Avec cette méthode d’évaluation, GPT-4o n’a résolu que 35,2 % des tâches aériennes et un peu plus de 60 % des tâches retail. L’article a également introduit pass^k : la probabilité que les k essais indépendants réussissent tous, moyennée sur les tâches.

Le split retail, plus facile, avait un pass^8 inférieur à 25 %. Pour une tâche retail choisie aléatoirement et huit essais indépendants, la probabilité que les huit exécutions réussissent toutes était inférieure à 25 %. Une évaluation sur une seule exécution ne peut pas mesurer cette régularité.

MAST étudie les raisons des échecs des agents. Les auteurs ont construit une taxonomie de 14 modes à partir de 150 traces annotées manuellement, puis l’ont appliquée à plus de 1 600 traces provenant de 7 frameworks multi-agent populaires. La taxonomie inclut des définitions de rôles vagues (conception du système), un agent qui ignore ce qu’un autre agent a signalé (désalignement inter-agents) et la déclaration d’un succès sans vérification du résultat (absence de vérification). Ces échecs mettent en cause les prompts, la logique d’orchestration et les contrôles manquants dans le harness. Un modèle de base plus puissant ne peut pas exécuter une étape de vérification qui n’a jamais été implémentée ; la cible de l’évaluation doit donc inclure le harness autour du modèle.


Le retard d’adoption

L’enquête State of Agent Engineering de LangChain (1 340 répondants, réalisée fin 2025) suggère que de nombreuses équipes disposent déjà de la matière première nécessaire à de meilleures évaluations. Elle indique que 89 % disposaient d’un certain niveau d’observabilité, que 52,4 % exécutaient des évaluations offline et que 37,3 % exécutaient des évaluations online.

L’enquête indique également que 57,3 % des répondants ont déjà des agents en production. À la question des principaux obstacles à la mise en production, 32 % citaient la qualité et 20 % la latence. Il s’agit d’une enquête menée auprès des répondants de ce fournisseur, et non d’un recensement des équipes travaillant sur des agents, mais elle met en évidence un écart utile entre la collecte de traces et l’évaluation systématique.

Les équipes se retrouvent ainsi dans une situation intermédiaire inconfortable : elles peuvent examiner une mauvaise exécution a posteriori, puis livrer deux fois le même échec.

Chaque échec de production diagnostiqué devrait laisser une trace, une annotation, une ligne de dataset et un scorer. Un échec reproductible appartient à la suite de régression.


Choisir les métriques selon le mode d’échec

La bonne métrique dépend du mode d’échec, et non du framework. La séparation utile comporte trois niveaux :

  1. Les évaluations de résultat répondent à la question : la tâche a-t-elle réussi ?
  2. Les évaluations de trajectoire répondent à la question : le chemin était-il valide, efficace et conforme à la politique ?
  3. Les évaluations de composants répondent à la question : quel outil, retriever, sous-agent ou étape de décision a échoué ?

Trois niveaux d’évaluation des agents et leurs métriquesTrois niveaux d’évaluation des agents et leurs métriques

Chaque niveau peut être exécuté offline sur des cas fixes et rejouables avant la release, ou online sur des traces de production échantillonnées après la réponse. La section consacrée aux garde-fous détaille cette séparation. Les évaluations offline peuvent nécessiter des goldens : des cas stockés associant une entrée au résultat, aux invariants d’outils et aux arguments qu’une exécution correcte doit produire. Les évaluations online devraient privilégier les invariants, les distributions et les contrôles asynchrones qui restent hors du chemin de la requête.

QuestionFamille de métriquesContrat offline / onlineDéterministe ou juge ?Point d’attention
L’agent a-t-il appelé les bons outils ?Exactitude des outils : correspondance exacte, dans l’ordre ou dans n’importe quel ordreGoldens exacts offline ; invariants d’outils requis et anomalies onlineDéterministeLa correspondance exacte pénalise les chemins alternatifs valides
Les a-t-il appelés avec les bonnes entrées ?Exactitude des arguments, validation du schéma, correspondance des paramètresArguments attendus offline ; contrôles de schéma, de plage et de politique onlineLes deuxLe bon outil avec de mauvais arguments reste incorrect
A-t-il gaspillé des étapes ?Efficacité des étapes, nombre de relances, détection de boucles, coût et latenceBudgets d’étapes et de boucles offline ; dérive du coût et de la latence onlinePrincipalement déterministeUn taux élevé de réussite peut masquer une exploration coûteuse
La tâche a-t-elle réellement réussi ?Achèvement de la tâche, évaluation du résultat, diff de l’état finalSimulateur ou état de référence offline ; état final, signal utilisateur ou juge asynchrone onlineJuge ou contrôle d’étatÉvaluez l’état de l’environnement lorsque c’est possible
Le contexte a-t-il été conservé entre les tours ?Fidélité multi-tour, respect des rôles, complétude de la conversationCas scénarisés à long horizon offline ; sessions longues échantillonnées onlineJugeLes tests mono-tour ne disent rien du tour 14
L’agent s’est-il arrêté au bon moment ?Exactitude de la terminaison, succès prématuré, travail sans finTests de scénarios offline ; surveillance des boucles, timeouts et faux succès onlineLes deux« Terminé » peut être un état halluciné
A-t-il correctement interprété les résultats des outils ?Compréhension des tool results, contrôles de l’état en avalSorties d’outils adversariales offline ; contrôles de l’état en aval et revue échantillonnée onlineLes deuxÉvaluez l’état en aval, pas le code de sortie de l’outil

Commencez par les métriques déterministes. Elles se répètent pour des entrées et du code fixes, et coûtent peu à exécuter. Leurs règles peuvent toutefois devenir obsolètes lorsque les outils ou la politique changent ; versionnez donc le scorer avec la spécification qu’il contrôle.

Exactitude des tool calls

L’exactitude des outils compare les outils appelés aux outils attendus. Choisissez délibérément le niveau de stricte :

  • Correspondance exacte : la séquence doit correspondre exactement. Utilisez-la lorsque l’ordre relève de la politique, par exemple lookup_order -> verify_identity -> issue_refund.
  • Correspondance dans l’ordre : les outils requis doivent apparaître dans le bon ordre relatif, mais des appels supplémentaires sans effet indésirable sont autorisés.
  • Correspondance dans n’importe quel ordre : les outils requis doivent apparaître, mais l’ordre peut varier.

Un petit scorer local suffit pour commencer :

from collections import Counter

def tool_correctness(called: list[str], expected: list[str], mode: str = "in_order") -> float:
    if mode not in {"exact", "in_order", "any_order"}:
        raise ValueError(f"unknown matching mode: {mode}")
    if mode == "exact":
        return float(called == expected)
    if not expected:
        return 1.0
    if mode == "any_order":
        matched = sum((Counter(called) & Counter(expected)).values())
        return matched / len(expected)

    rows = [[0] * (len(expected) + 1) for _ in range(len(called) + 1)]
    for i, tool in enumerate(called):
        for j, wanted in enumerate(expected):
            if tool == wanted:
                rows[i + 1][j + 1] = rows[i][j] + 1
            else:
                rows[i + 1][j + 1] = max(rows[i][j + 1], rows[i + 1][j])
    return rows[-1][-1] / len(expected)

called = ["lookup_order", "check_refund_policy", "issue_refund"]
expected = ["lookup_order", "verify_identity", "issue_refund"]

print(round(tool_correctness(called, expected, "exact"), 3))     # 0.0
print(round(tool_correctness(called, expected, "in_order"), 3))  # 0.667
assert tool_correctness(["issue_refund"], [], "exact") == 0.0
assert tool_correctness([], [], "exact") == 1.0
assert tool_correctness(["a", "b"], ["a", "a", "b"], "any_order") == 2 / 3
try:
    tool_correctness([], [], "typo")
except ValueError:
    pass
else:
    raise AssertionError("unknown modes must fail")

Le score in_order est un rappel de la plus longue sous-séquence commune : quelle fraction de la séquence requise a été conservée, dans le bon ordre. Remarquez ce qu’il ignore. Les appels superflus ne le diminuent pas ; un agent peut donc obtenir 1,0 ici tout en effectuant deux fois plus d’appels que nécessaire. Lorsque les appels supplémentaires coûtent de l’argent ou modifient l’état, suivez également la précision (appels requis correspondants sur le nombre total d’appels) et lisez les deux métriques ensemble. Le rappel détecte l’étape manquante ; la précision détecte les détours. Ni un rappel de 1,0 ni une précision élevée n’autorisent des mutations supplémentaires. Vérifiez chaque appel qui modifie l’état au regard de ses permissions, de sa ressource, de ses arguments et de la vérification préalable requise. Avec une liste attendue vide, seul le mode exact signifie « aucun appel autorisé » ; les autres modes n’imposent aucune exigence positive.

La métrique Tool Correctness de DeepEval expose les mêmes réglages via should_consider_ordering et should_exact_match.

Exactitude des arguments

Appeler le bon outil avec de mauvais arguments est souvent pire qu’appeler le mauvais outil, car la trace semble normale.

Pour les cas simples, validez le JSON Schema et les valeurs exactes. Pour les cas sémantiques, stockez les arguments attendus et évaluez les écarts :

{
    "trace_id": "tr_2417",
    "input": "Reschedule order A-100 for June 19, 2026.",
    "expected_tools": ["lookup_order", "reschedule_delivery"],
    "expected_arguments": {
        "reschedule_delivery": {
            "order_id": "A-100",
            "date": "2026-06-19"
        }
    }
}

Une métrique fondée sur le nom de l’outil ne peut pas détecter 2026-06-17 lorsque la politique impose 2026-06-19. Le dataset doit également stocker les arguments.

Pour cette illustration avec un seul appel par outil, la correspondance des paramètres est la fraction des triplets (tool, key, value) attendus que l’agent a correctement fournis. Les dictionnaires ci-dessous ne sont valides que lorsque chaque outil concerné est invoqué au plus une fois. Ne les construisez pas en écrasant les appels précédents portant le même nom : cela masquerait un mauvais remboursement suivi d’un remboursement correct. Pour les appels répétés, conservez les identifiants d’appel et l’ordre, associez l’invocation prévue et validez chaque mutation séparément.

def argument_correctness(called_args: dict, expected_args: dict) -> float:
    total = matched = 0
    for tool, params in expected_args.items():
        for key, want in params.items():
            total += 1
            if key in called_args.get(tool, {}) and called_args[tool][key] == want:
                matched += 1
    return matched / total if total else 1.0

assert argument_correctness({}, {"reschedule_delivery": {"date": None}}) == 0.0
assert argument_correctness({"reschedule_delivery": {}},
                            {"reschedule_delivery": {"date": None}}) == 0.0
assert argument_correctness({"reschedule_delivery": {"date": None}},
                            {"reschedule_delivery": {"date": None}}) == 1.0

L’égalité exacte convient aux identifiants, aux enums et aux dates déjà normalisées dans un format unique. Elle ne convient pas au texte libre, aux flottants ni aux dates dans le format produit par le modèle, pour lesquels == signale à tort une réponse correcte comme incorrecte. Évaluez ces champs selon leur nature : comparaison de chaînes normalisées, parsing de date, tolérance numérique. La métrique reste la même ; c’est le comparateur par champ qui change.

Efficacité, boucles et impasses

Un agent qui termine la tâche après cinq tool calls redondants révèle tout de même un problème de planification et coûte plus cher à exécuter.

Commencez par ces signaux peu coûteux :

  • Taux d’appels redondants : appels d’outils identiques avec des arguments identiques répétés plus de deux fois.
  • Anomalies de forme des traces : pics soudains de profondeur, de nombre de tool calls, de nombre de tokens, de latence ou de coût.
  • Convergence du chemin : proximité de l’exécution avec le chemin valide le plus court connu pour la tâche.
  • Exactitude de la terminaison : l’agent s’est-il arrêté trop tôt, a-t-il continué après le succès ou a-t-il déclaré un succès sans la modification d’état requise ?
  • Respect du plan : si l’agent rédige un plan avant d’agir, vérifiez si la trace l’a suivi. Un bon plan ignoré et un mauvais plan suivi à la perfection échouent tous deux, pour des raisons opposées ; la différence entre le plan et la trace vous indique laquelle.

Exécutez ces contrôles avant un juge chaque fois que possible. Un détecteur de boucles tient en quelques lignes sur la trace. Il n’a pas besoin de modèle.

Achèvement de la tâche et évaluation du résultat

Lorsqu’elle porte sur le résultat, la question de l’évaluation est : « l’utilisateur a-t-il obtenu ce qu’il demandait ? »

Deux approches fonctionnent particulièrement bien :

  • Évaluation sans référence de l’achèvement de la tâche : extraire l’objectif de l’entrée et déterminer si la trace et la réponse finale l’ont atteint. Cette approche fonctionne online, car le trafic de production fournit rarement des sorties de référence.
  • Évaluation de l’état de l’environnement : comparer les lignes finales de la base de données, les fichiers, les tickets, les réservations ou les enregistrements à un état cible annoté. Cette approche est plus robuste que la comparaison de transcriptions, car les agents peuvent trouver des chemins valides que vous n’aviez pas écrits.

La seconde option est préférable lorsque vous pouvez la mettre en place. L’état final est le contrat. La transcription n’est qu’un élément de preuve.

Deux réserves permettent de rester honnête. Un audit de 2025 sur les benchmarks agentic a constaté que tau-bench évalue certaines tâches uniquement sur l’état de la base de données. Pour certaines tâches, le résultat annoté n’exige ni modification d’état ni texte spécifique. Un agent qui ne fait rien peut alors obtenir la réussite : 38 % sur le split aérien et 6,0 % sur le retail, à n’importe quel k. Anthropic a rapporté une exécution d’Opus 4.5 qui a « échoué » à une tâche de réservation dans tau2-bench, le benchmark successeur. L’agent avait trouvé une faille de politique qui constituait en réalité le meilleur résultat pour l’utilisateur. L’évaluation de l’état est préférable à la comparaison de transcriptions, mais l’état cible reste une annotation, et les annotations comportent des erreurs. Auditez les cas qui réussissent trop facilement, pas uniquement ceux qui échouent.

Les versions des benchmarks et les environnements modifient le résultat

Les chiffres tau-bench originaux ci-dessus illustrent la fiabilité sur des essais répétés ; ils ne constituent pas le classement actuel des modèles. Le dépôt tau-bench maintenu présente désormais tau3-bench, qui ajoute la recherche de connaissances et la voix full-duplex. Le correctif de grading de juillet 2026 pour la version v1.0.1 modifie les scores banking_knowledge : les résultats des versions antérieures ne sont pas comparables pour ce domaine. Épinglez les révisions des tâches et des graders ainsi que le modèle, et réévaluez les trajectoires sauvegardées lorsqu’une annotation est corrigée.

Choisissez un benchmark qui exerce l’interface réellement déployée. Des tests de service client uniquement textuels ne peuvent pas établir la gestion des interruptions dans un agent vocal. Les tâches de recherche de connaissances nécessitent également le corpus, la configuration de recherche et les éléments de preuve disponibles à chaque tour. Reprenez ces formes de tâches pour vos cas de régression locaux plutôt que d’importer le rang d’un leaderboard public comme critère de release.

Le sandbox fait également partie du test. L’étude d’infrastructure de février 2026 d’Anthropic a constaté une différence de six points de pourcentage sur Terminal-Bench 2.0 entre ses configurations de ressources stricte et non plafonnée, avec le même modèle, le même harness et les mêmes tâches. Une marge supplémentaire réduisait les échecs d’infrastructure et permettait également des stratégies de résolution différentes. Documentez les garanties et limites de CPU et de RAM, les timeouts, la concurrence, l’accès réseau et le traitement des erreurs d’infrastructure. Rapportez ces échecs séparément sans les supprimer discrètement du dénominateur des tâches attendues.

Évaluations des composants

Les métriques de résultat et de trajectoire indiquent que l’exécution a échoué et donnent approximativement l’endroit. Les évaluations de composants notent un span : le chunk récupéré était-il pertinent, le sous-agent a-t-il renvoyé le schéma attendu par son appelant, la réponse de l’outil a-t-elle été correctement parsée ? Attachez le score au span plutôt qu’à l’exécution, afin que « quel outil s’est dégradé cette semaine ? » soit une requête et non une nouvelle exécution.

Trois contrôles couvrent la majorité des cas :

  • Évaluation par span : exécutez la métrique adaptée au type de span. Les spans de retrieval reçoivent des métriques de rappel et de précision par rapport au chunk annoté ; les spans de sous-agents reçoivent une validation du schéma ainsi que leur propre score d’exactitude des outils ; les spans d’outils reçoivent un taux d’erreur et une latence.
  • Interprétation des résultats d’outils : fournissez à l’agent une sortie d’outil correcte mais difficile à exploiter (liste vide, correspondance partielle, timestamp obsolète) et vérifiez son action suivante. Un outil peut être correct tandis que l’agent le lit mal, et cet échec peut n’apparaître que deux étapes plus tard.
  • Attribution de l’échec : l’échec visible se situe généralement en aval de la véritable cause. Attribuez-le au premier span dont la sortie était déjà incorrecte, et non à l’étape qui a levé l’erreur.

C’est également ici que les mathématiques cumulatives de l’introduction prennent tout leur sens. Si 20 étapes semblent correctes isolément, l’exécution peut tout de même échouer la plupart du temps. Les taux de réussite par span montrent quelle étape fonctionne à 95 % et laquelle fonctionne à 70 %.


La boucle de rétroaction des traces vers l’évaluation

Exploitez les échecs de production avant d’imaginer de nouveaux cas d’évaluation.

La boucle de rétroaction des traces vers l’évaluationLa boucle de rétroaction des traces vers l’évaluation

La boucle :

  1. Capturez suffisamment d’éléments de preuve dans la trace pour reconstruire l’échec, en contrôlant les contenus sensibles.
  2. Annotez ce qui a échoué.
  3. Regroupez les échecs similaires.
  4. Conservez des goldens représentatifs, y compris les variantes qui nécessitent des résultats différents.
  5. Versionnez le dataset.
  6. Exécutez-le en CI.
  7. Continuez à scorer online les traces de production échantillonnées.

Le dépôt compagnon trace2evals implémente la boucle complète pour un agent de support défectueux. Il capture des spans OpenTelemetry GenAI, détecte les échecs avec des règles déterministes, déduplique les cas dans un dataset golden versionné et rejoue chaque golden en CI. Le backend par défaut remplace le modèle par des règles déterministes qui reproduisent les décisions de l’agent défectueux ; ainsi, make demo reproduit toute la boucle offline sans clé API. Exécutez uv sync --extra live et définissez une clé API : les mêmes commandes piloteront alors un modèle réel.

Il s’agit d’un pipeline pédagogique. La révision relue le 6 septembre 2026 comporte encore des cas limites dans les scorers, des contrôles d’autorisation fondés sur les noms et un état de trial partagé. Son adaptateur de traces attend ses propres attributs de span et formats de messages. Les exemples corrigés ici ne mettent pas à jour ce dépôt et n’établissent pas d’autorisation de production ; validez l’autorisation réussie et limitée à la ressource pour chaque mutation, et isolez les trials avant de vous fier à leurs verdicts CI.

Exploiter les échecs avec l’analyse d’erreurs

Le guide pratique de Hamel présente le workflow : examiner les conversations réelles, prendre des notes ouvertes, catégoriser les échecs et construire des tests spécifiques.

  1. Examinez les traces et notez librement ce qui n’a pas fonctionné.
  2. Regroupez les échecs récurrents dans des catégories nommées.
  3. Annotez les traces selon cette taxonomie.
  4. Construisez des tests spécifiques pour les clusters exploitables les plus importants.

Ne commencez pas par des labels comme reasoning_issue ou tool_problem. Ils sont trop vagues pour être testés. Utilisez des labels comme missing_identity_verification, date_argument_mismatch, retried_same_tool_after_429 ou stopped_before_database_update. Un label aussi précis indique exactement ce que le test de régression doit vérifier.

Dédupliquer avant de promouvoir

La boucle d’exploitation des traces comporte un piège : ajouter indéfiniment chaque mauvaise trace. Vous obtenez alors un dataset volumineux, coûteux et étroit. Il réussit sur des quasi-doublons de mars tout en manquant la nouvelle forme du même bug en juin.

Commencez par regrouper. Conservez un golden représentatif par cluster, puis gardez les variantes ayant des permissions, des arguments, des états de récupération ou des résultats attendus différents. Une formulation similaire ne rend pas deux cas de politique équivalents. Stockez les identifiants de traces associés dans des métadonnées à accès contrôlé afin qu’un reviewer puisse examiner les éléments de preuve ultérieurement.

Si un cluster d’échecs réapparaît après un correctif, le cas de régression ne s’est pas généralisé. Revoyez le cluster et ajoutez les variantes comportementales manquantes plutôt que de collecter des transcriptions presque identiques.

Versionner le dataset

Versionnez les datasets comme vous versionnez les prompts et le code. Chaque fois qu’un élément significatif change (modèle, prompt, tool schema, prompt du juge ou comportement de l’application), vous devez exécuter la même version du dataset avant et après.

Le contrôle CI doit figer :

  • la version du dataset
  • la version de l’application
  • la version du prompt
  • le modèle du juge
  • le prompt du juge
  • la version du code de l’évaluateur
  • les tool schemas, la politique, le harness et la configuration de gestion du contexte
  • la révision du modèle, les paramètres de raisonnement et d’échantillonnage
  • la fixture d’environnement initiale et les effets externes autorisés

Si l’un de ces éléments change, votre comparaison avant/après devient difficile à interpréter. Un fichier goldens-v3.json dans git convient à petite échelle. Les snapshots natifs des outils dans Langfuse, Phoenix, Braintrust ou LangSmith deviennent utiles lorsque le dataset est collaboratif.

Séparez les régressions de développement, les exemples de calibration du juge, la validation en réserve et les échantillons de monitoring. Regroupez les sessions, utilisateurs et tâches liés avant le split afin d’éviter que des quasi-doublons ne fuient entre les ensembles. Dès qu’un cas influence un prompt ou une rubric, traitez-le comme une donnée de développement. Une suite de régressions issue de l’exploitation des traces teste des régressions connues ; sa moyenne n’est pas une estimation du taux de réussite en production.

Réinitialisez l’état mutable pour chaque trial : fichiers, lignes de base de données, caches et fixtures d’outils. Isolez les credentials et les effets externes, et maintenez des budgets identiques pour le candidat et la baseline. Rapportez séparément le nombre de tâches et le nombre de trials, ainsi que toutes les tentatives démarrées, les timeouts, les crashes et les résultats non scorables. Comparez les résultats appariés sur les mêmes tâches. Ces choix suivent l’approche des trials propres et de l’évaluation des résultats décrite dans le guide d’évaluation d’Anthropic.

Exécuter les évaluations en CI

Un contrôle de release doit faire échouer le build lorsqu’une métrique franchit sa limite convenue. Sinon, la suite d’évaluation n’est qu’un dashboard.

Après avoir restauré la fixture du cas dans un trial isolé, le test doit réexécuter l’agent actuel sur l’entrée du golden. Il ne doit pas simplement rejouer l’ancienne trace ayant échoué (esquisse ; la version exécutable se trouve dans le dépôt compagnon) :

@pytest.mark.parametrize("golden", GOLDENS, ids=[item["id"] for item in GOLDENS])
def test_agent_regression(golden: dict) -> None:
    answer, fresh_trace = run_agent_and_capture_trace(golden["input"])

    refired = set(flag_failures(fresh_trace)) & set(golden["failure_modes"])
    assert not refired, f"failure mode regressed: {sorted(refired)}"

    assert tool_correctness(
        called=[call["name"] for call in fresh_trace["tool_calls"]],
        expected=golden["expected_tools"],
        mode=golden.get("tool_match", "in_order"),
    ) >= golden.get("tool_threshold", 1.0)

Cette distinction est facile à manquer. Le rôle du dataset est de détecter la prochaine version de l’agent qui répéterait un ancien échec, et non d’archiver l’échec lui-même.


Calibrer le juge avant de lui faire confiance

Le LLM-as-judge est utile. Il est également facile de se tromper soi-même avec cet outil.

G-Eval évalue trois benchmarks de méta-évaluation. SummEval est construit à partir de résumés d’actualités CNN/DailyMail ; Topical-Chat est un benchmark de dialogue fondé sur les connaissances ; QAGS teste la cohérence factuelle sur des résumés CNN/DailyMail et XSum. Avec GPT-4 comme backbone, G-Eval-4 a atteint une corrélation de Spearman de 0,514 avec les jugements humains sur SummEval. Sa fonction de score pondère les niveaux de notation par la probabilité des tokens (score=ip(si)si\text{score} = \sum_i p(s_i)\,s_i).

L’article a estimé les probabilités de tokens de GPT-4 par 20 échantillonnages, car ce modèle ne les exposait pas dans l’expérience. Un modèle hébergé peut ne fournir aucun logprob exploitable ; conservez donc la rubric, mais ne laissez pas entendre que vous avez reproduit la pondération probabiliste de l’article. Ces résultats comparent le protocole de l’article à ses baselines NLG sur ces benchmarks. Ils justifient le test d’un juge fondé sur une rubric explicite, pas son remplacement général des métriques automatiques ou d’un benchmark de trajectoires d’agents en production.

MT-Bench a montré que GPT-4 était d’accord avec les préférences humaines à une fréquence comparable à celle de l’accord entre humains. Ce résultat a contribué à populariser l’évaluation par LLM. Des travaux ultérieurs ont mis en évidence des biais de position, de longueur et d’auto-préférence. Les scores du juge peuvent également varier lorsque le prompt ou la version du modèle change.

JudgeBench a construit des paires de réponses dont l’une était objectivement incorrecte dans des domaines vérifiables : connaissances, raisonnement, mathématiques et code. Avec un prompt de juge standard, GPT-4o a obtenu 50,9 %, à peine mieux qu’un pile ou face ; le prompt Arena-Hard plus robuste de l’article n’a porté le même modèle qu’à 56,6 %. Le remplacement du modèle avec ce prompt plus robuste a davantage d’importance : Claude 3.5 Sonnet, meilleur juge généraliste testé, a atteint 64,3 %, et o3-mini avec un effort de raisonnement élevé a atteint 80,9 %. Les réponses fausses mais formulées avec assurance restent difficiles à détecter pour un juge qui ne raisonne pas avant de noter.

Traitez le juge comme un instrument de mesure : calibrez-le sur des annotations humaines avant de lui faire noter quoi que ce soit et vérifiez à nouveau sa calibration chaque fois que le modèle ou le prompt du juge change.

Boucle de calibration du jugeBoucle de calibration du juge

Lorsqu’un juge est nécessaire, rendez son verdict structuré. Schema-Guided Reasoning (SGR) fournit au verdict un schéma qui définit la forme de sortie et facilite son inspection. Structured Outputs ou le constrained decoding peuvent imposer la forme de l’objet, les champs requis et les contraintes de valeur pour des champs tels que evidence, passed_criteria, failed_criteria, failure_mode et score.

Placez les champs de preuve avant le score si cela facilite l’inspection de l’enregistrement. L’ordre des champs relève de la présentation et ne garantit pas le raisonnement. Un verdict valide selon le schéma peut tout de même contenir des éléments de preuve non étayés ou un score peu fiable. Utilisez la calibration sur des annotations humaines, des validateurs déterministes et une revue de la transcription pour tester la fiabilité du juge. La CI peut comparer un objet JSON stable, mais cela vérifie l’inspectabilité et la forme, sans prouver que les étapes de la rubric ont été suivies.

Un verdict structuré peut également modifier la courbe de coût. Traitez un modèle moins cher comme un candidat, et non comme un remplacement automatique. Exécutez-le sur le même ensemble de calibration annoté par des humains. Comparez son accord, son taux de faux positifs et son taux de faux négatifs avec ceux du juge plus puissant. Utilisez-le pour les cas courants uniquement s’il franchit les seuils définis par votre application. Conservez le juge plus puissant pour les désaccords, les cas à haut risque ou les exécutions de calibration.

Checklist de base pour l’hygiène des juges :

  1. Privilégiez le binaire réussite/échec lorsque c’est possible. Les échelles à cinq niveaux donnent une fausse impression de précision.
  2. Annotez des trajectoires couvrant les modes d’échec réels avant de finaliser la rubric. Choisissez la taille de l’échantillon en fonction de la couverture et de l’incertitude que la décision peut tolérer, puis réservez des cas distincts pour la validation.
  3. Mesurez l’accord juge-humain avec le kappa de Cohen, une matrice de confusion et le rappel positif/négatif. Le kappa mesure l’accord après prise en compte de l’accord attendu par hasard ; plus il est élevé, mieux c’est. Un juge qui répond toujours « réussite » n’a aucun pouvoir de discrimination utile ; son kappa peut donc être nul ou indéfini. Décidez quoi faire lorsqu’il est indéfini avant d’utiliser cette métrique pour approuver une release.
  4. Décomposez les critères trop généraux. « L’agent a-t-il vérifié l’identité avant le tool call de remboursement ? » vaut mieux que « La trajectoire était-elle bonne ? »
  5. Émettez le verdict via un schéma SGR contenant les éléments de preuve, les critères échoués, le mode d’échec et le score.
  6. Comparez les juges d’une même famille et de familles différentes à des annotations humaines conservées pour la validation ; la séparation des familles ne suffit pas à établir la fiabilité.
  7. Mesurez la sensibilité à l’ordre des paires. Ne conservez la randomisation ou l’agrégation avec inversion de l’ordre que si elle améliore les décisions sur les cas conservés pour la validation ; une étude contrôlée de 2026 a constaté que l’inversion pouvait nuire aux cas adversariaux.
  8. N’accordez aucun crédit au texte supplémentaire, sauf s’il apporte un contenu correct, pertinent et étayé. Une réponse plus longue n’est pas nécessairement meilleure.
  9. Figez le modèle du juge, le prompt, le dataset, le schéma et la version de l’application.
  10. Recalibrez après toute modification du modèle, du prompt, des outils, de la politique ou du schéma.

Un panel constitue une autre option à tester. PoLL a rapporté un meilleur alignement avec les jugements humains, une réduction du biais intra-modèle et un coût inférieur à sa baseline mono-GPT-4 sur six datasets. Ces résultats concernent ses modèles, ses tâches et ses prix historiques. Ils n’établissent pas qu’un panel est plus sûr pour votre tâche. Comparez ses faux positifs, ses faux négatifs, son coût et la charge de traitement des désaccords avec ceux d’un juge calibré unique sur des labels conservés pour la validation.

Il n’existe pas de seuil universel de kappa qui rende un juge adapté à la CI. Rapportez la matrice de confusion, le nombre de labels, le taux de faux positifs parmi les échecs humains et le taux de faux négatifs parmi les réussites humaines, avec l’incertitude associée. Choisissez les limites de release en fonction des conséquences de ces erreurs. Utilisez des files de revue lorsque les éléments de preuve sont trop faibles pour une acceptation automatique et conservez une autorisation humaine pour les actions conséquentes lorsque le workflow l’exige.


Les garde-fous bloquent inline ; les évaluations online observent après coup

Ces concepts sont souvent confondus parce qu’ils produisent tous deux des scores. La différence tient à leur emplacement : inline dans le chemin de la requête, avant la release ou après la réponse.

Garde-fous et évaluations onlineGarde-fous et évaluations online

Les garde-fous s’exécutent inline. Ils sont rapides et visibles par l’utilisateur. Un garde-fou peut bloquer un tool call, masquer des PII, rejeter une prompt injection ou imposer une relance avant que la réponse ne quitte votre système. Un faux positif est un bug de production. Un faux négatif est plus discret et plus grave, car rien dans le chemin de la requête ne le signale. Les contrôles de schéma, de plage et de politique sont déterministes. La détection des injections et des PII repose sur des classifieurs : considérez donc les ratés comme attendus et maintenez une évaluation asynchrone pour surveiller ce qu’ils laissent passer.

Les évaluations offline s’exécutent avant la release. Elles sont reproductibles. Elles vérifient les prompts, les modèles, les outils, les retrievers et les politiques sur un dataset fixe.

Les évaluations online s’exécutent après la réponse, généralement sur du trafic échantillonné. Elles peuvent utiliser des juges LLM plus lents, car elles ne se trouvent pas sur le chemin de latence. Leur rôle est de détecter la dérive, de trouver de nouveaux clusters d’échecs et d’alimenter le dataset offline suivant.

Un mauvais placement est préjudiciable dans les deux cas :

  • Un juge dans le chemin de la requête ajoute de la latence et une nouvelle source d’instabilité.
  • Un garde-fou relégué à un scoring asynchrone laisse les violations de politique atteindre les utilisateurs.

Pour les tests de sécurité, distinguez la détection d’une attaque, la tentative d’une action interdite et la réussite effective d’un effet nuisible. Rapportez les effets nuisibles réussis par trial d’attaque, avec le threat model et le budget de tentatives, en parallèle de la réussite des tâches légitimes et des blocages à tort par trial bénin. Le score d’un détecteur ne peut pas, à lui seul, établir que les données sont restées privées ou qu’une écriture a été empêchée. Utilisez des cibles isolées ; le rapport d’incident d’évaluation de cybersécurité d’Anthropic montre pourquoi les effets des évaluations doivent être contenus.

Pour les systèmes à fort volume, évaluez un petit échantillon avec un juge plus puissant et un échantillon plus large avec des classifieurs moins coûteux. Déclenchez des alertes sur les clusters et les intervalles de confiance, pas sur une seule estimation ponctuelle bruitée.


Choix des outils

Aucun outil ne couvre à lui seul toute la boucle. Comparez séparément un store de traces/datasets et un runner CI/eval ; un même produit peut couvrir les deux, mais vous n’avez pas besoin de les acheter auprès d’un seul fournisseur.

Il s’agit d’un état des lieux réalisé par l’auteur le 6 septembre 2026. Chaque lien renvoie vers la documentation actuelle utilisée pour étayer la capacité indiquée. Les plans, licences, clés API, accès aux fournisseurs et exigences d’infrastructure restent applicables.

OutilChoisissez-le lorsque…Capacité vérifiée et condition
DeepEvalVous exécutez des contrôles en Python et pytest.deepeval test run exécute les fichiers de tests d’évaluation et les métriques en échec font échouer le build. Pour marquer une baseline officielle Confident AI, il faut CONFIDENT_API_KEY.
Inspect AIVous avez besoin de tâches de sécurité, frontier ou d’agents en sandbox.inspect eval et l’API Python exécutent les tâches ; les limites, agents, sandboxes et accès aux fournisseurs de modèles sont configurés séparément. Il s’agit d’un runner d’évaluation, pas d’un store de traces de production.
PhoenixVous avez besoin de tracing et d’évaluations self-hosted, avec les données conservées dans votre infrastructure.Phoenix documente un self-hosting gratuit sans limitation fonctionnelle, ainsi que des évaluations déterministes et LLM. Vous exploitez le déploiement.
LangfuseVous voulez un workflow open source de traces, datasets et expériences.Le cœur est self-hostable ; Docker Compose à petite échelle ne fournit ni haute disponibilité, ni mise à l’échelle, ni sauvegardes, tandis que certains add-ons nécessitent une licence. Son action d’expérience CI peut figer une version de dataset et faire échouer une régression.
LangSmithVous utilisez déjà LangChain/LangGraph et acceptez les limites de sa plateforme.L’hébergement de la plateforme propose Cloud, Bring Your Own Cloud (BYOC) et des options self-hosted ; BYOC et self-hosted nécessitent Enterprise. Le déploiement hybride concerne les Agent Servers et est distinct de l’hébergement de la plateforme de tracing et d’évaluation.
BraintrustLes retours de PR gérés et les snapshots d’expériences comparables comptent davantage que le self-hosting.Sa documentation CI/CD montre une GitHub Action qui publie les résultats dans une pull request ; la CI nécessite une BRAINTRUST_API_KEY et le service géré.
PromptfooLes régressions de prompts ou de red teaming doivent s’exécuter avant le déploiement.Sa documentation CI couvre les parcours CLI et GitHub Action ; l’action nécessite une configuration, un token GitHub et les secrets du fournisseur lorsque le fournisseur sélectionné les exige. Ce n’est pas un store de traces.

Les remarques sur les compromis décrivent l’origine des coûts, pas leur montant. Les pages de tarification évoluent et les fournisseurs comptabilisent des éléments différents : traces, observations, spans, scores, utilisateurs, rétention ou données traitées. Vérifiez à nouveau les tarifs en vigueur avant de vous engager.

Recommandations selon les contraintes :

  • Choisissez Phoenix lorsque le self-hosting, la confidentialité et un tracing compatible avec OTel sont des exigences fortes et que votre équipe peut exploiter le déploiement.
  • Choisissez Langfuse si vous avez également besoin du versioning des datasets et d’expériences, et si vous pouvez exploiter votre stack de stockage ou acheter les add-ons requis.
  • Choisissez DeepEval lorsque la réussite/échec en CI avec Python/pytest constitue le contrat principal.
  • Choisissez Inspect AI lorsque l’essentiel du travail concerne l’évaluation d’agents de sécurité ou frontier dans des sandboxes configurables.
  • Choisissez LangSmith lorsque l’intégration LangChain/LangGraph correspond à votre workflow ; utilisez Cloud ou tenez compte de l’exigence Enterprise pour l’hébergement de la plateforme BYOC ou self-hosted.
  • Choisissez Braintrust lorsque les retours gérés sur les pull requests et la comparaison d’expériences justifient un service fondé sur une clé API.
  • Choisissez Promptfoo lorsque les contrôles de prompts ou de red teaming constituent la principale surface de régression et qu’un store de traces est hors périmètre.

Le choix de l’outil est secondaire. Si les échecs de production ne deviennent pas des cas de test, vous payez surtout pour du stockage de traces.


Checklist pratique de déploiement

Construisez le pipeline de preuves avant d’élargir la stack de métriques. Commencez par décider d’où viendront les exemples.

  1. Collectez d’abord les exécutions historiques. Si l’agent existe déjà, récupérez les traces, tickets de support, rapports de bugs, sessions avec pouces vers le bas, transcriptions de QA manuelle et notes de dogfooding avant de modifier l’implémentation. Si l’agent n’existe pas encore, journalisez chaque prototype et chaque exécution de test manuel dès le premier jour.

  2. Instrumentez la forme des traces. Capturez les messages, tool calls, arguments, sorties d’outils, erreurs, nombres de tokens, latence, coût, feedback utilisateur, version de l’application, version du prompt, version du modèle, version du tool schema et état final de l’environnement. Utilisez les conventions OpenTelemetry GenAI ou des spans de type OpenInference si vous souhaitez de la portabilité, et figez la version de la convention et de l’adaptateur. Capturez le contenu de manière sélective : masquez les secrets et les données personnelles, restreignez les accès et définissez la rétention avant de promouvoir les traces en datasets. Utilisez Langfuse, LangSmith, Phoenix ou Braintrust si vous voulez immédiatement une interface de traces et un workflow de datasets.

  3. Transformez les échecs réels en cas initiaux. Lisez les traces avant de les résumer avec un modèle. Pour chaque échec utile, stockez l’entrée, l’identifiant de trace source, l’état attendu, les invariants d’outils attendus, le mode d’échec, la gravité et la note du reviewer. Langfuse peut relier les éléments d’un dataset aux traces de production ; LangSmith peut créer des datasets à partir d’exécutions tracées. Conservez le lien source afin que le cas reste auditable.

  4. En l’absence d’historique, générez des cas de démarrage à froid. Demandez à un LLM de rédiger des tâches à partir des exigences produit, des politiques, des tool schemas, des machines à états et des macros de support. Couvrez les chemins nominaux et les échecs tels que les mauvaises permissions, l’absence de vérification d’identité, les résultats d’outils obsolètes, les dates ambiguës, les relances après des rate limits et les sorties d’outils contradictoires.

  5. Ne faites pas confiance aux cas synthétiques avant leur revue humaine. Les exemples synthétiques sont utiles pour la couverture, pas pour la vérité. Marquez-les avec source: synthetic et exigez qu’un reviewer approuve le résultat attendu. Exécutez si possible un chemin de référence connu comme correct et validez indépendamment les attentes générées ; l’utilisation d’une autre famille de modèles ne remplace pas cette vérification.

  6. Construisez un petit dataset équilibré. Incluez des réussites, des échecs, des refus, des cas limites, des cas à nombreux tours, des cas sensibles du point de vue des politiques et des chemins alternatifs valides. Ne faites pas du golden « l’ancienne transcription exacte ». Stockez ce qu’un golden doit contenir ci-dessus, ainsi que le mode d’échec qui a placé le cas dans la suite.

  7. Ajoutez d’abord les contrôles déterministes. L’ordre des outils lorsqu’il relève de la politique, les arguments requis, la validation du schéma, les diffs de l’état final, les limites de boucles et les plafonds de tokens et de latence, ainsi que les invariants propres à la tâche, doivent être exécutés avant tout juge.

  8. Ajoutez un juge structuré par SGR. Utilisez-le uniquement pour la partie qui nécessite une interprétation. Calibrez-le sur des annotations humaines et testez la rubric choisie sur des cas de validation non utilisés précédemment. S’il ne sépare pas les bons et les mauvais exemples sur l’ensemble de calibration, corrigez la rubric avant de le brancher à la CI.

  9. Reliez la boucle. Exécutez la petite suite offline en CI, la suite plus large avant la release, évaluez online le trafic de production échantillonné et réinjectez dans le dataset offline les clusters d’échecs online récurrents.

Votre première suite d’évaluation manquera des cas. Exécutez-la tout de même, puis ajoutez les échecs récurrents comme cas. Une suite exécutée chaque jour vous fournit les éléments nécessaires pour l’améliorer.


Références