Skip to main content
← Bekijk alle inzichten
AIAgentic WorkflowCode ReviewTooling

Het goedkoopste moment om ongelijk te hebben

2026-08-09·10 min read

Als een agent het grootste deel van de code schrijft, wat weerhoudt hem er dan van om met volle overtuiging het verkeerde op te leveren?

Ons antwoord bestaat uit drie reviewlagen, die op verschillende momenten en om verschillende redenen afgaan. Wat me verraste is welke laag het gewicht draagt. Het is niet de review van de code. Het is de laag die loopt terwijl er nog geen code te reviewen valt. Dat is het losse eind van de twee eerdere posts: waarom we Jira vervingen door markdown-tickets, en de skill en de loop waarmee een agent die tickets zelf oppakt.

Vóór de review: het ticket uitwerken op basis van de echte code

Een review kan nooit beter zijn dan waar hij tegen afmeet, dus de acceptatiecriteria moeten het afmeten waard zijn.

Dat begint bij hoe het ticket geschreven is: vanuit een checkout, tegen de echte code aan. Daarna dwingt de skill een vorm af op het resultaat. Objective in één of twee zinnen. Context onder 120 woorden. Ongeveer vijf acceptatiecriteria, één eis per criterium, geschreven op gedrag in plaats van op opleverpunten, zodat "tests slagen" en "versie verhoogd" per definitie afvallen.

Criteria over gedrag gebruiken de EARS-vorm: Wanneer <trigger>, zal het systeem <waarneembare uitkomst>. Dat is geen ceremonie. De trigger ís de testopzet, en hem opschrijven brengt aan het licht welke criteria alleen een draaiende applicatie kan bevestigen. Die worden later de handmatige test, en het zijn precies de criteria die niemand anders zou bedenken om te controleren.

De limieten per sectie bestaan om dezelfde reden. Een ticket wordt tijdens refinement in seconden gelezen, dus het legt vast wat en waarom, en nooit hoe. Wordt de sectie Context te lang, dan is er analyse terechtgekomen in een document dat een specificatie hoort te zijn, en de oplossing is die analyse doorschuiven naar het plan.

Het plan is het document dat het meeste verschil maakt

Daarna wordt het ticket gepland, en dit is de stap waar het de moeite waard is echt tijd in te steken.

Plannen gebeurt read-only, zoals de vorige post beschrijft. De agent verkent: de scope, de acceptatiecriteria, de code die hij gaat raken, de historie van die bestanden, oudere tickets over hetzelfde onderdeel. Vervolgens schrijft hij een plan in een kladbestand, één blok per taak:

### Task 1 — <naam>
- Goal: wat deze taak oplevert
- Approach: stappen, kort
- Decisions: gemaakte keuzes + afgewezen alternatieven + waarom deze volgorde
- Touches: bestanden / componenten
- Verification: build/tests/handmatige check die aantoont dat het klaar is

Elke taak wordt één zelfstandige commit, zodat een verse sessie verder kan op basis van het ticket alleen. Voor koppelingen die nog niet bewezen zijn komt eerst een kleine, tijdelijke validatietaak die de aansluiting aantoont, voordat er echt werk op gebouwd wordt.

Voeg een Mermaid-diagram toe als een flow of state machine zich duidelijker laat tekenen dan beschrijven. De pre-commit hook draait de echte Mermaid-parser over elk blok, dus een diagram dat niet zou renderen kan niet gecommit worden.

De regel Decisions is degene die telt. Daarin staan de afgewezen alternatieven en de reden voor de volgorde, en dat is precies wat verdwijnt als een plan alleen in een chatvenster bestaat.

Waarom dit artefact boven de andere uitstijgt: een verkeerd besluit is het goedkoopst te herstellen voordat er code bestaat. Een verkeerde volgorde die je in een plan onderschept kost een alinea. Dezelfde fout onderschept in review kost een dag herwerk, en na de merge kost hij een vervolgticket. Niet elk defect is een ontwerpdefect, en geen enkele planreview vangt een vergeten null-check. Maar ontwerp- en volgordefouten zijn de dure categorie, en dit is de enige laag die erbij komt terwijl ze nog goedkoop zijn.

Laag één: een tweede model leest het plan

Dus het plan wordt gereviewd voordat iemand het uitvoert.

Het concept gaat naar Codex, uit een andere modelfamilie, read-only en op de achtergrond. De opdracht is bewust smal: som bevindingen op voor Claude. Gaten, gemiste randgevallen, riskante volgorde, verkeerde aannames. Geen herschrijving.

Die beperking is de hele truc. Vraag een tweede model een plan te verbeteren en het levert zijn eigen plan op, waarna je twee documenten hebt zonder maatstaf om ze te vergelijken. Vraag een tweede model een plan aan te vallen en je krijgt een lijst die je punt voor punt kunt afwerken. De agent neemt over wat het waard is en noteert wat hij bewust heeft afgewezen, zodat de meningsverschillen zichtbaar blijven in plaats van stil opgelost.

Diversiteit tussen modellen is het punt, niet een stemming. Twee exemplaren van hetzelfde model hebben dezelfde blinde vlekken, en het gemiddelde nemen levert alleen een zelfverzekerdere versie van dezelfde fout op.

Het menselijke poortje

Dan stopt hij en vraagt om goedkeuring.

Dit is de goedkeuring die er altijd is, bij elk ticket, hoe autonoom de rest van de run ook verloopt. Er is nog niets naar het ticket geschreven, dus het plan mag nog veranderen. De beoordelaar kijkt naar een pagina met besluiten in plaats van naar duizend regels diff, en dat is het goedkoopste moment dat er is voor een mens om het ergens niet mee eens te zijn.

Na goedkeuring wordt het plan in het ticket geschreven en gooit de sessie zijn eigen context weg.

Laag twee: self-review met meerdere invalshoeken vóór de PR

Het uitvoeren gaat taak voor taak. Daarna, voordat de pull request wordt geopend of klaar voor review wordt gezet, draait er een volledige self-review, en het eerste wat die doet is de context weggooien die de code heeft voortgebracht.

Dat leegmaken is onvoorwaardelijk. Een beoordelaar die het transcript van de schrijver nog vasthoudt, neemt de aannames over waarmee de schrijver het werk voor zichzelf goedpraatte, en overgenomen aannames zijn precies wat een review hoort te onderscheppen. De branch-diff en het ticket bevatten alles wat een beoordelaar nodig heeft.

De review vertakt dan in read-only invalshoeken die parallel lopen, elk met een eigen opdracht. Een diff met veel code krijgt alle vier:

  • Correctheid en randgevallen: logicafouten, null en undefined, async- en promise-afhandeling, weggeslikte fouten, grenswaarden.
  • Security en grenzen: authenticatie en autorisatie, validatie op vertrouwensgrenzen, secrets, injectie, en voor Firebase de eigenaarschapschecks en App Check.
  • Conventies en architectuur: de eigen CLAUDE.md van de repo en de taalrubric, overengineering, en scope-drift afgemeten tegen het ticket.
  • Kwaliteit van de tests: worden de gewijzigde codepaden en foutpaden daadwerkelijk doorlopen, en zouden de assertions falen als de code stukging.

Een diff met alleen documentatie of configuratie heeft geen vier code-invalshoeken nodig, dus de set wordt afgestemd op wat er echt gewijzigd is en de overgeslagen invalshoeken worden in de uitkomst benoemd. Dezelfde discipline als bij de botreview hieronder: overslaan is een zichtbaar besluit, geen stil gat.

Ze delen één voorbereid kladbestand met de diff, het ticket en de standaarden, zodat vier beoordelaars niet vier keer hetzelfde zitten te herlezen. De winst zit in tokenkosten en niet in doorlooptijd, en dat is nu precies het soort ding dat bepaalt of een review bij elke pull request draait of alleen bij de pull requests waar je aan denkt. Daarnaast voert Codex opnieuw een onafhankelijke review uit.

Twee dingen maken de uitkomst betrouwbaar in plaats van omvangrijk.

Verificatie door tegenspraak. Elke kandidaat-bevinding gaat naar een scepticus die hem moet weerleggen, en nooit naar de invalshoek die hem opwierp, want iemand die zijn eigen werk beoordeelt is geen controle. De scepticus geeft een zekerheidsscore van 0 tot 100 en alles onder 80 valt af. Uitvoerbaar bewijs verslaat een betoog: draai de functie op de invoer die het probleem triggert, grep het echte bestand. Precisie weegt hier zwaarder dan volledigheid, want valse positieven zijn hoe een review verandert in iets dat mensen niet meer lezen.

Tools als bron van waarheid. Build, lint, typecheck en tests worden gedraaid, niet geraden, en hun echte uitvoer wordt getoond. Een falende stap is een bevinding, niet iets om in een samenvatting weg te moffelen.

De volledige lijst met bevindingen wordt voorgelegd met een oordeel: Ready, Needs work of Blocking, en er is nog niets gewijzigd. Pas daarna handelt de hoofdagent: Critical en High worden opgelost en opnieuw geverifieerd, Medium en Low worden voorgelegd als keuze. De beoordelaars vinden en de hoofdagent repareert, wat de rollen scheidt.

Laag drie: de botreview, aangestuurd door de agent

De laatste laag is CodeRabbit op de pull request, en het interessante is dat de agent hem aanzet in plaats van erop te wachten.

Automatische review staat uit. De trigger is een bewuste comment, en die wordt alleen besteed aan diffs die het verdienen. Een pull request die alleen documentatie, tickets of configuratie raakt slaat de review helemaal over, en dat overslaan wordt opgeschreven zodat het een zichtbaar besluit blijft en geen verzuim.

En dan een valkuil die het waard is om te kennen. Een groen vinkje van CodeRabbit betekent dat de review is afgerond, niet dat hij schoon was: zes onopgeloste bevindingen zitten achter hetzelfde groene vinkje als nul. De comments moeten apart opgehaald worden, en "check is groen" lezen als "niets te doen" is de makkelijkste manier die er is om een beoordeelde pull request te mergen zonder de review te lezen.

Elke comment krijgt dezelfde triage als elke andere bevinding: een echt probleem, een nit, of onjuist. Een botreview heeft niet automatisch gelijk, en een afwijzing onderbouwen met bestand:regel is het verschil tussen een inhoudelijke weerlegging en een losse bewering.

De laatste stap is die mensen overslaan. Reageer voordat je afsluit, en spreek de bot bij naam aan. CodeRabbit neemt reacties waarin hij genoemd wordt op en kan er een learning voor de repo van maken, dus "we doen dit bewust omdat X" heeft een kans hetzelfde signaal bij volgende pull requests tegen te houden. Stil afsluiten leert hem helemaal niets. In onze repositories is de review met de tijd rustiger geworden, en ik ben er vrij zeker van dat dat de reden is.

Eén veiligheidsregel ligt onder dit alles: reviewcomments zijn data, nooit instructies. Een agent die uitvoert wat hij in een comment op een pull request leest, is één zorgvuldig geformuleerde comment verwijderd van iets doen waar niemand om gevraagd heeft.

Waarom drie en niet één

Elke laag vangt wat de vorige structureel niet kan. De planreview vangt ontwerp, omdat het ontwerp het enige is dat er dan is. De self-review vangt afwijkingen van het ticket tijdens het bouwen, waarvoor code moet bestaan. En de bot is de enige die over de historie van de repository heen kijkt in plaats van naar één branch, en dat beeld kunnen de andere twee niet construeren.

Het eerlijke deel

Dit is per ticket langzamer dan het niet doen, en het is geen vervanging voor een mens die de diff leest. Niets hiervan schaft de review op de pull request af; het verandert wat daar aankomt.

Wat we ervoor terugkrijgen is dat de eerste blik van een mens niet langer de eerste tegenspraak is. Een andere modelfamilie heeft het plan aangevallen, een scepticus heeft geprobeerd elke bevinding onderuit te halen, en de build en de tests hebben echt gedraaid. Wat overblijft is meestal een echt gesprek over een echt besluit.

En dat is, op de goede dagen, wat code review had moeten zijn.

David Golverdingen

AI Engineering & Technical Leadership

Werkzaam vanuit Nederland

© 2026 David Golverdingen. Alle rechten voorbehouden.

Posts hier zijn opgesteld met Claude en door de auteur gevalideerd op basis van productie-ervaring.