Automatische vertaling
Dit artikel is automatisch vertaald vanuit de oorspronkelijke Engelse versie.
AI-agents in productie evalueren: van traces naar testsuites
Een chatbotantwoord is één rij. Een agent-run is een boom.
Dat verschil breekt veel evaluatiegewoonten. Het uiteindelijke antwoord kan er goed uitzien terwijl de agent een vereiste tool oversloeg, dezelfde call 17 keer opnieuw probeerde, een toolresultaat verkeerd las, of een pad volgde dat in productie niet toegestaan zou zijn. Als je alleen het antwoord beoordeelt, mis je het deel waar het systeem daadwerkelijk faalde.
TL;DR: Agent-evals hebben drie lagen nodig: uitkomstmetrics, trajectmetrics en componentmetrics. Bouw rond deze lus: trace -> label -> cluster -> dedupe -> geversioneerde dataset -> CI-gate -> online monitoring. Gebruik deterministische checks voor toolvolgorde, argumenten, loops en invarianten. Gebruik LLM-judges alleen waar de check afhangt van interpretatie, structureer die judges met Schema-Guided Reasoning (SGR), en kalibreer ze tegen menselijke labels voordat je ze vertrouwt.
Waarom agent-evals anders zijn
Traditionele LLM-evals scoren meestal één input-outputpaar: relevantie, faithfulness, correctheid, veiligheid, misschien stijl. Agents voegen planning, tool-calls, retries en termination checks toe, en elke stap is een nieuwe plek waar het mis kan gaan.
Neem een refund-agent. Het transcript kan goed eindigen terwijl de trace fout is:
lookup_order -> issue_refund -> final_answer
De output-eval slaagt. Een trajectory-eval zou moeten falen omdat verify_identity nooit draaide vóór issue_refund. Voor agents die tools gebruiken zijn answer-only evals smoke tests: ze vangen totale uitval en missen verder alles.
Er is een tweede probleem: fouten stapelen zich op. Als een workflow van 20 stappen per stap 95% betrouwbaar is, dan komt de end-to-end succeskans nog steeds uit op ongeveer 36%:
Dus de agent kan er solide uitzien in geïsoleerde checks en toch de meeste volledige runs laten mislukken. De breuk zit meestal ergens in het midden, en die vinden vereist zichtbaarheid op componentniveau, niet nog een blik op het antwoord.
Twee onderzoeksteams hebben dit gekwantificeerd.
tau-bench is een benchmark waarin een agent airline- en retail-klantenservicetaken afhandelt: hij praat met een gesimuleerde gebruiker, roept API's aan en moet onderweg domeinbeleid volgen. De beoordeling negeert het transcript. Nadat het gesprek eindigt, controleert de benchmark of de database de geannoteerde doelstatus heeft bereikt, dus een beleefde, plausibel klinkende run die de verkeerde rijen achterlaat, faalt alsnog. Onder die beoordeling slaagde zelfs GPT-4o voor minder dan de helft van de taken. Het paper introduceerde ook pass^k: voer dezelfde taak k keer uit en tel alleen een pass als de agent in alle k runs slaagt. Retailscores die voor één poging nog acceptabel leken, zakten onder 25% bij k = 8. Dezelfde agent, dezelfde taak, acht runs, meestal verschillende uitkomsten. Die inconsistentie is onzichtbaar als je elke evalcase maar één keer draait.
MAST stelt een andere vraag: niet hoe vaak agents falen, maar waarom. De auteurs annoteerden meer dan 1.600 execution traces uit 7 populaire multi-agentframeworks en verdeelden de fouten in 14 terugkerende modi. Bijna geen daarvan is "het model gaf een fout antwoord." Het gaat om zaken als vage roldefinities (system design), één agent die negeert wat een andere agent hem vertelde (inter-agent misalignment), en succes verklaren zonder het resultaat te controleren (no verification). De meeste fouten zitten in de harness: de prompts, de orchestration logic, de ontbrekende checks. Een sterker basismodel verkleint deze aantallen, maar kan geen verificatiestap repareren die nooit is gebouwd. Daarom moet je de harness evalueren, niet alleen het model erin.
De adoptiekloof
De meeste teams hebben het ruwe materiaal voor betere evals al. Ze hebben traces. Ze hebben ze alleen nog niet omgezet in tests.
De survey State of Agent Engineering van LangChain is het duidelijkste publieke beeld van deze kloof. Daarin staat dat 57,3% van de respondenten al agents in productie heeft, 89% enige observability heeft, 52,4% offline evals draait en 37,3% online evals draait. En op de vraag wat productie blokkeert, noemde 32% van de respondenten kwaliteit, vóór latency op 20%. Datgene wat evals meten is precies waar teams vastlopen.
Dat laat teams in een ongemakkelijke tussenstaat: ze kunnen een slechte run achteraf inspecteren, en daarna toch dezelfde fout twee keer shippen.
Eén regel lost dit op: elke gediagnosticeerde productiefout moet een trace, een label, een datasetrij en een scorer achterlaten. Als het opnieuw kan gebeuren, hoort het in de regressiesuite.
Kies metrics op basis van failure mode
De juiste metric hangt af van de failure mode, niet van het framework. De nuttige opsplitsing heeft drie scopes:
- Outcome-evals beantwoorden of de taak slaagde.
- Trajectory-evals beantwoorden of het pad valide, efficiënt en policy-compliant was.
- Component-evals beantwoorden welke tool, retriever, sub-agent of beslisstap brak.
Elke scope kan offline draaien (vaste, replaybare cases vóór release) of online (gesamplede productietraces na de response); de guardrails-sectie hieronder behandelt die splitsing in detail. De korte versie: offline evals kunnen goldens vereisen, terwijl online evals beter invarianten, distributies en async checks gebruiken die buiten het request-pad blijven.
| Vraag | Metricfamilie | Offline-/online-contract | Deterministisch of judge? | Let op |
|---|---|---|---|---|
| Riep de agent de juiste tools aan? | Tool correctness: exacte, in-order of any-order match | Exacte goldens offline; required-tool-invarianten en anomalieën online | Deterministisch | Exact match bestraft valide alternatieve paden |
| Riep hij ze aan met de juiste inputs? | Argument correctness, schemavalidatie, parameter match | Verwachte argumenten offline; schema-, bereik- en policychecks online | Beide | Juiste tool plus verkeerde argumenten blijft kapot |
| Verspilde hij stappen? | Step efficiency, retry count, loopdetectie, cost en latency | Step- en loopbudgetten offline; cost- en latency-drift online | Meestal deterministisch | Hoge task completion kan duur rondzwerven verbergen |
| Slaagde de taak daadwerkelijk? | Task completion, outcome grading, final state diff | Simulator of golden state offline; final state, gebruikerssignaal of async judge online | Judge of state check | Beoordeel waar mogelijk de omgevingsstatus |
| Behield hij context over meerdere turns? | Multi-turn fidelity, role adherence, conversation completeness | Gescripte long-horizon-cases offline; gesamplede lange sessies online | Judge | Single-turn-tests zeggen niets over beurt 14 |
| Stopte hij op het juiste moment? | Termination correctness, premature success, endless work | Scenariotests offline; loop-, timeout- en false-success-monitors online | Beide | "Done" kan een gehallucineerde status zijn |
| Interpreteerde hij toolresultaten goed? | Tool-result understanding, downstream state checks | Adversarial tool outputs offline; downstream state checks en gesamplede review online | Beide | De tool kan correct zijn terwijl de agent hem verkeerd leest |
Begin met deterministische metrics. Ze zijn goedkoop, snel en driften niet.
Tool-call-correctheid
Tool correctness vergelijkt de aangeroepen tools met de verwachte tools. Kies de strengheid bewust:
- Exact match: de sequentie moet exact overeenkomen. Gebruik dit wanneer volgorde policy is, bijvoorbeeld
lookup_order -> verify_identity -> issue_refund. - In-order match: vereiste tools moeten in de juiste relatieve volgorde voorkomen, maar extra onschuldige calls zijn toegestaan.
- Any-order match: vereiste tools moeten voorkomen, maar de volgorde mag variëren.
Een kleine lokale scorer is genoeg om te beginnen:
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":
return len(set(expected) & set(called)) / len(set(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
DeepEval's Tool Correctness metric biedt dezelfde knoppen via should_consider_ordering en should_exact_match.
Argument-correctheid
De juiste tool aanroepen met de verkeerde argumenten is vaak erger dan de verkeerde tool aanroepen, omdat de trace er normaal uitziet.
Voor eenvoudige gevallen valideer je JSON-schema en exacte waarden. Voor semantische gevallen sla je verwachte argumenten op en beoordeel je de delta's:
{
"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"
}
}
}
Een tool-name-metric kan 2026-06-17 niet vangen waar beleid 2026-06-19 vereist. De dataset moet dus ook argumenten opslaan.
Efficiëntie, loops en dead ends
Het pad doet ertoe, zelfs wanneer de bestemming wordt bereikt. Een agent die de taak voltooit na vijf redundante tool-calls wijst nog steeds op een planningsprobleem en kost meer om te draaien.
Goedkope signalen waarmee je moet beginnen:
- Redundant-call rate: identieke tool-calls met identieke argumenten die meer dan twee keer worden herhaald.
- Trace shape anomalies: plotselinge pieken in diepte, aantal tool-calls, tokenaantal, latency of cost.
- Path convergence: hoe dicht de run bij het kortst bekende geldige pad voor de taak ligt.
- Termination correctness: of de agent te vroeg stopte, bleef doorwerken na succes, of succes verklaarde zonder de vereiste statuswijziging.
Draai deze waar mogelijk vóór een judge. Een loopdetector is een paar regels over de trace. Daar is geen model voor nodig.
Task completion en outcome grading
End-to-end is de vraag: "kreeg de gebruiker wat hij vroeg?"
Twee patronen werken het best:
- Referenceless task-completion judging: haal het doel uit de input en beoordeel of de trace plus het uiteindelijke antwoord dat doel bereikten. Dit werkt online omdat productieverkeer zelden golden outputs heeft.
- Environment-state grading: vergelijk de uiteindelijke databaserijen, bestanden, tickets, boekingen of records met een geannoteerde doelstatus. Dit is robuuster dan transcriptmatching omdat agents geldige paden kunnen vinden die jij niet hebt uitgeschreven.
De tweede optie is beter als je die kunt bouwen. De eindstatus is het contract. Het transcript is alleen bewijs.
Het trace-naar-eval-vliegwiel
Bedenk je evalset niet eerst. Mijn productiefouten.
De lus:
- Leg de volledige trace vast.
- Label wat faalde.
- Groepeer vergelijkbare fouten.
- Houd één representatieve golden per cluster.
- Versioneer de dataset.
- Draai hem in CI.
- Blijf gesamplede productietraces online scoren.
Mijn fouten met error analysis
Hamel Husain en Shreya Shankar onderwijzen een error-analysis-workflow precies voor deze stap; Hamels field guide loopt erdoorheen. De eerste twee stappen lenen hun naam uit kwalitatief onderzoek, maar de methode is eenvoudig: lees traces, maak aantekeningen, benoem de patronen.
- Open coding: lees 30 tot 50 echte traces en schrijf vrije notities over wat er misging.
- Axial coding: cluster die notities in 5 of 6 benoemde foutcategorieën.
- Label alles tegen de taxonomie.
- Bouw metrics voor de grootste buckets.
Begin niet met labels als reasoning_issue of tool_problem. Die zijn te vaag om te testen. Gebruik labels als missing_identity_verification, date_argument_mismatch, retried_same_tool_after_429 of stopped_before_database_update. Een label dat zo specifiek is, vertelt je exact wat de regressietest moet asserten.
Dedupliqueer voordat je promote
De trace-mining-lus heeft een valkuil: elke slechte trace voor altijd blijven toevoegen. Dat creëert een dataset die groot, duur en smal is. Hij slaagt op bijna-duplicaten uit maart terwijl hij de nieuwe vorm van dezelfde bug in juni mist.
Groepeer eerst. Promote één representatieve golden per cluster. Sla de gerelateerde trace-ID's op in metadata zodat een reviewer later het productie-evidence kan inspecteren.
Als een failure cluster terugkeert na een fix, generaliseerde de regressiecase niet. Cluster opnieuw en verbreed de golden in plaats van 15 puntsvoorbeelden toe te voegen.
Versioneer de dataset
Versioneer datasets zoals je prompts en code versioneert. Wanneer er iets betekenisvol verandert (model, prompt, toolschema, judge-prompt of appgedrag), wil je dezelfde datasetversie vóór en na draaien.
De CI-gate moet het volgende pinnen:
- datasetversie
- appversie
- promptversie
- judge-model
- judge-prompt
- evaluator-codeversie
Als een van die dingen verschuift, wordt je before/after-vergelijking troebel. Een goldens-v3.json-bestand in git is prima op kleine schaal. Tool-native snapshots in Langfuse, Phoenix, Braintrust of LangSmith helpen zodra de dataset collaboratief wordt.
Gate CI
Een falende metric moet een falende build worden, anders is de evalsuite alleen een dashboard dat niemand leest.
De test moet de huidige agent opnieuw draaien tegen de golden input. Hij moet niet alleen de oude mislukte trace replayen:
@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)
Dit onderscheid is makkelijk om fout te doen. Het is de taak van de dataset om te vangen dat de volgende versie van de agent een oude fout herhaalt, niet om de fout zelf te archiveren.
Kalibreer de judge voordat je hem vertrouwt
LLM-as-judge helpt. Het is ook makkelijk om jezelf ermee voor de gek te houden.
Het idee heeft een trackrecord. G-Eval liet zien dat een judge die stap voor stap door een expliciete rubric loopt, menselijke ratings beter volgt dan de oudere automatische metrics die hij verving. MT-Bench liet zien dat GPT-4 ongeveer net zo vaak met menselijke voorkeuren overeenkomt als mensen onderling, en dat maakte LLM-judging mainstream. Daarna kwamen de kanttekeningen: judges geven de voorkeur aan welk antwoord ook maar als eerste in een pairwise prompt verschijnt, geven langere antwoorden hogere scores, prefereren outputs uit hun eigen modelfamilie, en verschuiven wanneer de prompt- of modelversie verandert. JudgeBench testte judges op response-paren waarbij één antwoord objectief fout is en vond dat zelfs sterke judges op de moeilijke gevallen rond coin-flip-accuratesse blijven hangen.
Behandel de judge als een meetinstrument.
Wanneer een judge nodig is, maak het verdict gestructureerd. Schema-Guided Reasoning (SGR) is hier het standaardpatroon: definieer het reasoning-pad van de judge als een Pydantic-schema, draai het via Structured Outputs of constrained decoding, en dwing het model om velden uit te geven zoals evidence, passed_criteria, failed_criteria, failure_mode en score.
Dat maakt de judge niet magisch correct. Het maakt de meting wel reproduceerbaarder. De judge moet bij elke run en op elk compatibel model door dezelfde vooraf gedefinieerde rubricstappen lopen, in dezelfde veldvolgorde. Een reviewer kan benoemde velden inspecteren in plaats van een alinea te moeten parsen. CI kan een stabiel JSON-object diffen. Kalibratie wordt eenvoudiger omdat de rubric niet langer verstopt zit in vrije tekst.
Het verandert ook de cost curve. Als de reasoning-topology expliciet is en de output constrained is, zijn goedkopere modellen vaak al goed genoeg voor routinematig judgen. Bewaar de zwaardere judge voor meningsverschillen, high-risk-cases of kalibratieruns in plaats van ervoor te betalen op elke trace.
| Bias | Wat gebeurt er | Mitigatie |
|---|---|---|
| Positie | Pairwise prompts geven één slot de voorkeur | Wissel de volgorde en neem het gemiddelde van beide permutaties |
| Verbositeit | Langere antwoorden scoren hoger, zelfs als kwaliteit gelijk blijft | Penaliseer unsupported verbosity in de rubric |
| Zelfvoorkeur | Een judge geeft de voorkeur aan zijn eigen modelfamilie | Gebruik een andere modelfamilie of een jury |
| Sycophancy | De judge crediteert niet-geverifieerde claims | Vereis bewijs uit de trace in het verdict |
| Calibration drift | Een model- of promptupdate verschuift scores | Pin judge-model en prompt; kalibreer opnieuw bij verandering |
Standaard checklist voor judge-hygiëne:
- Geef waar mogelijk de voorkeur aan binaire pass/fail. Schalen van vijf punten nodigen uit tot nep-precisie.
- Label 30 tot 50 trajectories handmatig voordat je de definitieve rubric schrijft.
- Meet judge-mens-overeenstemming met Cohen's kappa of gewone TPR/TNR.
- Splits grove criteria op. "Verifieerde de agent identiteit vóór de refund-tool-call?" is beter dan "Was het traject goed?"
- Laat het verdict via een SGR-schema emitten met evidence, failed criteria, failure mode en score.
- Gebruik waar mogelijk een judge uit een andere modelfamilie dan de generator.
- Randomiseer de pairwise-volgorde en neem het gemiddelde van beide richtingen.
- Pin het judge-model, de prompt, dataset, schema en appversie.
- Kalibreer opnieuw na wijzigingen in model, prompt, tool, beleid of schema.
Gebruik voor high-stakes-scores liever een kleine jury dan één grote judge. PoLL testte exact deze opzet: een panel van kleinere judges uit niet-overlappende modelfamilies, waarvan de verdicts werden samengevoegd tot één score. Over zes datasets volgde het panel menselijke oordelen beter dan één enkele GPT-4-judge, vermeed het de self-preference bias die een solitaire judge heeft voor output uit de eigen familie, en kostte het meer dan zeven keer minder. Houd menselijke review voor beslissingen die geld, toegang, veiligheid of compliance raken.
Als een judge op jouw taak met mensen overeenkomt op 0,55 kappa, gebruik hem dan niet om deploys te blokkeren. Gebruik hem om reviewqueues te sorteren. Zit hij rond 0,75 en zijn de kosten van falen gematigd, dan is een CI-gate veel beter te verdedigen.
Online evals zijn geen guardrails
Mensen halen deze door elkaar omdat ze allebei scores produceren. Ze zitten op verschillende plekken.
Guardrails draaien inline. Ze zijn snel, deterministisch en user-visible. Een guardrail kan een tool-call blokkeren, PII redigeren, prompt injection afwijzen, of een retry forceren voordat de response je systeem verlaat. Een false positive is een productiebug.
Offline evals draaien vóór release. Ze zijn reproduceerbaar. Ze gate'en prompts, modellen, tools, retrievers en beleid tegen een vaste dataset.
Online evals draaien na de response, meestal op gesampled verkeer. Ze kunnen tragere LLM-judges gebruiken omdat ze niet in het latency-pad zitten. Hun taak is drift detecteren, nieuwe failure clusters vinden en de volgende offline dataset voeden.
Plaats je ze verkeerd, dan doet het in beide richtingen pijn:
- Een judge in het request-pad voegt latency en een nieuwe bron van flakiness toe.
- Een guardrail die wordt gedegradeerd naar async scoring laat beleidschendingen gebruikers bereiken.
Voor systemen met hoog volume score je een kleine sample met een sterkere judge en een bredere sample met goedkopere classifiers. Alarmeer op clusters en confidence bounds, niet op één ruisige puntschatting.
Toolkeuzes
Geen enkele tool bezit de hele lus. De meeste serieuze stacks gebruiken twee onderdelen: een trace store en een CI/eval-runner.
| Tool | Beste fit | CI-verhaal | Self-hosting-verhaal | Trade-off |
|---|---|---|---|---|
| DeepEval | Pytest-native agent- en LLM-evals | Sterk: deepeval test run past in CI |
Core library is lokaal/open source | Judge-calls en cloudfeatures kunnen cost toevoegen |
| Inspect AI | Safety-, frontier- en sandboxed evaluations | CLI en Python API | Volledig lokaal/open source | Geen productie-traceplatform |
| Phoenix | OTel/OpenInference-tracing plus evals | Custom scripts | Sterke self-host-optie | Managed alerting zit in de commerciële laag |
| Langfuse | Trace store, datasets, promptversies | Experiments en custom gates | Sterke self-host-optie | Eval-metrics zijn minder batteries-included dan DeepEval |
| LangSmith | LangChain/LangGraph-tracing en evals | pytest, Vitest, GitHub-workflows | Enterprise self-host | Closed source; let op per-seat- en trace-volume-pricing |
| Braintrust | Eval-gedreven productlus en PR-review | Zeer sterke managed PR-regression flow | Enterprise/hybride | Spanvolume, verwerkte data en aantal scores kunnen oplopen |
| Promptfoo | Prompttests en red-team-suites | GitHub, GitLab, Jenkins, CircleCI | Lokale/open source core | Geweldige pre-release-runner, geen trace hub |
De opmerkingen over trade-offs beschrijven waar kosten vandaan komen, niet wat ze zijn. Pricing pages veranderen en vendors tellen verschillende dingen: traces, observations, spans, scores, users, retention of processed data. Controleer live pricing opnieuw voordat je commit.
Beslissingsshortcuts:
- Self-hosted tracing nodig met OTel-portabiliteit: begin met Phoenix of Langfuse.
- Een code-first CI-gate nodig: begin met DeepEval.
- Al committed aan LangGraph: LangSmith is handig.
- Managed PR-regression review gewenst: Braintrust is moeilijk te verslaan.
- Security- en red-team-cases domineren: Promptfoo is de gerichte tool.
- Safety-research of gecontroleerd benchmarkwerk: Inspect AI past beter.
Toolkeuze is secundair. Als productiefouten geen testcases worden, betaal je vooral voor trace-opslag.
Een praktische rollout-checklist
Voordat de implementatie slim wordt, bouw je de evidence-pijplijn. De eerste vraag is niet "welke metric moeten we optimaliseren?" maar "waar komen de voorbeelden vandaan?"
-
Verzamel eerst historische runs. Als de agent al bestaat, trek dan traces, supporttickets, bugreports, thumbs-down-sessies, handmatige QA-transcripten en dogfooding-notities binnen voordat je de implementatie wijzigt. Bestaat de agent nog niet, log dan vanaf dag één elke prototype- en handmatige testrun.
-
Instrumenteer de tracevorm. Leg messages, tool-calls, argumenten, tooloutputs, errors, tokenaantallen, latency, cost, gebruikersfeedback, appversie, promptversie, modelversie, toolschema-versie en uiteindelijke environment state vast. Gebruik OpenTelemetry GenAI conventions of OpenInference-stijl spans als je portabiliteit wilt. Gebruik Langfuse, LangSmith, Phoenix of Braintrust als je direct een trace-UI en datasetworkflow wilt.
-
Maak van echte fouten seed cases. Lees de traces voordat je ze door een model laat samenvatten. Sla voor elke bruikbare fout de input, bron-trace-ID, verwachte status, verwachte tool-invarianten, failure mode, severity en reviewernotitie op. Langfuse kan datasetitems teruglinken naar productietraces; LangSmith kan datasets maken vanuit getracede runs. Bewaar de bronlink zodat de case auditabel blijft.
-
Als er geen historie is, genereer dan cold-start-cases. Vraag een LLM om taken op te stellen uit producteisen, beleid, toolschema's, state machines en supportmacro's. Genereer zowel happy paths als "should not happen"-cases: verkeerde permissies, ontbrekende identiteitschecks, stale toolresultaten, dubbelzinnige datums, retries na rate limits, en tooloutputs die de gebruikersvraag tegenspreken.
-
Vertrouw synthetische cases niet totdat een mens ze reviewt. Synthetische voorbeelden zijn nuttig voor dekking, niet voor waarheid. Markeer ze met
source: synthetic, eis dat een reviewer de verwachte uitkomst goedkeurt, draai waar mogelijk een known-good reference path, en vermijd het gebruik van dezelfde modelfamilie om zowel de case te genereren als het resultaat te beoordelen. -
Bouw een kleine gebalanceerde dataset. Neem successen, fouten, refusals, boundary cases, long-turn-cases, policy-sensitive-cases en valide alternatieve paden op. Maak de golden niet "het exacte oude transcript". De golden moet de vereiste uitkomst, toegestane invarianten en failure mode coderen.
-
Voeg eerst deterministische checks toe. Vereiste toolvolgorde waar volgorde policy is, vereiste argumenten, schemavalidatie, final-state-diffs, looplimieten, token- en latency-plafonds en taakspecifieke invarianten moeten vóór elke judge draaien.
-
Voeg één SGR-gevormde judge toe. Gebruik hem alleen voor het deel dat interpretatie vereist. Kalibreer hem tegen menselijke labels. Als hij goede en slechte voorbeelden in de kalibratieset niet kan scheiden, repareer dan de rubric voordat je hem in CI hangt.
-
Sluit de lus. Draai de kleine offline suite in CI, draai de grotere suite vóór release, score gesampled productieverkeer online, en promote terugkerende online failure clusters terug naar de offline dataset.
Je eerste evalsuite zal op saaie manieren fout zijn. Ship hem toch. Een suite die je elke dag draait is makkelijker te repareren dan een perfect design doc dat nooit een slechte PR blokkeert.
Belangrijkste punten
- Agent-evals zijn trace-evals. Het uiteindelijke antwoord is slechts één node in de run.
- Toolselectie, argument-correctheid, loopdetectie, task completion en multi-turn fidelity horen in aparte metrics.
- Het productievliegwiel is trace -> label -> cluster -> dedupe -> dataset -> CI-gate -> online score.
- Begin deterministisch. Toolchecks, argumentchecks, state checks en loopdetectors zijn goedkoper en stabieler dan judges.
- LLM-judges hebben structuur en kalibratie nodig. Gebruik SGR voor reproduceerbare, inspecteerbare verdicts, en pin daarna het judge-model, de prompt, het schema, de datasetversie, de appversie en de sample met menselijke labels.
- Offline evals gate'en bekende cases vóór release. Online evals minen gesamplede productietraces na de response. Guardrails blokkeren onveilig gedrag inline.
- De meeste teams hebben een trace store en een CI-runner nodig. Kies saaie tools waarmee productiefouten snel regressietests worden.
Referenties
- LangChain - State of Agent Engineering
- Anthropic - Demystifying Evals for AI Agents
- Hamel Husain - A Field Guide to Rapidly Improving AI Products
- OpenTelemetry semantic conventions for generative AI systems
- DeepEval Tool Correctness
- DeepEval Task Completion
- Schema-Guided Reasoning on vLLM: Structured Outputs with xgrammar and Pydantic
- Langfuse datasets and versioning
- LangSmith - Create and manage datasets programmatically
- Braintrust - Evaluate systematically
- Phoenix LLM evals
- Promptfoo GitHub Action integration
- tau-bench: A Benchmark for Tool-Agent-User Interaction in Real-World Domains
- Why Do Multi-Agent LLM Systems Fail?
- G-Eval: NLG Evaluation using GPT-4 with Better Human Alignment
- Judging LLM-as-a-Judge with MT-Bench and Chatbot Arena
- Replacing Judges with Juries: Evaluating LLM Generations with a Panel of Diverse Models
- JudgeBench: A Benchmark for Evaluating LLM-based Judges
- Self-Preference Bias in LLM-as-a-Judge