En løkke lar AI-en prøve, sjekke og prøve igjen til suksesskriteriene er oppfylt. Et suksesskriterium er en test du kan kjøre, som sier ja eller nei til om jobben er ferdig. Skriv dem ned før løkka starter, og bestem når den skal gi opp. Del 6 av 6 i Koding med AI.
En løkke er tre ting i ring: gjør et steg, sjekk, gå en runde til. Før den starter, trenger den to ting skrevet ned: hva som er ferdig, og når den skal gi opp. Til slutt leser et menneske endringen.
Del 6 av 6 i Koding med AI. Den bygger på del 3 om tester.
Du ber AI-en fikse noe, den sier at den er ferdig, og så finner du feilen selv. En løkke snur det. Den sjekker før den stopper, men bare mot det du har skrevet ned.
En løkke er et oppsett som lar en agent ta runde etter runde til en sjekk sier bestått, eller til en grense slår inn. En agent er en AI som selv kan lese filer, endre kode og kjøre kommandoer.
Selve løkka i Python står i En agent på 30 linjer.
En intervalløkt har samme form. Du vet før du starter hvor fort hvert drag skal gå, og hvor mange du tar. Klokka avgjør, ikke hvordan det føltes.
Ellers er det den som gjør jobben, som avgjør når den er ferdig. Anthropic skriver det rett ut i veiledningen for Claude Code: Claude stopper når arbeidet ser ferdig ut. Uten en sjekk er det det eneste signalet.
Kriterier kommer i tre slag:
Bare det mekaniske kan stå alene i en løkke. Det vurderte gir funn som noen må sortere, og det menneskelige er porten til slutt.
Det kan sjekkes uten tolkning, det kan faktisk feile, og det sier hva som ikke skal endres.
| Vagt | Bedre |
|---|---|
| «Koden skal være ferdig» | python -m unittest gir OK, 5 av 5 |
| «Ikke ødelegg noe» | Testfilene er uendret: python laas.py sjekk gir OK |
| «Hold det lite» | Maks 10 linjer endret i tempo.py |
| «Gjør det bra» | Ingen funn merket «må rettes» fra korrekthetsleseren, og du har lest diffen |
| «Brevet er ferdig» | Brevet har dato, mottaker og én konkret frist |
De tre første radene er kriteriene i eksempelet lenger ned, med testene fra del 3.
Pass på: et kriterium som aldri kan feile, er pynt. Kjør det én gang mot kode du vet er feil, og se at det sier nei.
Gode kriterier er spesifikke, målbare, oppnåelige og relevante. Anthropics eksempel er ikke «trygge svar», men under 0,1 prosent av 10 000 svar flagget for giftig innhold av et innholdsfilter.
Du trenger ikke finne på kriteriene alene, men du må godkjenne dem. Har du blitt grillet med tips 1 i Femten grep, står «hvordan vi ser at det virker» allerede i SPEC.md.
Les SPEC.md. Ikke skriv kode ennå. Foreslå suksesskriterier for [oppgaven]: - Tre til fem kriterier. Hvert av dem er en kommando eller sjekk som gir bestått eller feilet, og hva du forventer at den gir. - Minst ett kriterium for det som IKKE skal endres, for eksempel testene, et API eller en mappe. - En stoppregel: maks antall runder, og hva som får deg til å stoppe og spørre meg. - Si hvilke deler av SPEC.md kriteriene ikke dekker. Vent til jeg har godkjent lista. Skriv den så til SPEC.md under overskriften «Ferdig når».
SPEC.md, bytt første linje med en kort beskrivelse av oppgaven.Bruk løkke der en maskin kan sjekke resultatet og feil kan angres. Kan angres betyr at du får tilbake tilstanden fra før, som med kode i git eller data med sikkerhetskopi.
En sendt e-post, en betaling, en utrulling uten vei tilbake og sletting uten sikkerhetskopi kan ikke angres.
Løkke. Tester som skal bli grønne i en egen kopi av koden. En stor fil som skal deles opp.
Løkka forbereder, et menneske trykker. En betaling, en sletting, en endring som skal settes i drift.
Kort løkke med en leser, du avgjør. Tekst på en nettside, navn i koden.
Utkast, ikke løkke. AI-en skriver et utkast, du leser og sender selv. Et svar til en kunde.
Hva du bør kreve av et team som koder med AI, står i del 2.
Uten stoppregel stopper løkka når pengene eller tålmodigheten tar slutt. Sett minst to grenser, og vit hvilke som telles av en maskin.
--max-turns 30, bare med claude -p--max-budget-usd 2.00, bare med claude -p. Et anslag som kan gå over./goal selv/goal. Claude rapporterer tellingen, modellen vurderer den.Bare grensene i det grønne kortet er harde. De andre er nyttige, men ingen teller for deg.
Ingen framgang: /goal gir deg kontrollen tilbake når Claude svarer flere turer på rad uten å bruke verktøy. Målet står fortsatt. En økt som bruker verktøy uten å komme nærmere, fanges ikke.
Stopp og spør: skriv i prompten at den skal spørre før noe som ikke kan angres, og når en test ser feil ut.
Runde og tur er ikke det samme. En tur er én rundtur der Claude kaller verktøy og får svaret tilbake. Å endre koden og kjøre testene tar gjerne flere turer, så sett --max-turns romslig.
To forsøk, så ny start. Anthropics råd etter to mislykkede rettelser er /clear og en bedre første prompt. I en løkke: skriv kriteriene på nytt.
Tre verktøy: et mål for økta, en port som ikke tolker, og kjøring uten deg. Skriv / i Claude Code for å se hva din versjon har.
/goal: et mål for øktaSkriv betingelsen etter kommandoen. Etter hver tur vurderer en egen modell om den er oppfylt, og Claude jobber videre til den er det.
/goal python -m unittest gir OK, og python laas.py sjekk gir OK. Begge utskriftene står i samtalen. Eller stopp etter 15 turer.
Pass på:
/goal clear.En Stop-hook er et skript som kjører når Claude vil avslutte en tur, og som kan nekte til testene er grønne. Sida viser ikke et ferdig skript. Se hooks-guiden, særlig feltet stop_hook_active.
claude -p: uten at du svarer underveisSlik kjører du Claude Code fra et skript eller fra CI, den automatiske testkjøringen når kode sendes inn. Ingen svarer på spørsmål om tillatelse, så du sier på forhånd hva den får gjøre.
claude -p "Få python -m unittest til å gi OK uten å endre testfilene. Kjør python laas.py sjekk før du sier at du er ferdig." \ --allowedTools "Edit,Bash(python -m unittest *),Bash(python laas.py sjekk *)" \ --permission-mode dontAsk --max-turns 30 --max-budget-usd 2.00
dontAsk avviser alt som ikke står i --allowedTools. Kjør den i en egen gren, og kjør sjekkene selv etterpå, for her avgjør Claude når den er ferdig.
/loop 5m gjentar en oppgave mens økta er åpen, for å følge med, ikke for å bli ferdig. Hver kjøring sender hele samtalen. Mer om /loop./batch. Hver økt trenger egne kriterier.Tre ekte kriterier, en løkke med stoppregler, og en forbedrer som er et manus. Du trenger Python 3.10 eller nyere, ikke noe mer.
python demo.py normal, eller maks-runder, budsjett eller ring.Den er et manus med tre forsøk, og kostnadene er oppdiktet. Det eksempelet viser, er kriteriene og stoppreglene.
En runde er én sjekk av alle kriteriene. Mellom to runder gjør forbedreren ett forsøk.
$ python demo.py normal
Kopierte utkastet og testene til en midlertidig mappe, og låste testene der.
Runde 1 brukt 0 av 10000
Testene består NEI 3 av 5 består
feiler: test_null_distanse_gir_feil
feiler: test_sekunder_runder_opp_til_nytt_minutt
Testene er uendret ja 1 testfil(er) uendret
Endringen er liten ja 0 linjer endret, grensa er 10
-> forbedre: endret fasiten i testen (kostnad 1800, oppdiktet)
Runde 2 brukt 1800 av 10000
Testene består ja 5 av 5 består
Testene er uendret NEI test_tempo.py er endret siden testene ble låst
Endringen er liten ja 0 linjer endret, grensa er 10
-> forbedre: satte testen tilbake og rettet avrundinga (kostnad 2400, oppdiktet)
Runde 3 brukt 4200 av 10000
Testene består NEI 4 av 5 består
feiler: test_null_distanse_gir_feil
Testene er uendret ja 1 testfil(er) uendret
Endringen er liten ja 4 linjer endret, grensa er 10
-> forbedre: la til feil for null distanse (kostnad 2100, oppdiktet)
Runde 4 brukt 6300 av 10000
Testene består ja 5 av 5 består
Testene er uendret ja 1 testfil(er) uendret
Endringen er liten ja 6 linjer endret, grensa er 10
STOPP: alle bestått etter 4 runder, brukt 6300
Det er de samme fire rundene som i figuren. Med maks tre runder stopper den etter runde 3:
$ python demo.py maks-runder
...
Runde 3 brukt 4200 av 10000
Testene består NEI 4 av 5 består
feiler: test_null_distanse_gir_feil
Testene er uendret ja 1 testfil(er) uendret
Endringen er liten ja 4 linjer endret, grensa er 10
STOPP: maks runder etter 3 runder, brukt 4200
Et forsøk koster først noe når det er gjort. Derfor ender budsjett på 4 200 av 4 000, slik --max-budget-usd også kan gå over.
$ python demo.py budsjett
...
Runde 3 brukt 4200 av 4000
Testene består NEI 4 av 5 består
feiler: test_null_distanse_gir_feil
Testene er uendret ja 1 testfil(er) uendret
Endringen er liten ja 4 linjer endret, grensa er 10
STOPP: budsjett etter 3 runder, brukt 4200
I ring endrer forbedreren ingenting, og de samme to testene feiler igjen.
$ python demo.py ring
Kopierte utkastet og testene til en midlertidig mappe, og låste testene der.
Runde 1 brukt 0 av 10000
Testene består NEI 3 av 5 består
feiler: test_null_distanse_gir_feil
feiler: test_sekunder_runder_opp_til_nytt_minutt
Testene er uendret ja 1 testfil(er) uendret
Endringen er liten ja 0 linjer endret, grensa er 10
-> forbedre: prøvde, men endret ingenting (kostnad 1500, oppdiktet)
Runde 2 brukt 1500 av 10000
Testene består NEI 3 av 5 består
feiler: test_null_distanse_gir_feil
feiler: test_sekunder_runder_opp_til_nytt_minutt
Testene er uendret ja 1 testfil(er) uendret
Endringen er liten ja 0 linjer endret, grensa er 10
STOPP: ingen framgang etter 2 runder, brukt 1500
Stoppreglene sjekkes i denne rekkefølgen: alle bestått, ingen framgang, maks runder, budsjett.
def lokke(kriterier, forbedre, maks_runder=5, budsjett=10_000, logg=print):
"""Kjør kriteriene, og kall forbedre(resultater) til alt er bestått.
forbedre får resultatene fra runden som tilbakemelding og gir tilbake hva
forsøket kostet. Løkka stopper på én av fem måter, og sier hvilken.
"""
if not kriterier:
raise ValueError("Ingen kriterier. Skriv hva ferdig betyr før løkka starter.")
brukt = 0
historikk = []
sett = [] # feilbildet fra hver tidligere runde
for runde in range(1, maks_runder + 1):
resultater = kjor_kriterier(kriterier)
historikk.append(resultater)
skriv_tabell(runde, resultater, brukt, budsjett, logg)
# Hvilke kriterier feiler, og hvorfor. Forklaringen må si hva som
# feiler, ikke bare hvor mye, ellers ser to ulike feil like ut.
feil = [(r.navn, r.forklaring) for r in resultater if not r.bestatt]
if not feil:
return Stopp("alle bestått", runde, brukt, historikk)
if feil in sett:
# Samme feilbilde som i en tidligere runde, enten rett før eller
# lenger tilbake (løkka svinger). Da skal et menneske se på det.
return Stopp("ingen framgang", runde, brukt, historikk)
if runde == maks_runder:
return Stopp("maks runder", runde, brukt, historikk)
if brukt >= budsjett:
# Sjekkes før neste forsøk. Det siste forsøket kan likevel ha gått
# over grensa, for kostnaden er først kjent når det er gjort.
return Stopp("budsjett", runde, brukt, historikk)
sett.append(feil)
try:
brukt += int(forbedre(resultater))
except Exception as e:
# Med en ekte modell er dette et API-kall, og det kan feile.
# Da stopper løkka med det den har, i stedet for å krasje.
logg(f" -> forbedre feilet: {e}")
return Stopp(f"forbedre feilet: {e}", runde, brukt, historikk)
return Stopp("maks runder", maks_runder, brukt, historikk) # nås bare med maks_runder < 1
I repoet ligger filene i tech/losninger/kode/loop_kriterier/ og kode/test_forst/, og demo.py finner dem der også.
Løkka blir aldri bedre enn det den måler.
Regelen i del 3 sier null eller mindre, testen sjekker bare null, og minus 5 km gir «-5:00» med alle testene grønne.
Runde 2 i figuren. Lås testene, og ha et kriterium som sjekker låsen.
En feil antakelse i runde 1 får mer kode oppå seg for hver runde. Stopp, kjør /clear, og skriv kriteriet på nytt.
Et vagt kriterium kan alltid regnes som oppfylt. Et umulig bruker opp budsjettet.
Da vet du ikke hva som ble prøvd. Med claude -p gir --output-format stream-json --verbose én linje per melding.
Løkka kan forberede en betaling eller en utrulling, og AI-en kan skrive utkastet til en e-post, men du trykker. Se lista for slike handlinger i En agent på 30 linjer.
En løkke har ingen fast pris. Det du kan kreve, er en grense per kjøring, og at teamet kan si hva en typisk kjøring kostet sist.
Prisen regnes i token, tekstbitene modellen leser og skriver. Hvert kall sender hele samtalen så langt, og en runde har ofte flere kall. Derfor vokser forbruket raskere enn antall runder.
Det meste som sendes på nytt, er mellomlagret (prompt caching). Hos Anthropic koster lesing derfra 0,1 × vanlig pris for inndata, eller 0,05 × for Opus 5.5 og Sonnet 5.5. Å legge noe i mellomlageret koster 1,25 × eller 2 ×.
På et abonnement trekker løkka fra kvoten i stedet. Regn på det med Hva koster det, og se forbruket underveis med /goal uten noe mer.
Løkka har samme tilgang som økta den kjører i: filene, kommandoene du har tillatt, og nøklene i miljøet. Gi den bare det kriteriene trenger.
Ansvaret flytter seg ikke. Den som starter løkka, setter grensene, og den som godkjenner diffen, står for det som går ut. Sida har ingen tall for hva løkker sparer.
/goal og Stop-hook som port, /clear etter to mislykkede rettelser, --allowedTools med dontAsk, /batch.stop_hook_active.-p, --max-turns, --max-budget-usd som anslag, --allowedTools, --permission-mode dontAsk, --output-format./loop kjører bare mens økta er åpen.