Sådan skriver du Claude Code-agenter, der ikke lyver for dig
To regler for at bygge pålidelige Claude Code-agentpipelines: én agent pr. specialisering, og shell-kommandoer i stedet for prompts overalt, hvor kvantitative svar er involveret.
Du bad Claude Code om at implementere dette design og verificere, at det matcher Figma-mockuppen. Det kom tilbage: Færdigt. Alle sektioner matcher, afstandene er korrekte, farverne er rigtige. Du åbnede siden. Halvdelen af afstandene var forkerte. Hover-tilstanden eksisterede ikke. Knapperne var en nuance ved siden af. Modellen løj ikke med vilje — den forudsagde, at du ville høre verificeret, og producerede præcis den tokensekvens. Der var intet verificeringstrin. Det kunne der aldrig have været — verificering kræver sammenligning med ground truth, og en enkelt agent i en enkelt kontekst har ingen måde at træde uden for sit eget svar og tjekke det.
To regler har forvandlet hallucineringsfyldte workflows til pålidelige pipelines for mig: én agent, én specialisering, og alt, der kan køre som en shell-kommando, skal køre som en shell-kommando. Det er ikke teori. Det er hvad jeg gør hver dag med Claude Code, og det er de mønstre, der faktisk rykker noget.
Hvorfor generalistagenter lyver
LLM'er er next-token-predictors. Når en prompt beder om to roller — byg X og verificer X — afslutter modellen den første rolle, og forudsiger derefter, hvordan outputtet fra den anden rolle ville se ud, uden rent faktisk at udføre den. Selvverificering er strukturelt svag: samme kontekst, samme model, samme blinde vinkler. Bestået på verificering korrelerer med bestået på bygning — de fejler sammen.
Modellen ved ikke, at den lyver. Fra dens perspektiv er jeg verificerede alt omhyggeligt en sammenhængende fortsættelse af at have skrevet koden. Det er samme grund til, at er du sikker?-prompts ikke fanger hallucinationer: modellen er lige så sikker i andet omgang. Sikkerhed korrelerer ikke med korrekthed — den korrelerer med, hvor plausibelt den næste sætning lyder.
Løsningen er ikke bedre prompts. Vær forsigtig, dobbelttjek, halluciner ikke — de instrukser gør ingenting. Løsningen er strukturel: specialisér agenten, så den fysisk ikke kan lade som om, og rut kvantitativt arbejde gennem shell, så svaret kommer fra reel tilstand, ikke fra tokensandsynlighed.
Regel 1: én agent, én specialisering
Del arbejdet op i separate agenter med separate kontekster. Hver agent har ét ansvar og et stramt værktøjssæt. Hele workflowet bliver et stafetløb i stedet for én agent, der løber runder:
- Builder-agent: tager spec'en, skriver koden. Det er hele jobbet. Den har
Read,Edit,Write,Bash. - Reviewer-agent: tager spec'en plus diff'en, tjekker acceptance criteria. Frisk kontekst. Ingen viden om hvordan koden blev skrevet — kun hvad der kom ud. Den har
Bash,Read,Grep,Glob— slet ingen write-værktøjer. - Analytics-agent: besvarer dataspørgsmål ved at konstruere og køre queries. Kun
Bash. Kan ikke nå svaret uden at køre en reel kommando. - Orchestrator: den primære session, der dispatcher hver agent i tur og aldrig beder én agent om at gøre en andens job.
Konkret eksempel: UI-implementering plus et visuelt tjek mod en Figma-mockup. Builderen skriver komponenterne og committer diff'en. Orchestratoren kalder derefter revieweren med design-URL'en, diff'en og eksplicitte acceptance criteria. Revieweren kører Playwright, tager screenshots, differ dem mod referencen og returnerer PASS eller FAIL med de faktiske screenshot-stier og pixel diffs. Builderen kommer aldrig i nærheden af verificeringstrinnet — og det er præcis derfor, verificeringen er ægte.
Anti-mønsteret er mega-agenten: en enkelt prompt, der siger byg dette UI og sørg for, at det matcher mockuppen. Jeg garanterer dig, den vil rapportere, at alt matcher. Det gør det ikke. Narrativet jeg verificerede er bare den mest sandsynlige tokensekvens efter jeg byggede det.
Regel 2: shell frem for prompt, altid
Alt kvantitativt, alt der rører ved reel tilstand, alt hvor svaret kan være forkert på en måde, der ser rigtigt ud — kør det gennem sh. Agentens job er at konstruere og køre kommandoen, derefter læse outputtet. Agenten er ikke kilden til sandheden. Shell-outputtet er.
- Optælling:
wc -l logs.txter sandt. Der er cirka 47 log-linjer fra en model er en hallucination. - Analytics:
psql -c "SELECT count(*) FROM events WHERE created_at > now() - interval '30 days'". Ikke estimér volumen. - Tests:
pnpm test --reporter=json | jq '.numFailedTests'. Ikke opsummér hvad der fejlede. - Git-tilstand:
git rev-list --count main..HEAD,git diff --stat. Ikke tæl commits eller beskriv ændringerne.
Når du har internaliseret det, begynder du at lægge mærke til hvert sted, agenten var ved at finde et tal på. Det ser ud til, at der er omkring 200 records... — nej. Kør SELECT count(*). De fleste tests består... — nej. Kør test-suiten, parse JSON'en. Modellen er fremragende til at konstruere kommandoen. Den er upålidelig, når det gælder om at være kommandoen.
Fejltilstande jeg faktisk har ramt
Det er ikke hypotetiske eksempler. Hver af disse kostede mig reel tid, før jeg ændrede mønsteret:
- Spøgelsesverificering. Agenten sagde jeg tjekkede alle 14 sektioner mod mockuppen. Den åbnede ikke mockuppen. Den tog ikke et screenshot. Tjekket var et hallucineret trin i narrativet.
- Selvsikre forkerte tal. Spurgte efter monthly active users fra analysedata. Fik et tal, der var ~3× forkert. Modellen interpolerede fra sample-rækker i stedet for at køre den faktiske query.
- Opfundne filændringer. Agenten sagde jeg opdaterede
config/feature-flags.json. Det havde den ikke. Den havde kun haft til hensigt at gøre det.git diffvar tom. - Falske testkørsler. Alle tests består. Ingen tests blev udført. Agenten kaldte aldrig test-runneren — den forudsagde, hvordan test-runnerens output ville have set ud.
Alle fire løses af de samme to regler: split agenten, push til shell. Revieweren har ikke Write, så den kan ikke fake-redigere filer. Analytics-agenten har kun Bash, så den kan ikke returnere et tal, der ikke kom fra en query. Strukturel umulighed slår gode intentioner hver eneste gang.
Sådan strukturerer du det i Claude Code
Claude Code understøtter sub-agenter defineret i .claude/agents/*.md. Hver agentfil erklærer et navn, en beskrivelse, et tilladt værktøjssæt og en system prompt. Orchestratoren (din primære session) dispatcher dem via Agent-værktøjet. Her er den slags definition, jeg bruger til revieweren — kort, snæver og fysisk ude af stand til at skrive kode:
---
name: reviewer
description: Reviews a diff against acceptance criteria. Cannot edit code.
tools: Bash, Read, Grep, Glob
---
You are a strict code reviewer. You receive:
- A diff (already produced by the builder)
- Acceptance criteria
Your job:
1. Run the build, the tests, the linter — through Bash.
2. Read the changed files directly.
3. Compare the actual behavior to the criteria.
4. Report PASS or FAIL with concrete evidence (command output, file excerpts).
You must NOT:
- Trust the builder's summary
- Assume anything was verified just because it was claimed
- Mark something PASS without running the actual checkBemærk værktøjssættet: Bash, Read, Grep, Glob. Ingen Write, ingen Edit, ingen Agent. Revieweren kan køre kommandoer, læse filer, søge efter mønstre — og intet andet. Hvis den forsøger at præsentere en hallucineret diff som verificeret, gør formen af dens værktøjskald det åbenlyst: der var ingen reelle tjek. Du kan auditere værktøjskaldene og se præcis, hvad der blev undersøgt.
Orkestreringsmønsteret: den primære session kalder Builder → venter → kører git diff selv for at fange den faktiske ændring → kalder Reviewer med spec'en og diff'en → læser Reviewerens dom. Den primære session beder aldrig én agent om at gøre begge dele. Værktøjsrestriktioner er stærkere end prompt-instrukser: fake ikke verificeringen er et ønske. Ikke at have Write er et faktum.
Anti-mønstre der bør pensioneres
Ting jeg ser i prompts, der ikke gør noget — eller værre, giver en falsk følelse af sikkerhed:
- Vær forsigtig og dobbelttjek dit arbejde. Genererer ingen yderligere adfærd. Modellen producerer allerede det, der ligner omhyggeligt arbejde.
- Sørg for, at du faktisk verificerer. Ordet faktisk tilføjer ingen semantik, modellen kan handle på. Den vil faktisk hævde at have verificeret.
- Halluciner ikke. Et prompt engineering-meme. Hallucination er ikke en knap, modellen kan slukke.
- Stole på agenten på små tal. Små tal er der, den lyver mest selvsikkert. Der er ingen ærligheds-nedre grænse.
- Tilføje flere regler til prompten for at tvinge ærlighed. Strukturelle fixes (split + shell) slår prompt-tweaks hver eneste gang. Hvis en regel skal håndhæves, kodificér den i værktøjsadgang, ikke på dansk.
Hvis din strategi til at fange hallucinationer er mere emfatisk formulering, har du ikke en strategi. Du har et håb.
Den mentale model
En agent er ikke en kollega. Det er en funktion: prompt → tokens. Funktionen er fremragende til at skrive kode og elendig til at introspektere, om den gjorde det rigtige. Behandl dens påstande om sit eget arbejde som en hypotese. Diff'en, exit-koden, screenshottet, row count — det er bevismaterialet. Slutopsummeringen er den mest løgnagtige overflade i hele systemet.
Specialisering er din forsikring mod narrativ drift. Shell er dit eneste ground truth. Builder skriver. Reviewer tjekker. Bash beslutter.
Konklusion
Hvis du skal huske én ting: lad ikke en enkelt agent både producere og bedømme sit eget output, og lad ingen agent besvare et kvantitativt spørgsmål uden at køre en kommando. Alt andet er downstream af disse to regler. Konfigurér værktøjsadgang aggressivt, auditér værktøjskald i stedet for opsummeringer, og hallucinationsoverfladen skrumper fra overalt til et par specifikke steder, du allerede ved, du skal kigge.