##  [En agent, der bygger sine egne værktøjer](/da/node/299)

    *Indsendt af Lennart den tor, 8 okt 2026 - 11:32*

  [ ![En agent, der bygger sine egne værktøjer](/sites/default/files/styles/max_1300x1300/public/2026-10/composite_3.png.avif?itok=_Zlp5vka)](/sites/default/files/2026-10/composite_3.png)

*De fleste AI-agenter har en fast værktøjskasse, som et menneske har skrevet på forhånd. I går byggede jeg en, hvor agenten selv skriver værktøjerne, og hvor hvert værktøj bliver liggende til næste opgave. Alt, hvad den gør, kan revideres bagefter.*

Når man i dag bygger en AI-agent, giver man den et sæt værktøjer: slå op i kalenderen, søg i CRM'et, send en mail. Modellen vælger mellem dem, men den kan ikke lave nye. Mangler der et værktøj, må et menneske skrive det.

Det andet scenarie er endnu værre: Agenten skriver et Python-script i farten, kører det og smider det væk. Sådan arbejder mange kodeagenter og dataanalysefunktioner i chatbots. Næste gang den samme opgave kommer, skriver den et nyt script, der er lidt anderledes end sidst. Intet bliver genbrugt, intet bliver testet, og bagefter kan ingen sige, hvilken kode der gav tallet i rapporten. Man betaler for, at modellen opfinder det samme værktøj igen og igen, og hver gang er det et nyt sted, den kan tage fejl.

Mit eksperiment vender det om. Agenten, her DeepSeek, får en opgave og skriver selv et lille program, der løser den. Programmet bliver registreret, det kører med det samme, og det forsvinder ikke, når opgaven er løst. Det står klar til næste gang, til mig, til andre programmer og til agenten selv.

## Koden bor i loggen, ikke i en fil

Under agenten ligger [cross.stream](https://cablehead.github.io/xs/), forkortet xs. Det er en hændelseslog: en lang række af ting, der er sket, i den rækkefølge de skete. Intet bliver overskrevet. Der bliver kun skrevet nyt i bunden.

Det særlige ved xs er, at kode også er en hændelse. Skriver man Nushell-kode til et emne, der ender på `.create`, bliver koden registreret og kører. Der er ingen fil at gemme, ingen server at starte og intet at installere. Når maskinen genstarter, læser xs loggen igen og sætter alle gyldige programmer i gang.

Det betyder, at agenten kan udvide systemet, den selv kører i. Den skriver en hændelse, og så findes der et nyt værktøj.

## Værktøjer, der bygger på værktøjer

Ved siden af programmerne ligger der delte moduler: små biblioteker med funktioner, som programmerne kan importere. Når agenten skal skrive noget nyt, får den kildekoden til alle modulerne med i sin opgave, så den ved, hvad der allerede findes.

Modulerne kan inspiceres som alt andet. Siden viser hvert modul med dets kildekode og versioner, og et klik lægger koden ind i et redigeringsfelt. Et menneske kan altså selv skrive et modul eller rette i et, og den nye version bliver også en hændelse i loggen. Et program, der allerede kører, bliver på den modulversion, det blev registreret med, til det bliver opdateret. Et nyt modul kan derfor ikke stille og roligt ændre opførslen af noget, der kører i forvejen.

Det virker. Jeg bad om en aktør, der holder en løbende sum og kun lægger gyldige tal til. DeepSeek skrev den og importerede selv `program-lib`, et modul med funktionen `require-number`, frem for at skrive talkontrollen igen. Den genbrugte et værktøj, der lå der i forvejen.

Lageret er et andet eksempel. Det er en aktør med reservationer og forsendelse: Man fylder ti på, reserverer fire til én ordre, prøver at reservere syv til en anden og får nej, fordi der kun er seks tilbage. Jeg bad agenten forbedre det, og den skrev en ny version, der håndterer en forsendelse af en reservation, som ikke findes, frem for at gå ned. Den byggede videre på sit eget arbejde.

Pointen er, at værktøjskassen vokser. Hver opgave kan efterlade et værktøj, og den næste opgave kan bruge det. Og når først et værktøj er skrevet, er det kode og ikke en sprogmodel, der svarer. Det koster ingenting at køre, det giver det samme svar hver gang, og det kan testes.

I dag er det modulerne, agenten ser, når den skriver nyt. Næste skridt er at give den listen over sine egne færdige programmer, så den også kan kalde dem. Designet gør det til et lille skridt, for listen er bare en forespørgsel på loggen.

## Et audit trail, man ikke skal huske at føre

Det er her, designet for alvor tjener sig hjem. Når en agent selv skriver kode, er det første spørgsmål: Hvad har den egentlig lavet? Her er svaret altid i loggen, for alt er en hændelse:

- Min opgave er en hændelse: `agent.call`.
- Koden, modellen skrev, er en hændelse med en beskrivelse og et link til opgaven.
- At systemet accepterede eller afviste koden, er en hændelse.
- Hvert kald af programmet er en hændelse, og det samme er svaret eller fejlen.
- En ny version peger på den forrige og på den fejl, den skulle rette.

Efter et døgn ligger der 416 hændelser og ni programmer. Jeg kan se præcis, hvad jeg bad om, hvad modellen svarede, hvilken version der kører, og hvad hvert eneste kald gav. Siden på `127.0.0.1:3031/agent` gør det muligt at inspicere alt: kildekoden til hvert program, hele versionshistorikken, aktørens seneste tilstand og koden i hvert delt modul, programmerne importerer. Intet kører, uden at jeg kan læse det, og det gælder også de værktøjer, værktøjerne bygger på.

Det er ikke en log, nogen har skullet huske at føre. Den *er* systemet. Programmerne findes kun, fordi de står i loggen, så der kan ikke findes et program, der ikke er sporbart.

## Når koden fejler

Jeg bad om et program, der skulle huske en liste. DeepSeek skrev kode, der læste fra `$frame.stream`, et felt, der ikke findes. Det var en ren opfindelse. Den lignede noget, der burde findes, og det er præcis sådan, sprogmodeller tager fejl.

Programmet blev registreret, og mit første kald fejlede med «Cannot find column 'stream'». Fejlen blev en hændelse med den præcise linje og kolonne.

Så skete der noget, jeg ikke gjorde selv. En anden aktør, `auto-repair`, holder øje med alle fejl i loggen. Den sendte den fejlende kode og fejlbeskeden tilbage til modellen og bad om en rettelse. Den nye version blev skrevet som en ny hændelse med et link til den gamle og til fejlen. Der er et loft på to rettelser pr. fejl, så en model og en fejl ikke kan holde hinanden i gang hele natten.

Og her viste audit trailet sit værd. **Rettelsen fjernede fejlen, men også en del af hensigten.** Den nye version returnerer en liste med det ene element, jeg sender. Den husker ikke noget. Den virker, men den gør ikke det, jeg bad om. Det kunne jeg kun se, fordi begge versioner, opgaven og fejlen lå side om side. Et system, der retter sine egne fejl, optimerer efter, at fejlen forsvinder. Det er ikke det samme som, at opgaven bliver løst, og derfor skal et menneske kunne kigge efter.

## Potentialet for en SMV

**Tavs viden bliver til værktøjer.** En SMV kører på små regler, der sidder i hovedet på nogen: Lageret må ikke gå i minus. De hastende opgaver kommer først. En udbetaling over et vist beløb kræver to underskrifter. Her kan hver regel beskrives i en sætning og blive til et værktøj, der kører, kan genbruges og ikke går på pension.

**Agenten bliver billigere, jo mere den bruges.** Første gang en opgave løses, tænker modellen. Anden gang kører der kode. En agent, der bygger sine egne værktøjer, flytter arbejdet fra dyre og uforudsigelige modelkald til billig og forudsigelig kode.

**Sporbarhed er gratis.** Spørger en revisor eller en bestyrelse «hvorfor gjorde systemet det her den 7. oktober», er svaret ikke et skuldertræk. Man spiller loggen frem til den dag og ser det: opgaven, koden, versionen og kaldet.

**Data overlever koden.** Kaldene er det varige, mens en aktørs tilstand bliver regnet ud ved at spille kaldene igennem, ligesom en saldo er summen af posteringerne. En bedre version af lageret kan spille den samme historik igennem og komme frem til det nye svar.

## Det, der skal være på plads først

Det her kører på min egen maskine, og det er der en grund til.

**Der er ingen sandkasse.** Prompten beder modellen om kun at skrive rene beregninger uden netværk, filer og eksterne kommandoer. Men en instruks i en prompt er et ønske, ikke en mur. Koden kører med serverens rettigheder. Audit trailet gør det muligt at se, hvad der skete. Det forhindrer det ikke.

**Grønt lys er ikke det samme som rigtigt.** Listeeksemplet viser det. Nogen skal læse koden, i hvert fald før et værktøj får lov at røre noget, der betyder noget.

**Genafspilning stiller krav.** Fordi en aktørs historik spilles igennem ved hver opstart, må den ikke gøre noget i verden undervejs. Sender den en mail ved hvert kald, sender den dem alle igen efter en genstart.

Det er de spørgsmål, enhver virksomhed bør stille, før AI får lov at skrive noget, der kører: Hvem læser koden? Hvad har den adgang til? Og kan vi se bagefter, hvad der skete? De fleste AI-systemer svarer dårligst på det sidste. Her er det dét, hele designet er bygget op omkring.