Hva jeg lærte av å bygge en AI-kodingsagent (og hvorfor jeg ikke klarte å la være)
Ikke den produktive irritasjonen som driver deg til å fikse en feil før morgenkaffen er ferdig. Den andre typen. Den der du bruker et verktøy som nesten gjør det du vil — men ikke helt — og du tenker «dette burde jo bare fungere annerledes». Og så er klokka plutselig tre om natta, du har skrevet 400 linjer med TypeScript som ingen ba deg om, og katten ser på deg med blikket som sier vi har snakket om dette før.
Hvorfor i all verden
Jeg brukte AI-kodingsverktøy daglig. De var gode. De var også frustrerende på måter som var vanskelige å sette ord på over en lunsj. Verktøyet visste ikke at prosjektet mitt brukte Actions i stedet for Services. Det leste 500 linjer kode bare for å finne en funksjonssignatur. Det stoppet og spurte meg om lov til å gjøre ting jeg nettopp hadde bedt det om. Og hver gang det gikk i feil retning tre steg på rad, måtte jeg manuelt rulle tilbake filer og begynne samtalen på nytt, som en slags digital Sisyfos.
Ingen av disse tingene var uløselige. De var bare uløste.
Så jeg begynte å bygge. Ikke fordi verden trengte enda en kodingsagent — det gjør den helt åpenbart ikke — men fordi hjernen min ikke klarte å slutte å tenke på hvordan det burde fungere. Og jeg har lært meg, etter altfor mange år, at når hjernen min setter seg fast på sånt, er det bare to utveier: bygge det, eller late som det ikke skjer og bli passivt sur i seks måneder.
Jeg valgte å bygge.
Hva jeg faktisk lærte
1. Det som betyr noe er pinlig kjedelig
De flashy funksjonene — LSP-integrasjon, DAP-debugging, in-process grep skrevet i Rust — ser fantastiske ut i en README. De får folk til å klikke ⭐ på GitHub. De er også, viser det seg, nesten helt irrelevante for hvordan dagen din føles.
Det som faktisk endrer produktiviteten er: leser agenten færre token enn nødvendig? Fanger den sine egne feil umiddelbart? Kan jeg si «fiks dette» og gå og hente kaffe mens den jobber?
Jeg brukte en hel dag på å bygge et system der hvert verktøykall kjøres parallelt i Rust for å spare 50 millisekunder. Stolt som en hane. Så oppdaget jeg at agenten allerede parallelliserte verktøykall i TypeScript. Besparelsen var der hele tiden. Jeg bare visste det ikke. Det er det jeg liker å kalle aktiv ydmykhet gjennom kildelesning.
Samme dag la jeg til fire linjer kode som flyttet pinnede filer foran datoen i en meldingsblokk. Det sparte brukerne penger på hver eneste API-forespørsel. Fire linjer. Ingen Rust. Ingen arkitekturendring. Bare en gutt og hans innsikt om hvordan prompt caching faktisk fungerer.
Kjedelig slår kult. Hver eneste gang.
2. Utvidelser er alt
Den viktigste arkitekturbeslutningen jeg tok, var å holde kjernen liten og dytte alt annet ut i utvidelser. Ikke fordi det er elegant (det er det), men fordi det tvang meg til å spørre meg selv det vanskeligste spørsmålet i programvareutvikling: «Er dette noe alle trenger, eller bare noe jeg trenger?»
LSP for TypeScript? Utvidelse. SEO-verktøy? Utvidelse. Laravel-forståelse? Utvidelse. Side-samtaler? Utvidelse.
Resultatet er at Elyra uten utvidelser er sju verktøy og en editor. Med utvidelser er den hva enn du trenger den til å være. En Laravel-utvikler installerer @elyracode/laravel og @elyracode/stack-tall. En frontend-utvikler installerer ingen av dem. Ingen betaler for noe de ikke bruker — og hver utvikler får sitt eget skreddersydde lille univers.
Det tok meg tre versjoner å skjønne dette. De første versjonene hadde alt i kjernen. Det var et rot. Et imponerende, velfungerende, omfattende rot — men et rot.
3. Brukeren er flaskehalsen (sorry, men det er sant)
Den mest overraskende oppdagelsen i hele dette prosjektet: agenten er sjelden det svakeste leddet. Jeg er det.
Agenten venter på at jeg skal skrive «fortsett». Agenten venter på at jeg skal godkjenne en endring. Agenten venter på at jeg skal lese 30 linjer output og bestemme meg. Den sitter bare der, tålmodig som en golden retriever, mens jeg stirrer på skjermen og tenker på om jeg burde ta middag først.
/goal npm run check var det mest produktive jeg bygde i hele prosjektet. Ikke fordi det er teknisk imponerende — det er bokstavelig talt en while-løkke med en shell-kommando. Men det fjerner meg fra sløyfen. Agenten jobber, sjekker, fikser, sjekker igjen, fikser igjen. Jeg drikker kaffe. Stillheten brytes bare av at agenten av og til skriver «ferdig». Alle er fornøyde. Spesielt katten.
4. Token-økonomi er den egentlige arkitekturen
Hver designbeslutning handler til syvende og sist om token. Les hele filen? Dyrt. Les en oversikt først og deretter bare de linjene du trenger? Billig. La agenten planlegge neste steg på egen hånd? Dyrt og tregt. La kode bestemme neste steg? Gratis og raskt.
Workflow-utvidelsen vår gjør ingenting smart. Den leser en JSON-fil og kjører steg i rekkefølge. Men den eliminerer hundrevis av token per oppgave som ellers ville gått til å be modellen planlegge noe vi allerede visste svaret på.
Bruk kode til det kode er god til. Bruk modeller til det modeller er gode til.
Den setningen høres banal ut helt til du ser månedsregningen fra Anthropic. Da blir den plutselig sterkt poetisk.
5. Du trenger ikke det du tror du trenger
I starten laget jeg en lang liste over alt de andre verktøyene hadde som jeg manglet. Innebygd debugger. Hash-forankrede redigeringer. In-process grep i Rust. Nettleserautomatisering. 27 ulike DAP-operasjoner. Jeg så på lista som en arkeolog som har gravd opp en fryktelig konkurrent.
Så spurte jeg meg selv: «Når brukte jeg sist en debugger gjennom en kodingsagent?» Svaret var: aldri. «Når hadde jeg sist nytte av at grep kjørte 45 ms raskere?» Aldri — modellkallet tar tre sekunder uansett. «Når sist trengte jeg en agent som styrte en nettleser?» Også aldri, men jeg lot som om det var et fremtidsbehov i to dager før jeg innrømte det.
De tre tingene som faktisk utgjorde en forskjell var: smart fil-lesing (oversikter i stedet for full dump), diagnostikk etter hver redigering (kjør tsc umiddelbart) og /goal (la agenten jobbe uten meg).
Alt annet er CV-drevet utvikling. Som er en helt ærefull aktivitet, men la oss kalle den ved sitt rette navn.
6. Bare slipp det
På én dag sendte vi ut ti versjoner. Ti. Ikke fordi koden var perfekt, men fordi den var nyttig. Versjon 0.7.14 var en bugfiks fordi 0.7.13 hadde en variabel som het getCwd() der den skulle hett cwd. En bokstavelig énlinjer som ydmyket meg på direkten.
Jeg kunne testet mer. Jeg kunne skrevet integrasjonstester. Jeg kunne ventet til alt var pent og polert. I stedet slapp jeg det ut, fant feilen i produksjon 20 minutter senere, og slapp ut fiksen.
Perfekt kode som ingen bruker er verre enn imperfekt kode som løser et problem.
(Ikke fortell sjefen min at jeg sa det. Eller — jo, gjør det. Hun vet uansett.)
7. Skriv for fremtidens deg
Hver utvidelse jeg bygde, bygde jeg egentlig to ganger. Første gang som «dette fungerer». Andre gang som «dette fungerer, og jeg skjønner hvorfor når jeg leser det igjen om seks måneder».
CHANGELOG-filer. README-er. Skill-dokumentasjon. Bloggposter som denne. Ikke for brukerne — for meg. Fordi fremtidens meg garantert kommer til å åpne en fil og lure høyt: «Hvorfor i all verden la jeg til fire cache breakpoints i Anthropic-leverandøren?» Og svaret skal ligge der, i en commit-melding og en bloggpost, klart til å minne meg på at jeg en gang var smart.
Eller i det minste at jeg trodde jeg var det.
Hvorfor egentlig
Folk spør meg av og til hvorfor jeg bygger dette når det allerede finnes Cursor, Claude Code, Copilot og femten andre alternativer som har VC-finansiering og mye penere logoer.
Svaret er det samme som har drevet hver eneste utvikler siden tidenes morgen: «Jeg klarer sikkert å lage en bedre versjon på en helg.» Vi tar feil hver eneste gang. Men det er nettopp der vi lærer noe. Du kan lese hundre artikler om prompt caching, eller du kan implementere det og oppdage at datoen i meldingsblokken stille og rolig invaliderer cachen for alle pinnede filer hver eneste morgen klokka midnatt. Den ene innsikten er verdt mer enn alle artiklene til sammen.
Og dessuten — irritasjonen forsvant aldri helt. Den ble bare mer spesifikk. Nå er jeg irritert over helt andre ting. Bedre ting. Ting jeg vet hvordan jeg fikser.
Det er kanskje den egentlige grunnen til å bygge noe selv: ikke for å lage det perfekte verktøyet, men for å oppgradere problemene dine.
Mine problemer er nå av topp kvalitet. Skarpt avgrensede. Estetisk tilfredsstillende. Akkurat passe vanskelige til at jeg kan løse dem mellom to kopper kaffe.
Det er, når jeg tenker på det, ganske luksuriøst.
Elyra kommer som åpen kildekode iløpet av denne sommeren. Imens kan installere den fra elyracode.com