Alejandro Rioja.
AI Agents Operations

De Eval-Harness die Ik Gebruik om AI-Agents Zonder Angst te Lanceren

Alejandro Rioja
Alejandro Rioja
6 min lezen
TL;DR

Agents zonder angst lanceren komt voort uit één ding: een eval-harness. Een vaste set beoordeelde testgevallen, automatisch gescoord (asserties plus een LLM-jurylid), uitgevoerd vóór elke prompt- of modelwijziging. Houdt de score stand, dan lanceer je. De testset wordt opgebouwd uit echte productiefouten.

Gratis nieuwsbrief

Elke woensdag. 28.400+ operators. Geen opvulling.

Inhoudsopgave

Bijgewerkt juni 2026.

TL;DR: De reden dat ik een prompt kan wijzigen of een model kan verwisselen op een live agent zonder mijn adem in te houden, is één ding: een eval-harness. Een vaste set beoordeelde testgevallen, automatisch gescoord — harde asserties waar ik ze kan schrijven, een LLM-jurylid waar dat niet lukt — uitgevoerd vóór elke wijziging. Houdt de score stand, dan lanceer ik. Daalt de score, dan niet. De testset is niet synthetisch; hij is opgebouwd uit echte productiefouten, dus elke bug wordt een permanente regressietest.

Operator’s read: Over meer dan 100 agents heen is het verschil tussen die ik met vertrouwen aanraak en die waar ik bang voor ben, of ze evals hebben. Geen eval-harness betekent dat elke promptaanpassing een gok is. Een eval-harness verandert “ik denk dat dit beter is” in “dit is meetbaar 4 punten beter en heeft niets gebroken”. Dat is de hele ontgrendeling.

Je zou geen code lanceren zonder tests. Mensen lanceren voortdurend agents zonder evals en vragen zich dan af waarom een “kleine promptaanpassing” de productie brak. Een eval-harness is de testsuite voor niet-deterministische software. Hier is de harness die ik daadwerkelijk draai.

Begin met een testset opgebouwd uit echte fouten

De harness is slechts zo goed als zijn testgevallen, en de beste testgevallen komen uit de productie, niet uit je verbeelding. Telkens als een agent in het wild faalt, leg ik de exacte invoer vast (ik log elke run met een trace-ID — zie hoe je een agent in productie debugt) en maak er een eval-geval van:

typescript
interface EvalCase {
  id: string;
  input: AgentInput;        // de exacte productie-invoer
  expected?: string;        // ground truth, wanneer die er is
  assertions: Assertion[];  // harde controles die moeten slagen
  rubric?: string;          // voor het LLM-jurylid, wanneer de uitvoer open is
}

Twee praktijken doen er hier toe. Haal uit de productie, zodat je evals testen wat daadwerkelijk breekt, niet wat je gokte dat zou kunnen breken. En dek de hele spreiding — het gelukkige pad, randgevallen, vijandige invoer, en de lege/misvormde invoer die stille fouten veroorzaakt. Een testset van 30 tot 50 goedgekozen gevallen vangt veel meer dan 500 luie. Ik heb liever 40 gevallen die elk een echte faalmodus vertegenwoordigen dan duizend die allemaal hetzelfde makkelijke pad testen.

Scoor eerst met asserties, daarna met een LLM-jurylid

Niet elke uitvoer heeft een model nodig om te beoordelen. Ik grijp naar de goedkoopste scorer die werkt.

Harde asserties voor alles wat gestructureerd is. Parseert de uitvoer als geldige JSON? Bevat het het vereiste veld? Valt de geëxtraheerde datum binnen het bereik? Heeft het de juiste tool met de juiste argumenten aangeroepen? Deze zijn deterministisch, gratis en ondubbelzinnig — schrijf er zoveel je kunt.

typescript
const assertions: Assertion[] = [
  (out) => isValidJSON(out),
  (out) => parse(out).category in ALLOWED_CATEGORIES,
  (out) => parse(out).confidence >= 0 && parse(out).confidence <= 1,
];

Een LLM-jurylid voor de open rest — toon, behulpzaamheid, “heeft dit de vraag echt beantwoord”. Hier geef je een model de invoer, de uitvoer en een rubriek, en vraag je het om te scoren. Twee regels houden het jurylid eerlijk: maak de rubriek specifiek (een schaal van 1 tot 5 met beschreven ankers verslaat “beoordeel de kwaliteit”), en gebruik een sterk model als jurylid — beoordelen is een redeneertaak, dus dit is een plek waar ik met plezier voor Sonnet betaal, zelfs wanneer de agent zelf op Haiku draait volgens de kostenwiskunde. Een vage rubriek of een zwak jurylid geeft je ruis die op signaal lijkt.

Draai de harness vóór elke wijziging

De harness bestaat om één vraag te beantwoorden: heeft deze wijziging de agent beter of slechter gemaakt? Dus ik draai hem vóór elke promptbewerking, modelverwisseling of toolwijziging.

bash
# baseline op main
npm run eval -- --suite=booking-agent > baseline.json

# maak de wijziging, draai dan opnieuw
npm run eval -- --suite=booking-agent > candidate.json

# vergelijk
npm run eval:diff baseline.json candidate.json

De diff toont de geaggregeerde score, het slagen/falen per geval en — cruciaal — welke specifieke gevallen geregresseerd zijn. Een aggregaat dat omhoog kruipt terwijl drie gevallen stilletjes breken is geen verbetering; het is een afweging die ik wil zien en goedkeuren, niet eentje die er stiekem doorheen glipt. De diff per geval in de gaten houden is hoe je “één ding gerepareerd, twee andere gebroken” vermijdt — de faalmodus die mensen bang maakt voor hun eigen prompts.

Stel een regressiepoort in en laat hem blokkeren

Zodra je de harness vertrouwt, koppel hem als poort in het pad naar productie. Mijn regel is bot: een wijziging die de score onder de baselinedrempel duwt, wordt niet gelanceerd. Niet “ik kijk er later naar” — hij is geblokkeerd, net als een falende CI-test.

typescript
const PASS_THRESHOLD = 0.90; // 90% van de gevallen moet slagen
if (candidate.passRate < PASS_THRESHOLD || candidate.passRate < baseline.passRate) {
  throw new Error(`Eval regression: ${candidate.passRate} < ${baseline.passRate}`);
}

Dit is wat evals omzet van een leuke-bijkomstigheid in het ding dat je snel laat bewegen. De poort is wat “zonder angst lanceren” letterlijk waar maakt: het ergste geval voor een slechte wijziging is een rode eval-run, geen productie-incident. En omdat de testset groeit telkens als er iets breekt, wordt de poort vanzelf strenger en beschermender naarmate de tijd vordert.

Houd rekening met non-determinisme bij het scoren

Een subtiliteit waar mensen over struikelen: dezelfde invoer kan over runs heen anders scoren omdat het model anders sampelt. Als je elk geval één keer draait, zie je spookregressies — een geval dat “brak” maar in werkelijkheid slechts samplingruis is.

Twee tegenmaatregelen. Draai evals op temperature: 0 om de variantie te verkleinen (het zal die niet volledig wegnemen). En voor gevallen die je hebt zien flikkeren: draai ze N keer en neem het slagingspercentage, niet een enkel slagen/falen. Een geval dat 9 van de 10 keer slaagt is er beter aan toe dan een dat 5 van de 10 keer slaagt, ook al kunnen beide een groene enkele run tonen. Dit is hetzelfde principe van volume-boven-anekdote dat ik gebruik bij het debuggen van intermitterende fouten — één run is een mening, vijftig runs zijn data.

Sluit de lus met productiemonitoring

De eval-harness test tegen bekende gevallen. De productie werpt nieuwe op. Dus de lus is: monitor live gedrag, vang een nieuwe faalmodus, maak er een eval-geval van, repareer het, en nu is het permanent bewaakt. De monitoringkant — het bijhouden van slagingspercentage, uitvoervaliditeit en kosten per run op live verkeer — is wat ik behandel in hoe ik meet of een AI-agent daadwerkelijk werkt. Evals en monitoring zijn twee helften van hetzelfde systeem: monitoring vindt de bugs, evals zorgen dat ze dood blijven.

Die feedbacklus is het echte product. Elke afzonderlijke eval-set veroudert; een proces dat elke productiefout omzet in een permanente test wordt elke week sterker. Zo gaat een agent van “eng om aan te raken” naar iets dat ik op een vrijdagmiddag zonder te knipperen herstructureer.

Veelgestelde vragen

Wat hoort er in een eval-set voor een AI-agent?

Echte productie-invoer omgezet in beoordeelde gevallen — gelukkig pad, randgevallen, vijandige en misvormde invoer — elk met harde asserties en, voor open uitvoer, een LLM-jurylid-rubriek. 30 tot 50 gevallen uit echte fouten verslaan honderden synthetische die allemaal het makkelijke pad testen.

Moet ik een LLM gebruiken om agent-uitvoer te beoordelen?

Gebruik harde asserties overal waar de uitvoer gestructureerd is (geldige JSON, juist veld, juiste toolaanroep) — ze zijn gratis en deterministisch. Reserveer een LLM-jurylid voor open eigenschappen als toon en behulpzaamheid, met een specifieke rubriek en een sterk jurymodel, zodat je signaal krijgt, geen ruis.

Hoe voorkom ik dat een promptwijziging de productie stilletjes breekt?

Draai de eval-harness vóór elke wijziging en diff tegen een baseline, met aandacht voor regressies per geval, niet alleen de geaggregeerde score. Koppel deploys vervolgens aan het resultaat, zodat elke wijziging die onder de baselinedrempel zakt, geblokkeerd wordt als een falende test.

Hoe ga ik om met non-determinisme in evals?

Draai op temperatuur 0 om de variantie te verminderen, en voor gevallen die flikkeren, draai ze meerdere keren en scoor het slagingspercentage in plaats van een enkele run. Een geval dat 9 van de 10 keer slaagt is gezonder dan een dat 5 van de 10 keer slaagt, zelfs als een enkele run beide groen toont.

Lees verder

Ontvang het AI-playbook in je inbox

Elke woensdag. 28.400+ operators. Geen opvulling.

↵ alle resultaten bekijken esc esc om te sluiten