Door · ·

Agentic coding vergroot de kloof voordat hij krimpt

Agentic coding vergroot de kloof voordat hij krimpt

Ik was sceptisch tijdens GPT-3.5 en GPT-4. Chat in een zijbalk was autocomplete met extra stappen — handig voor een alinea hier of een snelle lookup, niet handig voor het echte werk van software bouwen en draaien. Ik bleef wachten op het ding waarvan iedereen behalve ik volhield dat het al waar was, en het kwam niet. Wat er ongeveer een jaar later wel kwam was een ander primitive: agentic coding loops, waarbij het model een kleine set tools aanstuurt — lees een file, bewerk een file, draai een test, lees de error — in plaats van alleen tekst produceren. Dat is de versie waar ik op ben omgedraaid, en het is de versie waar de rest van deze post over gaat.

Agentic coding is een voordeel dat zich opstapelt voor developers die de vorm van het werk al kennen, en een information overload voor degenen die dat nog niet doen — en de kloof die dat creëert gaat groter worden voordat hij krimpt. Ik denk niet dat mijn eigen werk net zo efficiënt zou zijn als ik nu pas met coderen begon. De tool is een force multiplier op een bestaand mental model; het mental model is wat je vertelt wanneer de agent vol vertrouwen verkeerd zit, en het mental model is het dure ingrediënt, niet het model.

De algehele vorm

Bijna alles wat op dit moment op deze blog staat is gebouwd met een agent die naast me zat. Het WorkWear4All Magento 2 cluster is het hoofdbaan-stuk — een multi-store backend oud genoeg om een long tail aan operationele randen te hebben gekregen, waar agentic coding tools de manier zijn waarop ik door een codebase heen beweeg waarvan noch ik noch een van de juniors het meeste hebben geschreven. Hourly is een menubalk-macOS time tracker in SwiftUI, en SwiftUI is een stack waar ik voor dat project fris in stapte. mijndiamondpainting.nl was een Nederlandse webshop die ik heb gelanceerd en heb stopgezet, en de hele frontend van die shop — de Cropper.js upload flow, admin dashboards, de state-machine order funnel — is werk dat ik in dat tempo nooit zelf had geproduceerd. De AI-agent experimenten die ik aan het herwerken ben zitten daarnaast; de niche-hunt pipeline waar ik apart over heb geschreven is er nog eentje. De site die je nu leest is zelf een Express/EJS/Tailwind app op dezelfde manier gebouwd.

In geen van die gevallen produceert de agent in zijn eentje een voltooid systeem. Hij produceert het scaffold, de eerste eerlijke draft, de onderdelen waar ik anders de meeste tijd in had gestoken en het minst van had genoten. Wat hij niet produceert is het oordeel over of het scaffold überhaupt de juiste vorm heeft, of dat de eerste draft op een stille bug zit. Dat oordeel is van mij, en dat is wat beter moet worden naarmate de agent sneller wordt.

Waarom de scepticus omdraaide

Het GPT-3.5- en GPT-4-chattijdperk faalde voor mij op een specifieke as: het kon plausibel ogende code produceren, maar het kon niet het werk doen van die code daadwerkelijk draaien, de error lezen en het opnieuw proberen. Elke iteratie vroeg om mij als de handen — paste in de editor, run, paste de error terug in de chat, lees, paste. Het model was snel maar de loop was traag, en de loop is het ding dat ertoe doet bij echt werk. Wat er aan agentic loops anders aanvoelde was dat de tool layer naar binnen in de loop verschoof. Het model bewerkt een file, draait de test, leest de stack trace, bewerkt opnieuw. Ik ben nog steeds de reviewer, maar ik ben niet ook de koerier.

De caveat waar ik steeds op terugkom is dat de huidige agent-abonnementen vrijwel zeker gesubsidieerd zijn tegen de echte inference cost van de frontier-modellen die erachter zitten. Die rekening ligt érgens — de vraag is of de prijs die de individuele developer ziet de prijs is waar de economics van het ding uiteindelijk op uitkomt. Ik denk van niet. De enige versie van dit verhaal die structureel gezond blijft, is er één waarin kleine, lokaal draaiende modellen genoeg van de capability gap dichten om de hot path goedkoop te draaien, en de recente vooruitgang aan de kleine-model kant is genoeg geweest dat ik die bet serieus neem. Ik heb de vorm van die bet al op een ander project opgeschreven. De korte versie is: behandel het model als één aanroeper in een systeem, bouw er goede tools omheen die hij kan gebruiken, en het verschil tussen een frontier-scale model en een kleiner model krimpt sneller dan je zou verwachten.

Waar de agent zijn brood verdient

Frontend design is de eerste plek. Ik ben er niet goed in, ik ben nooit tevreden met het resultaat, en de tijd die ik er vroeger in stak om iets presentabel te krijgen was enorm. Op mijndiamondpainting.nl is de volledige publieke shop — de order funnel over zes URL’s, de foto-upload met Cropper.js, de admin met Chart.js dashboards, een Tailwind-laag die ik niet hand-tuned hoefde te maken, abandoned-cart e-mail templates — werk dat ik op eigen kracht of had overgeslagen of op een zichtbaar lagere kwaliteitslat had geleverd. Niet omdat een van die onderdelen op zichzelf moeilijk is, maar omdat ik bij iteratie vier op zou hebben gegeven en iets lelijks zou hebben geshipped. Met een agent en een duidelijke richting van wat ik probeerde te bereiken, plus een paar voorbeelden om de esthetiek te ankeren, heeft de frontend design me echt honderden uren bespaard. Dat getal is een schatting, geen meting, maar het is de juiste orde van grootte voor een jaar bouwen op de manier waarop ik aan het bouwen ben.

Een nieuw project scaffolden is de tweede. Ik heb nooit eigen boilerplate templates gemaakt, en ik kies bewust om de zoveel tijd een ander framework omdat de constraint interessant is en ik niet in één stack wil verkalken. Die combinatie betekende vroeger een lange, saaie eerste week van elk project waarin er niets gebeurde behalve copy-pasten van het vorige ding. Nu komt het scaffold in een middag binnen, correct genoeg om er meningen over te kunnen vormen. Die meningen zijn juist het deel waar ik mijn tijd aan wilde besteden.

Nieuwe dingen leren is de derde, en Hourly is het geval waar dit het meeste uitmaakt. SwiftUI, AppKit menubalk-glue, de Mac App Store build pipeline, code signing — de hele klif die voor iedereen ligt die nieuw is in Apple-platform development. Ik heb genoeg software in genoeg talen geshipped dat de concepten zich laten vertalen, maar de specifieke spreuken niet, en het Apple-ecosysteem is het soort plek waar de specifieke spreuk het ding is dat je anderhalve dag blokkeert. Direct werkende code kunnen genereren — vaak in één keer goed, soms na een ronde correctie — is wat het lanceren van Hourly daadwerkelijk heeft laten gebeuren op een tijdlijn die ik bij een side project zou overwegen. Zonder dat had ik vermoedelijk nog steeds vastgezeten in een of ander signing-configuration dialoogvenster.

Bij elk daarvan staat er een kostenpost naast de besparing. Gegenereerde frontend is zelden rigoureus op het vlak van accessibility of performance tenzij ik terugga en hem audit, en ik moet eraan denken om terug te gaan. Scaffolden in een framework dat ik weinig heb gebruikt is snel, maar het kan me stilletjes vastleggen op keuzes waarvan ik niet doorhad dat het keuzes waren — de meest recente die ik heb opgemerkt was een packaging-conventie die ik anders zou hebben opgelost als ik hem eerder had gezien, en die ik überhaupt niet had opgemerkt als de agent er niet voor de tweede keer tegenaan was gelopen en het naar boven had gebracht. Learning-while-shipping betekent dat ik code aan het opbouwen ben die ik minder goed begrijp dan code die ik zelf heb geschreven, wat prima is tot het dat niet meer is.

Waarom achtergrond nu juist meer uitmaakt, niet minder

De ongelijkheidsclaim is degene die ik daadwerkelijk wil verdedigen. De agent is een force multiplier, en force multipliers vermenigvuldigen waar ze ook maar op gericht worden. Als je weet hoe “goed” eruitziet in de stack — de conventies, de idiomen van het framework, de vorm van een gezonde codebase, het soort error dat meestal betekent wat hij zegt te betekenen en het soort dat meestal iets anders betekent — versnelt de agent je omdat hij genereert, en jij opvangt en corrigeert. De feedback loop is snel omdat jij snel bent.

Als je nog niet weet hoe “goed” eruitziet — omdat je net begint, of omdat de stack echt nieuw voor je is en je de smaak ervoor nog niet hebt opgebouwd — is dezelfde tool een information overload. Hij produceert vrolijk twintig regels code die naar vier conventies verwijzen die je niet herkent, drie utilities aanroepen waar je nog nooit van hebt gehoord, en op een architectuurbeslissing zitten waar jij nog niet klaar voor bent om mee in discussie te gaan. Je kunt de hallucinaties niet opvangen omdat je ze nog niet kunt ruiken, en je kunt niet in discussie gaan met de structurele keuzes omdat je niet de ervaring hebt die je zou vertellen om in discussie te gaan. Wat je wel kunt doen is het ding shippen, en dat is het probleem. Vol vertrouwen verkeerde code, geshipped door iemand die nog niet doorheeft dat hij vol vertrouwen verkeerd is, is de failure mode, en het is de failure mode die de tool makkelijker maakt, niet moeilijker.

Ik schrijf dit niet om afwijzend te zijn over mensen die net beginnen. Ik schrijf het omdat ik me herinner hoe het was om niet te weten hoe “goed” eruitziet, en ik weet hoe het zou hebben gevoeld om een tool aangereikt te krijgen die plausibel ogende code sneller produceerde dan ik er een mening over kon vormen. De eerlijke lezing is dat dit nu juist moeilijker is om op te leren, niet makkelijker, en de kloof tussen mensen die het op de langzame manier hebben geleerd en mensen die het op de snelle manier gaan proberen te leren gaat een tijd duren voordat hij dichtgaat — als hij überhaupt dichtgaat. De force multiplier op achtergrond werkt sterker bovenin de curve dan onderin.

De eerlijke caveats

Ik heb wat mentale vermoeidheid ervaren die ik niet had verwacht. De agent gaat snel genoeg dat hij me dwingt om beslissingen over de volgende stap sneller te nemen dan ik gewend ben, en het cumulatieve effect over een dag dichte werk heen is reëel. Het is een ander soort moe dan code met de hand schrijven — minder typen, meer oordeel per minuut, en oordeel is de dure resource. Het is vooral erg aan het begin van een project met veel onbekenden, of op een bestaande codebase met een hoop dependencies die in de vorm ervan zijn ingebakken.

Ik heb de agent prima werkende code zien breken in precies het soort plek waar de context rond WorkWear4All voor waarschuwde. Magento 2 is geen codebase waar een module netjes in isolatie bewerkt kan worden; de issues waar je tegenaan loopt zijn vaak het soort dat lastig te onderzoeken is zonder in aangrenzende componenten van de stack te duiken om ze uit te sluiten. Een agent die vol vertrouwen een module bewerkt die hij half heeft begrepen, zonder de indexers te draaien of te kijken wat de cache layer doet, is heel goed in het introduceren van een stille downstream break die pas opduikt wanneer een admin-user twee dagen later opmerkt dat een productprijs niet klopt. Dat is mij overkomen. De diagnose was een nachtmerrie want de voor de hand liggende plek om te kijken was niet de plek waar het probleem vandaan was gekomen, en op het moment dat het symptoom aan de oppervlakte kwam was ik mijn aandacht voor de oorspronkelijke wijziging al lang kwijt.

Hallucinaties zijn nog steeds reëel. Ik denk dat dit deels een skill issue is, in de zin dat als je de agent een vage taak met slechte context geeft, je vage output met slechte accuracy krijgt, en hetzelfde zou gelden voor een junior developer aan wie hetzelfde ticket wordt overhandigd. De fix daarop is prompting en context, en dat is het deel van het werk waar ik nog actief beter in word. Het deel dat geen skill issue is, is de failure mode waarbij de agent vol vertrouwen verkeerd zit over iets specifieks — de vorm van een library API, het gedrag van een framework in een corner case, een syntax-detail — omdat het ding waar hij vol vertrouwen in zit is wat hij heel vaak heeft gezien tijdens training, niet wat de library daadwerkelijk doet in de versie waar ik op zit. Dat zijn de gevallen die je moet opvangen met je eigen kennis van de stack, wat het argument terugbrengt naar de hoofdthese.

De failure mode waar ik het minst trots op ben is blind vertrouwen aan het einde van een vermoeide dag. Wanneer ik al een hoop features heb geproduceerd, ze heb verfijnd, en gewoon het laatste ding wil afronden voordat ik stop, ben ik geneigd om eerder te accepteren wat de agent heeft geproduceerd zonder het zorgvuldig genoeg te lezen. Dat is het tegenovergestelde van wat ik zou moeten doen — dat is juist het moment waarop ik het voorzichtigst zou moeten zijn — maar het is wat er in de praktijk gebeurt. Ik zit te denken aan een workflow waarbij de agent standaard verificatie inbouwt in de code die hij produceert, in plaats van als iets dat ik moet onthouden om te vragen. Hij doet dat de meeste tijd al voor de voor de hand liggende surfaces, maar in een complexe applicatie zijn er een hoop dingen die een drift in een ander deel van de applicatie kunnen triggeren waar het model niet altijd voor test. Die workflow bestaat nog niet. Het is een echte kloof.

Waar de bet naartoe gaat

De richting waar ik denk dat dit op gaat, en de richting waar mijn eigen werk al naartoe draait, is kleine lokale modellen die op de hot path draaien met goede tools eromheen — de operator die de agent gebruikt als één aanroeper tussen vele, in plaats van als een autonome redeneerder die de hele taak probeert te dragen. Dat herformuleert het probleem van “hoe kies ik een slimmer model” naar “wat moet het model zien, vanwaar, en in welke vorm” — wat een software-engineering probleem is, en een veel hanteerbaarder probleem dan het scaling probleem. Ik heb over die herformulering geschreven in de context van een AI-project dat ik op precies die bet heb gebouwd; dezelfde bet is van toepassing op de eigen workflow van de operator, niet alleen op agents die hij voor andere mensen bouwt.

De concrete volgende stap aan mijn kant is de verificatieworkflow. Iets dat licht genoeg is om automatisch te draaien op elke betekenisvolle wijziging die de agent voorstelt, mechanisch genoeg dat ik het aan het einde van een lange dag vertrouw, zelfs op het moment dat ik mezelf niet zou vertrouwen om de diff zorgvuldig te lezen. Dat is het ding dat ik tussen mij en de “om 23:00 alles accepteren”-failure-mode wil zetten.

Het deel dat zich generaliseert

Het principe waar ik hier steeds op terugkom, over de agents heen die ik bouw en de agents die ik gebruik om dingen te bouwen, is dat de tools de design surface zijn, niet het model. Zodra het model vastligt — je hebt je provider gekozen, je hebt de grootte gekozen, je gaat hem niet in een weekend fine-tunen — is alles wat er nog te ontwerpen valt de set affordances die het model ziet wanneer het gaat zitten om de taak te doen. Hetzelfde geldt wanneer de “agent” degene is die in jouw eigen codebase bewerkt. De ontwerpvraag is welke context je hem geeft, tot welke verificatie hij toegang heeft, wat hij op eigen autoriteit mag aanraken, en wat hij aan jou moet teruggeven. Het model is de constante in die vergelijking. Al het andere is het werk.

De kloof die ik eerder beschreef — tussen mensen die de vorm van het werk al kennen en mensen die dat nog niet doen — is oncomfortabel om eerlijk over te schrijven, omdat geen van beide kanten ervan vleiend is om hardop te zeggen. Maar het werk dat ik dit jaar daadwerkelijk heb gedaan is het bewijs ervoor, en het bewijs is sterk genoeg dat ik er liever eerlijk over schrijf dan te doen alsof de tool iedereen even hard optilt. Dat doet hij niet. Hij tilt de mensen op die al dicht bij het plafond zaten, en hij laat de mensen die nog aan hun eigen ladder timmerden achter met een tool die sneller beweegt dan de ladder zelf.

Lees ook