É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.

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. L’évaluation de la seule réponse masque ces échecs.

Pour les ingénieurs qui opèrent des agents utilisant des outils en production, la solution consiste à transformer les traces reproductibles en cas de régression bornés : des vérifications déterministes imposent l’ordre des outils, les arguments, les boucles et les invariants ; des juges calibrés prennent en charge les décisions nécessitant 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.

En bref : les evals d’agents comportent trois niveaux : métriques de résultat, métriques de trajectoire et métriques de composant. Construisez votre workflow autour de cette boucle : trace -> label -> cluster -> déduplication -> dataset versionné -> gate CI -> monitoring en ligne. Utilisez des vérifications déterministes pour l’ordre des outils, les arguments, les boucles et les invariants. Utilisez des juges LLM uniquement lorsque la vérification dépend d’une interprétation, structurez ces juges avec Schema-Guided Reasoning (SGR), puis calibrez-les sur des labels humains avant de leur faire confiance.


Pourquoi les evals d’agents sont différentes

Les evals traditionnelles de LLM évaluent généralement une paire entrée-sortie : pertinence, fidélité, correction, sécurité, voire style. Les agents ajoutent la planification, les tool calls, les retries et les vérifications de terminaison ; chaque étape devient donc un nouveau point de défaillance.

Prenons un agent de remboursement. La transcription peut se terminer correctement alors que la trace est erronée :

lookup_order -> issue_refund -> final_answer

L’eval de la sortie passe. Une eval de trajectoire devrait échouer, car verify_identity n’a jamais été exécuté avant issue_refund. Pour les agents utilisant des outils, les evals limitées à la réponse sont des smoke tests : elles détectent les pannes totales et ignorent tout le reste.

Un deuxième 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 présente la même fiabilité de 95 %, son taux de succès end-to-end atteint environ 36 % :

0.95200.360.95^{20} \approx 0.36

L’agent peut donc sembler solide lors de vérifications isolées et échouer malgré tout sur la majorité des exécutions complètes. La rupture se situe généralement quelque part au milieu ; l’identifier nécessite une visibilité au niveau des composants, et non un nouvel examen de la réponse.

Une ligne contre un arbre : où se cachent les échecs des agentsUne ligne contre 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 secteurs aérien et de la vente au détail. L’agent dialogue avec un utilisateur simulé, appelle des APIs et doit respecter la politique du domaine. Après la conversation, le grader vérifie si la base de données a atteint l’état cible annoté. Une transcription plausible avec des lignes incorrectes échoue tout de même.

Avec cette méthode d’évaluation, GPT-4o ne résolvait que 35,2 % des tâches aériennes et un peu plus de 60 % des tâches de vente au détail. L’article a également introduit pass^k : exécuter la même tâche k fois et ne compter un succès que si l’agent réussit les k exécutions.

La branche la plus facile, celle de la vente au détail, est tombée sous les 25 % avec k = 8. Pour plus des trois quarts de ces tâches, le même agent confronté huit fois à la même tâche échouait au moins une fois. Une eval sur une seule exécution ne peut pas révéler cette inconsistance.

MAST étudie les raisons des échecs des agents. Les auteurs ont construit une taxonomie à 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 qui entoure le modèle.


Le retard dans l’adoption

L’enquête de LangChain State of Agent Engineering (1 340 répondants, menée fin 2025) suggère que de nombreuses équipes disposent déjà des éléments nécessaires à de meilleures evals. Elle indique que 89 % avaient une forme d’observabilité, que 52,4 % exécutaient des evals offline et que 37,3 % exécutaient des evals online.

L’enquête indique également que 57,3 % des répondants ont déjà des agents en production. Lorsqu’on leur demande ce qui bloque la mise en production, 32 % citent la qualité et 20 % la latence. Il s’agit d’une enquête menée par un fournisseur auprès de ses répondants, et non d’un recensement des équipes travaillant sur des agents ; elle révèle néanmoins 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 inspecter une exécution défaillante a posteriori, puis livrer malgré tout le même échec une deuxième fois.

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


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

La métrique appropriée dépend du mode d’échec, et non du framework. La distinction utile comporte trois niveaux :

  1. Les evals de résultat répondent à la question : la tâche a-t-elle réussi ?
  2. Les evals de trajectoire répondent à la question : le chemin était-il valide, efficace et conforme aux politiques ?
  3. Les evals de composant 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 s’exécuter 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 guardrails détaille cette distinction. Les evals 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 evals online devraient privilégier les invariants, les distributions et les vérifications asynchrones qui restent hors du chemin de la requête.

QuestionFamille de métriquesContrat offline / onlineDéterministe ou juge ?Attention à…
L’agent a-t-il appelé les bons outils ?Correction des outils : correspondance exacte, ordonnée ou quelconqueGoldens 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 ?Correction 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 un échec
A-t-il gaspillé des étapes ?Efficacité des étapes, nombre de retries, 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 complétion peut masquer un parcours coûteux
La tâche a-t-elle réellement réussi ?Complétion de 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 vérification d’étatÉvaluez l’état de l’environnement lorsque c’est possible
Le contexte a-t-il été préservé entre les tours ?Fidélité multi-tour, respect des rôles, exhaustivité de la conversationCas scriptés à long horizon offline ; sessions longues échantillonnées onlineJugeLes tests sur un seul tour ne disent rien du tour 14
S’est-il arrêté au bon moment ?Correction de la terminaison, succès prématuré, travail sans finTests de scénarios offline ; monitoring 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, vérifications de l’état en avalSorties d’outils adversariales offline ; vérifications 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 sont peu coûteuses, rapides et ne dérivent pas.

Correction des tool calls

La correction des outils compare les outils appelés aux outils attendus. Choisissez délibérément le niveau de stricteté :

  • Correspondance exacte : la séquence doit correspondre exactement. Utilisez-la lorsque l’ordre est imposé par la politique, par exemple lookup_order -> verify_identity -> issue_refund.
  • Correspondance ordonnée : les outils requis doivent apparaître dans le bon ordre relatif, mais des appels supplémentaires inoffensifs sont autorisés.
  • Correspondance quelconque : les outils requis doivent apparaître, mais leur 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 not expected:
        return 1.0
    if mode == "exact":
        return float(called == expected)
    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

Le score in_order est le recall de la plus longue sous-séquence commune : la fraction de la séquence requise qui a été conservée dans le bon ordre. Remarquez ce qu’il ignore. Les appels parasites ne le diminuent pas ; un agent peut donc obtenir 1,0 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 interprétez les deux métriques ensemble. Le recall détecte l’étape manquante ; la précision détecte l’errance.

La métrique Tool Correctness de DeepEval expose les mêmes paramètres via should_consider_ordering et should_exact_match.

Correction 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 next Friday.",
    "expected_tools": ["lookup_order", "reschedule_delivery"],
    "expected_arguments": {
        "reschedule_delivery": {
            "order_id": "A-100",
            "date": "2026-06-19"
        }
    }
}

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

Le score associé à ce dataset est la correspondance des paramètres : la fraction des triplets (tool, key, value) attendus que l’agent a correctement produits.

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 called_args.get(tool, {}).get(key) == want:
                matched += 1
    return matched / total if total else 1.0

L’égalité exacte convient aux IDs, aux enums et aux dates déjà normalisées dans un format unique. Elle est inadaptée au texte libre, aux flottants et aux dates produites par le modèle dans un format quelconque, pour lesquels == signale à tort une réponse correcte. Évaluez ces champs selon leur nature : comparaison de chaînes normalisées, parsing de dates, tolérance numérique. La métrique reste la même ; c’est le comparateur propre à chaque 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 davantage à exécuter.

Voici les signaux peu coûteux à mettre en place en premier :

  • 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.
  • Correction 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é le 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 indique lequel des deux s’est produit.

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.

Complétion de tâche et évaluation du résultat

Pour évaluer le résultat, la question est : « L’utilisateur a-t-il obtenu ce qu’il demandait ? »

Deux approches fonctionnent particulièrement bien :

  • Évaluation de la complétion sans référence : extraire l’objectif de l’entrée et déterminer si la trace ainsi que la réponse finale l’ont atteint. Cette approche fonctionne online, car le trafic de production possède 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 méthode est plus robuste que la comparaison de transcriptions, car les agents peuvent trouver des chemins valides que vous n’aviez pas explicitement prévus.

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 rigoureux. Un audit de 2025 des benchmarks agentic a constaté que tau-bench évalue certaines tâches uniquement à partir de l’état de la base de données. Pour certaines tâches, le résultat annoté n’exige aucune modification d’état ni texte précis. Un agent qui ne fait rien peut alors obtenir un succès : 38 % sur la branche aérienne et 6,0 % sur la vente au détail, pour tout 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 dans la politique qui constituait en réalité un 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 peuvent comporter des erreurs. Auditez les cas qui passent trop facilement, pas uniquement ceux qui échouent.

Evals de composants

Les métriques de résultat et de trajectoire indiquent que l’exécution a échoué et, approximativement, où. Les evals de composants évaluent 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 propre réponse de l’outil a-t-elle été parsée ? Attachez le score au span plutôt qu’à l’exécution, afin que la question « quel outil s’est dégradé cette semaine ? » devienne une requête et non une nouvelle exécution.

Trois contrôles couvrent la majeure partie 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 recall et de précision par rapport au chunk annoté ; les spans de sous-agent reçoivent une validation de schéma ainsi que leur propre score de correction des outils ; les spans d’outil reçoivent un taux d’erreur et une latence.
  • Interprétation des tool results : fournissez à l’agent une sortie d’outil correcte mais difficile à exploiter (liste vide, correspondance partielle, timestamp obsolète) et vérifiez ce qu’il fait ensuite. Un outil peut être correct tandis que l’agent l’interprète mal ; l’échec n’apparaît alors que deux étapes plus loin.
  • 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 à ce niveau que les calculs de cumul présentés au début deviennent importants. Même 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 trace-to-eval

Commencez par exploiter les échecs de production avant d’imaginer de nouveaux cas d’évaluation.

La boucle trace-to-evalLa boucle trace-to-eval

La boucle :

  1. Capturez la trace complète.
  2. Annotez ce qui a échoué.
  3. Regroupez les échecs similaires.
  4. Conservez un golden représentatif par cluster.
  5. Versionnez le dataset.
  6. Exécutez-le dans la 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éfaillant. Il capture des spans GenAI OpenTelemetry, détecte les échecs avec des règles déterministes, déduplique les cas en un dataset golden versionné et rejoue chaque golden dans la 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éfaillant ; make demo reproduit donc toute la boucle offline, sans API key. Exécutez uv sync --extra live et définissez une API key pour que les mêmes commandes pilotent cette fois un modèle réel.

Exploiter les échecs avec l’analyse d’erreurs

Hamel Husain et Shreya Shankar enseignent un workflow d’analyse d’erreurs destiné précisément à cette étape ; le guide pratique de Hamel le décrit en détail. Les deux premières étapes reprennent leur nom dans la recherche qualitative, mais la méthode reste simple : lire les traces, prendre des notes et nommer les patterns.

  1. Codage ouvert : lisez 30 à 50 traces réelles et notez librement ce qui s’est mal passé.
  2. Codage axial : regroupez ces notes en 5 ou 6 catégories d’échec nommées.
  3. Annotez tout selon la taxonomie.
  4. Construisez des métriques pour les catégories les plus importantes.

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édupliquez avant de promouvoir

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

Regroupez d’abord. Promouvez un golden représentatif par cluster. Stockez les IDs des traces associées dans les métadonnées afin qu’un reviewer puisse inspecter ultérieurement les éléments de preuve issus de la production.

Si un cluster d’échecs réapparaît après un correctif, le cas de régression ne s’est pas généralisé. Recomposez les clusters et élargissez le golden au lieu d’ajouter 15 exemples ponctuels.

Versionnez le dataset

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

Le gate 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.

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

Ajoutez un gate CI

Une métrique en échec doit produire un build en échec ; sinon la suite d’evals n’est qu’un dashboard que personne ne consulte.

Le test doit rejouer l’agent actuel sur l’entrée golden. Il ne doit pas simplement rejouer l’ancienne trace défaillante (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 répétition d’un ancien échec par la prochaine version de l’agent, et non d’archiver l’échec lui-même.


Calibrez le juge avant de lui faire confiance

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

G-Eval évalue trois benchmarks de méta-évaluation. Il s’agit de SummEval, construit à partir de résumés d’actualités CNN/DailyMail ; de Topical-Chat, un benchmark de dialogue fondé sur des connaissances ; et de QAGS, qui teste la cohérence factuelle de 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 scoring 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 des 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 le 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 un rubric explicite, et non son remplacement général par les métriques automatiques ou par un benchmark de trajectoires d’agents en production.

MT-Bench a montré que GPT-4 était d’accord avec les préférences humaines à peu près aussi souvent que les humains entre eux. Ce résultat a contribué à populariser le jugement par LLM. Des travaux ultérieurs ont mis en évidence des biais de position, de longueur et de self-preference. 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 est objectivement fausse 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 renforcé a davantage d’impact : Claude 3.5 Sonnet, meilleur juge généraliste testé, a atteint 64,3 %, et o3-mini avec un effort de raisonnement élevé 80,9 %. Les réponses confiantes mais incorrectes restent difficiles à évaluer pour un juge qui ne raisonne pas avant de noter.

Traitez le juge comme un instrument de mesure : calibrez-le sur des labels humains avant toute utilisation et vérifiez à nouveau sa calibration dès 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 le verdict structuré. Schema-Guided Reasoning (SGR) fournit au verdict un schéma qui définit la forme de sa sortie et permet son inspection. Les Structured Outputs ou le constrained decoding peuvent imposer la forme de l’objet, les champs obligatoires 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 preuves non étayées ou un score peu fiable. Utilisez la calibration sur des labels humains, des validateurs déterministes et la revue de transcriptions pour tester la fiabilité du juge. La CI peut comparer par diff un objet JSON stable, mais cela vérifie l’inspectabilité et la forme, sans prouver que les étapes du rubric ont été suivies.

Un verdict structuré peut également modifier la courbe de coût. Considérez un modèle moins coûteux comme un candidat, et non comme un remplacement automatique. Exécutez-le sur le même jeu de calibration annoté par des humains. Comparez son accord, son taux de faux succès et son taux de faux échecs à 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 et les exécutions de calibration.

Checklist par défaut pour l’hygiène des juges :

  1. Privilégiez le pass/fail binaire lorsque c’est possible. Les échelles à cinq niveaux donnent une fausse impression de précision.
  2. Annotez manuellement 30 à 50 trajectoires avant de rédiger le rubric final.
  3. Mesurez l’accord juge-humain avec le kappa de Cohen, une matrice de confusion et le recall positif/négatif. Un juge qui répond toujours « pass » n’a aucune capacité de discrimination utile ; le kappa peut être nul ou indéfini lorsque le dénominateur de l’accord attendu est nul. Définissez explicitement la politique applicable au kappa indéfini avant d’utiliser cette métrique comme gate de déploiement.
  4. Décomposez les critères généraux. « L’agent a-t-il vérifié l’identité avant le tool call de remboursement ? » est préférable à « La trajectoire était-elle bonne ? »
  5. Émettez le verdict au moyen d’un schéma SGR contenant les preuves, les critères échoués, le mode d’échec et le score.
  6. Lorsque c’est possible, utilisez pour le juge une famille de modèles différente de celle du générateur.
  7. Randomisez l’ordre des paires et faites la moyenne dans les deux directions.
  8. Pénalisez la longueur non justifiée dans le rubric. 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, de l’outil, de la politique ou du schéma.

Pour les scores à fort enjeu, utilisez un petit jury plutôt qu’un seul grand juge. PoLL a testé un panel de juges plus petits issus de familles de modèles disjointes et a agrégé leurs verdicts. Sur six datasets, le panel suivait mieux les jugements humains qu’un juge GPT-4 unique. Il évitait également le biais de self-preference du juge unique, pour un coût plus de sept fois inférieur. Conservez une revue humaine pour les décisions qui affectent l’argent, l’accès, la sécurité ou la conformité.

Si un juge obtient un kappa de 0,55 avec les humains sur votre tâche, ne l’utilisez pas pour bloquer les déploiements. Utilisez-le pour trier les files de revue. S’il se situe autour de 0,75 et que le coût des échecs est modéré, un gate CI est beaucoup plus facile à justifier.


Les guardrails bloquent inline ; les evals online observent ensuite

Ces mécanismes 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.

Guardrails et evals onlineGuardrails et evals online

Les guardrails s’exécutent inline. Ils sont rapides et visibles par l’utilisateur. Un guardrail peut bloquer un tool call, rédiger des PII, rejeter une prompt injection ou forcer un retry 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 prévisibles et conservez une eval asynchrone pour surveiller ce qu’ils laissent passer.

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

Les evals online s’exécutent après la réponse, généralement sur du trafic échantillonné. Elles peuvent utiliser des juges LLM plus lents, puisqu’elles ne se trouvent pas sur le chemin de la 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 pénalisant dans les deux cas :

  • Un juge dans le chemin de la requête ajoute de la latence et une nouvelle source d’instabilité.
  • Un guardrail relégué à un scoring asynchrone laisse parvenir des violations de politique jusqu’aux utilisateurs.

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, et non 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 de CI/evals ; un même produit peut couvrir les deux, mais vous n’avez pas besoin de les acheter auprès du même fournisseur.

Cet instantané de l’auteur a été vérifié le 2026-08-16. Chaque lien renvoie vers la documentation utilisée pour étayer l’affirmation de capacité correspondante. Les plans, licences, API keys, accès aux providers et exigences d’infrastructure restent applicables.

OutilChoisissez-le lorsque…Capacité vérifiée et condition
DeepEvalPython et pytest doivent constituer le gate CI.deepeval test run exécute les fichiers d’eval 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 agentic de sécurité, frontier ou exécutées en sandbox.inspect eval et l’API Python exécutent les tâches ; les limites, agents, sandboxes et accès aux providers de modèles se configurent séparément. C’est un eval runner, pas un store de traces de production.
PhoenixVous avez besoin de tracing et d’evals 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 vous-même 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 scaling, ni backups, tandis que certains add-ons nécessitent une licence. Son CI experiment action peut figer une version de dataset et échouer en cas de régression.
LangSmithVous utilisez déjà LangChain/LangGraph et acceptez sa frontière de plateforme.Des modes cloud, hybride et self-hosted existent ; les déploiements hybrides et self-hosted sont des options Enterprise. La création de datasets et les workflows d’eval restent liés au déploiement sélectionné.
BraintrustLe feedback géré sur les PR et les snapshots d’expériences comparables comptent davantage que le self-hosting.Sa documentation CI/CD présente 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 chemins CLI et GitHub Action ; l’action nécessite une configuration, un token GitHub et les secrets du provider lorsque celui-ci les exige. Ce n’est pas un store de traces.

Les remarques sur les compromis indiquent d’où viennent les coûts, et non leur montant. Les pages tarifaires évoluent, et les fournisseurs comptabilisent des éléments différents : traces, observations, spans, scores, utilisateurs, rétention ou données traitées. Vérifiez les tarifs actuels 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 opérer le déploiement.
  • Choisissez Langfuse si vous avez également besoin du versioning des datasets et des expériences, et que vous pouvez opérer sa stack de stockage ou acheter les add-ons requis.
  • Choisissez DeepEval lorsque le pass/fail 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 l’emporte sur l’exigence Enterprise pour un déploiement hybride ou self-hosted.
  • Choisissez Braintrust lorsque le feedback géré sur les pull requests et la comparaison d’expériences justifient un service reposant sur une API key.
  • 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ù proviendront les exemples.

  1. Commencez par collecter 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 des outils, erreurs, nombres de tokens, latence, coût, feedback utilisateur, version de l’application, version du prompt, version du modèle, version du schéma d’outil et état final de l’environnement. Utilisez les conventions OpenTelemetry GenAI ou des spans de type OpenInference si vous voulez de la portabilité. 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’ID de la trace source, l’état attendu, les invariants d’outils attendus, le mode d’échec, la sévérité 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 des 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 cold start. Demandez à un LLM de rédiger des tâches à partir des exigences produit, politiques, tool schemas, machines à états et macros de support. Couvrez les happy paths et les échecs tels que permissions incorrectes, vérifications d’identité manquantes, résultats d’outils obsolètes, dates ambiguës, retries après des rate limits et sorties d’outils contradictoires.

  5. Ne faites pas confiance aux cas synthétiques avant revue humaine. Les exemples synthétiques sont utiles pour la couverture, pas pour établir la vérité. Marquez-les avec source: synthetic et exigez qu’un reviewer approuve le résultat attendu. Exécutez un chemin de référence connu comme correct lorsque c’est possible et utilisez des familles de modèles différentes pour générer le cas et évaluer le résultat.

  6. Construisez un petit dataset équilibré. Incluez des succès, des échecs, des refus, des cas limites, des cas à nombreux tours, des cas sensibles aux politiques et des chemins alternatifs valides. Ne faites pas du golden « l’ancienne transcription exacte ». Stockez ce qu’un golden doit contenir, ainsi que le mode d’échec qui a conduit le cas dans la suite.

  7. Ajoutez d’abord les contrôles déterministes. L’ordre des outils requis lorsque la politique l’impose, les arguments obligatoires, la validation du schéma, les diffs de l’état final, les limites de boucles, les plafonds de tokens et de latence ainsi que les invariants propres à la tâche doivent s’exécuter 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 labels humains. S’il ne distingue pas les bons et les mauvais exemples sur le jeu de calibration, corrigez le rubric avant de l’intégrer à la CI.

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

Votre première suite d’evals sera incorrecte de manière prévisible. Livrez-la tout de même. Une suite exécutée chaque jour est plus facile à corriger qu’un document de conception parfait qui ne bloque jamais une mauvaise PR.


Références