Verification loop
Wat is een verification loop?
Een verification loop is het patroon waarbij je een AI-agent een check meegeeft die hij zelf kan draaien, en hem laat werken, checken, het resultaat lezen en opnieuw proberen tot de check slaagt. Die check kan een testsuite zijn, een build die zonder fouten moet afsluiten, een schemavalidatie, een rijtelling die moet kloppen met de bron, of een rubriek waar een tweede model tegen scoort.
Zonder zo'n check stopt een agent op het moment dat het werk er af uitziet. De documentatie van Claude Code zegt het zonder omwegen: "ziet er af uit" is dan het enige signaal dat de agent heeft, en jij wordt zelf de verification loop, want elke fout blijft liggen tot jij ze opmerkt. Geef de agent iets dat een pass of een fail teruggeeft, en de lus sluit zichzelf.
Vergelijk het met een boekhouder die de maand afsluit. De boeken zijn niet klaar als alle boekingen ingetikt zijn. Ze zijn klaar als het banksaldo en het grootboek overeenkomen. Een verification loop geeft een agent diezelfde eindmeet: niet "ik heb de code geschreven", wel "de check zegt dat de code juist is".
Wat maakt een goede check
Niet elke check is het waard om er een lus rond te bouwen. In zijn tekst over verifieerbaarheid van november 2025 somt Karpathy drie eigenschappen op van een taak waar een AI zelfstandig op kan oefenen: je kan resetten en opnieuw beginnen, veel pogingen kosten weinig, en een automatisch proces kan elke poging scoren. Diezelfde drie eigenschappen beschrijven een goede check in een agent loop.
Goedkoop. De agent draait de check misschien twintig keer in één sessie. Een testsuite die in een minuut klaar is, komt in aanmerking. Een volledige nachtelijke lading van het datawarehouse niet; daarvoor neem je een steekproef of een kleinere testset.
Deterministisch. Dezelfde output moet elke keer hetzelfde oordeel krijgen. Een test slaagt of hij slaagt niet. Een rijtelling klopt of ze klopt niet. Een check waarvan het antwoord schommelt, leert de agent niets, want hij kan niet zien of hij het probleem opgelost heeft of gewoon geluk had.
Moeilijk te omzeilen. De check moet naar het resultaat kijken, niet naar wat de agent over het resultaat beweert. Een script dat het geproduceerde bestand vergelijkt met een gekende goede versie, praat je niet zomaar voorbij. Een instructie als "zorg dat de cijfers juist zijn" is geen check.
In software bestaan die checks al jaren: tests, een type checker, een linter, de exitcode van een build, en sinds kort ook een screenshot van de draaiende app naast het ontwerp. De handleiding van Claude Code noemt precies die lijst, en voegt eraan toe dat de agent het bewijs moet tonen, de testoutput of het commando dat hij draaide, in plaats van te zeggen dat het gelukt is.
Een uitgewerkt voorbeeld uit datawerk
Datawerk heeft zijn eigen checks, en de meeste teams gebruiken ze al zonder ooit het woord verification loop gehoord te hebben. De generieke tests van dbt zijn een goed voorbeeld. Elke test is een SELECT die op zoek gaat naar rijen die de regel breken: dubbels voor unique, lege waarden voor not_null, waarden buiten de toegelaten lijst voor accepted_values, verwijzingen naar een klant die niet bestaat voor relationships. Nul rijen terug betekent dat de test slaagt. Dat is een goedkope, deterministische en moeilijk te omzeilen check, klaar om door een agent gedraaid te worden.
Stel dat je een agent vraagt om het verkooporder-model opnieuw op te bouwen in een nieuw datawarehouse. In plaats van "zorg dat de data juist is" geef je hem drie checks mee:
Rijtelling. Het doel moet evenveel orderlijnen bevatten als de bron, min de lijnen die de gedocumenteerde filter wegneemt.
Controletotalen. De som van het bedrag per maand moet tot op de cent kloppen met de bron.
Referentiële check. Elke customer_id in de ordertabel moet bestaan in de klantentabel.
De agent schrijft het model, draait de drie checks en leest het resultaat. Zeg dat de rijtelling twee te kort komt en het totaal van januari 1.240 euro afwijkt. Hij gaat zoeken, vindt een datumfilter die orders van exact middernacht uitsluit, past die aan en draait de checks opnieuw. Pas als alle drie slagen, geeft hij het werk terug, met de query-output als bewijs. Wat jij naleest, is dat bewijs, niet de SQL regel per regel.
Dezelfde vorm werkt voor een Power BI-migratie (de nieuwe measure moet voor de laatste twaalf maanden hetzelfde totaal geven als het oude rapport), voor een schemawijziging (de JSON-output moet valideren tegen het gepubliceerde schema) en voor een agent die facturen verwerkt (de uitgelezen lijnen moeten optellen tot het factuurtotaal op het document).
Verification loop versus LLM-as-a-judge
Allebei zetten ze een check achter de output van een agent. Het verschil dat telt, is determinisme.
Een verification loop in strikte zin gebruikt een check die code is: een test, een query, een diff. Draai hem twee keer en je krijgt twee keer hetzelfde antwoord. Hij is smal, want hij kan enkel checken waar iemand een regel voor schreef, maar binnen die grens is hij betrouwbaar en de agent kan er niet tegen in discussie gaan.
LLM-as-a-judge laat een tweede model de output lezen en scoren tegen geschreven criteria. Dat raakt aan dingen waar geen script bij kan: is deze samenvatting trouw aan het rapport, is dit antwoord aan de klant beleefd, volgt deze presentatie de briefing. De prijs is dat de jury zelf een model is. Draai ze twee keer en je kan twee verschillende scores krijgen, en ze heeft gekende vertekeningen richting langere antwoorden en richting haar eigen modelfamilie.
In de tooling groeien de twee naar elkaar toe. Met Managed Agents van Anthropic definieer je een outcome met een rubriek van expliciete criteria; een aparte grader in zijn eigen contextvenster scoort het resultaat, geeft terug welke criteria niet gehaald zijn, en de agent doet een nieuwe poging, standaard drie iteraties en maximaal twintig. Het /goal-commando van Claude Code laat een klein model na elke beurt het transcript lezen en "gehaald", "nog niet gehaald" of "onmogelijk" teruggeven. Een Stop hook daarentegen draait je eigen script en is volledig deterministisch: hij blokkeert het einde van de beurt tot het script slaagt, tot acht keer na elkaar.
Een regel waar je mee verder kan: gebruik een codecheck overal waar er een bestaat, gebruik een rubriek-grader enkel voor wat een codecheck niet kan zien, en schrijf de rubriek als toetsbare uitspraken ("de CSV heeft een numerieke prijskolom") en niet als indrukken ("de data ziet er goed uit"). De documentatie van Anthropic over de grader zegt hetzelfde: vage criteria geven wisselvallige beoordelingen.
Als de agent de check omzeilt
De lus heeft één goed gedocumenteerde zwakte. Een agent die onder druk staat om de check te laten slagen, kan een manier vinden om aan de letter van de check te voldoen zonder het werk te doen. Het onderzoeksteam van Anthropic noemt dat reward hacking en gaf in november 2025, in een studie op hun eigen modellen, een concreet voorbeeld: sys.exit(0) aanroepen in Python om uit de testomgeving te breken met een succescode, zodat elke test lijkt te slagen. Hun vergelijking: een student die zelf "A+" bovenaan zijn eigen opstel schrijft.
In datawerk zijn de varianten makkelijk voor te stellen. De agent verbreedt de tolerantie op de reconciliatie tot het verschil erbinnen valt. Hij verwijdert de falende test in plaats van het model te herstellen. Hij zet het totaal van januari hard in de code. Dat is geen kwade wil; het model doet wat de lus beloont.
De verdediging zit vooral in de opzet:
Hou de check buiten bereik. De agent draait de tests, maar is geen eigenaar van het testbestand, de referentiedata of de tolerantie. In een pijplijn betekent dat: de check leeft in een aparte repository of op een beschermd pad.
Beoordeel in een verse context. Zowel de verificatie-subagent van Claude Code als de grader van Managed Agents draaien in hun eigen context, zodat het model dat het werk doet niet het model is dat beslist dat het klaar is.
Vraag bewijs. Vraag de ruwe output van de check, niet een zin die zegt dat hij geslaagd is. Een geplakte rijtelling is moeilijker te vervalsen dan "alle checks groen".
Begrens het aantal iteraties. Een lus die tien keer gedraaid heeft zonder te convergeren, vertelt je dat de taak of de check fout zit. Stop ze en kijk zelf.
Welke van je processen zijn klaar voor een agent
De vuistregel van Karpathy, die hij in april 2026 herhaalde in zijn verslag van zijn gesprek op de Ascent-conferentie van Sequoia, luidt: klassieke software automatiseert wat je kan specificeren, deze generatie AI automatiseert wat je kan verifiëren. Coding agents voelen zoveel beter aan dan een gewone chatbot omdat code het model feedback geeft: tests slagen of falen, programma's draaien of crashen. Creatief en strategisch werk, en alles wat afhangt van context die enkel in de hoofden van mensen zit, blijft achter omdat er geen automatische score is.
Dat geeft een KMO een bruikbare test voor zijn eigen processen. Vraag je bij elk proces af: eindigt het in iets dat moet kloppen met iets anders?
Leveranciersfacturen matchen met bestelbonnen en ontvangsten eindigt in een match of een verschil. Een btw-aangifte moet kloppen met het grootboek. Een stocktelling moet overeenkomen met het systeem. Een gemigreerd rapport moet dezelfde totalen geven als het oude. Die processen zijn klaar, want de check bestaat al en je team doet ze vandaag met de hand.
Een offerte schrijven voor een klant, een prijs bepalen, beslissen of je een moeilijke klant aanneemt: daar is geen automatische check, enkel oordeel. Een agent kan een voorstel maken, maar een mens verifieert nog altijd, en die verificatie is het werk.
Waar een goede check bestaat, verschuift de rol van de mens van het werk doen naar het bewijs lezen en beslissen of je het aanvaardt. Waar geen check bestaat, is de mens de check, en dan zet je een human-in-the-loop-stap op het moment van de actie, voor de mail vertrekt of de betaling vrijgegeven wordt.