Wat dit is
De site die je nu leest, inclusief deze pagina, is gebouwd door een agent. Niet “geholpen door” een agent. Gebouwd. Mijn rol was beperkt tot het vastleggen van de regels van de loop, het bekijken van wat er na elke iteratie uitkwam, en af en toe terugkoppelen dat een specifieke regel niet klopte.
Het werkte. Niet vanzelf: iteraties gingen verkeerd, eentje werd weggegooid en een stuk of vijf hadden achteraf nog een correctie nodig. Maar twintig iteraties later staat er iets dat ik anders nooit in dat tempo had kunnen bouwen.
Wat de meeste mensen typen
De prompt die de meeste mensen aan Claude Code geven voor zo’n klus klinkt ongeveer zo:
Bouw een editoriale persoonlijke website voor een Nederlandse internet-operator. NRC-stijl, zwart op crème, ingehouden, met een hedcut-portret. Laat ‘m goed werken op mobiel.
Dat is een doel. De agent denkt erover na, schrijft een Astro-template, kiest een paar fonts, kiest een paar marges, en levert iets op dat er bijna goed uitziet. Daarna ben jij aan de beurt om in detail te zeggen wat er anders moet, totdat je tien iteraties later opgeeft of er nog tien prompts achteraan jaagt.
Wat ik typte
Bovenaan zit een markdown-bestand dat ik program.md heb genoemd. Het bestand beschrijft hoe de loop werkt:
- Wat de agent mag aanraken (
/src/,/public/, root configs). - Wat hij niet mag aanraken (
.design/BRIEF.md,.design/tokens.md, de recensenten: die vormen het contract waaraan de agent zelf niet mag tornen). - Hoe fitness gemeten wordt: som van alle scores over zes recensent-rollen, minus tien per overtreden regel.
- Wanneer een iteratie behouden of weggegooid wordt: score omhoog is
git commit. Score gelijk of lager isgit reset --hard. Geen discussie. Het getal beslist. - Wat het stopcriterium is: zes referentiesites zijn eerst gescoord, voordat deze site bestond, en
target = max(referentie) × 1.05.
Geen orkestrator, geen Python, geen aparte gereedschappen. De agent leest program.md aan het begin van elke iteratie en werkt eraan binnen die kaders.
De recensenten
Voor een taalmodel werkt één fitnessgetal. Voor een website volstaat dat niet, omdat een goede site niet één ding tegelijk doet. Hij regelt typografie, visuele craft, motion, narratief, hoe een collega-operator hem leest, en hoe een Nederlandse M&A-tegenpartij hem leest. Dat zijn verschillende dingen die je niet in één optimalisatie samen kunt persen.
In .design/reviewers/ staat per as een persona. Bijvoorbeeld een editor van een weekendkatern. Een craft-designer in de traditie van Frank Chimero. En een motion-engineer die Rauno Freiberg als ijkpunt neemt voor wat ‘subtiele beweging’ betekent. Elk scoort vijf of zes dimensies, elk geeft een ranking ten opzichte van zes referentiesites, elk levert één concreet verbeterpunt voor de volgende iteratie.
Zes subagents draaien tegelijk per iteratie. Som van scores wordt fitness. Alles ligt vast in .design/scores/iter_N.json zodat ik later precies kan zien wat er bewoog.
De gates
Twee dingen wegen mee voor het eindresultaat zonder dat ze zelf een score zijn: Nederlandse tekst die als een vertaling aanvoelt, en de visuele opmaak van de pagina. Daar zit naast de zes recensenten een aparte controle voor. Die deelt geen punten uit, alleen waarschuwingen. Een ernstige of matige waarschuwing kost tien strafpunten op het eindresultaat.
De visuele controle draait in een browser, op drie schermbreedtes: mobiel, tablet en desktop. Hij kijkt of beelden in verhouding staan tot de tekst, of dingen netjes uitgelijnd zijn, en of de witruimte klopt. Toen ik in één ronde vijf nieuwe illustraties op de site zette, vond hij binnen twintig minuten drie problemen: een beeld dat te plat was bijgesneden voor de plek, een opmaak die op tablet niet meer paste, en een illustratie die voelde als versiering in plaats van dat hij iets droeg. Een menselijke designer had die er ook uitgehaald, alleen niet zo snel, en niet zonder dat ik er zelf naar moest kijken.
Wat de loop niet vangt
Smaak die buiten de meting valt blijft buiten de meting. Een recensent kan niet voelen wat een specifieke lezer raakt op een bepaalde dag. De loop vergroot middelmaat niet, hij filtert het weg, maar bovengemiddeld werk komt nog steeds van iemand die durft te zeggen: “het getal klopt, maar de site klopt niet.”
Content waar je echt iemand voor nodig hebt is het tweede gat. De loop kan een essay niet uit het niets schrijven over een onderwerp dat alleen in iemands hoofd zit. Bij elke iteratie waar het getal vastliep zat de oplossing in een feit dat de loop niet kon weten: een buurmanverhaal uit 2007, een prompt die destijds werkte, een omzetcijfer dat alleen op één openbare pagina stond. De loop signaleert dan dat het vastloopt; vanaf dat punt moet een mens ingrijpen.
En kleine visuele dingen onder de meetdrempel ontsnappen. De controle op opmaak vangt een halve pixel scheef niet altijd. Mijn eigen oog wel, op mijn eigen scherm. Daar bleef een laatste handmatige check nodig: vaak een kort bericht terug naar de agent met “kijk hier nog eens, dit klopt niet.”
De connectie met Karpathy
Andrej Karpathy beschreef deze loop voor het trainen van modellen: één bestand om aan te raken, één fitnessgetal, sturing via een markdown-bestand. Die kaders werken ook voor websites, voor M&A-due-diligence, voor SEO-audits, en vermoedelijk voor elke andere taak waar je een agent een week aan zet.
Niet omdat het een universele aanpak is die overal werkt, maar omdat ze elk domein dwingen om er een afgestelde loop van te maken in plaats van een verzameling losse prompts. Bij elk nieuw domein moet je opnieuw beslissen wat je fitness is en welk werkterrein je afbakent. De markdown-tekst die de agent stuurt volgt daaruit.
Zonder die afstelling typ je tien keer een variant van “maak het mooier” en hoop je op geluk. Mét die afstelling staat er na twintig iteraties iets dat klopt, omdat je elk meetbaar getal hebt gemeten en de rest aan een mens hebt overgelaten.