Avslutte ved stop_reason
La end_turn avslutte løkken, ikke strengsammenligning.
Avslutte ved stop_reason er en gratis leksjon i Claude Architect på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Claude Architect, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Claude Architect inneholder totalt 4 leksjoner.
Løkken trenger en utgang
En agentisk løkke er enkel: De sender en forespørsel, Claude svarer, og De avgjør om den skal fortsette. Det vanskelige spørsmålet er når den skal stoppe.
Hvert API-svar inneholder et stop_reason-felt. Dette er modellens eget signal om hvorfor den sluttet å generere. Løkken Deres bør lytte til dette signalet — ikke gjette ved å lese ordene i svaret.
Denne leksjonen lærer bort én regel som skiller robuste agenter fra skjøre: la end_turn avslutte løkken, ikke strengsammenligning.
De fire stoppårsakene
Claude returnerer én av fire stop_reason-verdier i hver omgang:
end_turn— modellen fullførte svaret sitt på naturlig vis. Oppgaveomgangen er fullført.tool_use— modellen ønsker å kalle et verktøy. Kjør det, legg til resultatet og fortsett.max_tokens— utskriften ble avkortet avmax_tokens-grensen Deres.stop_sequence— en egendefinert stoppsekvens De konfigurerte, ble truffet.
Disse fire verdiene utgjør en komplett og pålitelig kontrakt. Kontrollflyten bør forgrene seg direkte basert på dem.
resp = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
tools=tools,
messages=messages,
)
print(resp.stop_reason) # end_turn | tool_use | max_tokens | stop_sequenceAntimønsteret: Tolking av tekst
En fristende snarvei er å lese modellens tekst og se etter et nøkkelord som «ferdig» eller «fullført» for å avgjøre om løkken er over.
Dette er et klassisk antimønster. Tekst er probabilistisk. Modellen kan si «Jeg er ferdig med å tenke, nå vil jeg kalle et verktøy» — og tekstsøket Deres stopper for tidlig. Eller den kan uttrykke fullføringen på en annen måte, slik at løkken kjører for alltid.
Tolk aldri tekst for å finne signaler om fullføring. Det strukturerte stop_reason finnes nettopp for at De ikke skal måtte gjøre det.
# ANTI-PATTERN: do NOT do this
text = resp.content[0].text
if "done" in text.lower():
break # fragile, unreliable, exam-wrongDen kanoniske løkken
Her er løkkens riktige form. De undersøker stop_reason i hver omgang. Når den er tool_use, kjører De verktøyene og legger resultatene til i samtalen. De gjentar til stop_reason er end_turn.
Legg merke til at løkken styres fullstendig av det strukturerte signalet — ingen tekstinspeksjon avgjør avslutningen.
while True:
resp = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
tools=tools,
messages=messages,
)
messages.append({"role": "assistant", "content": resp.content})
if resp.stop_reason == "end_turn":
break
if resp.stop_reason == "tool_use":
results = run_tools(resp.content)
messages.append({"role": "user", "content": results})
continueFull historikk i hver omgang
En av grunnene til at løkken fungerer, er at modellen ikke beholder tilstand mellom forespørsler. Hvert API-kall må inneholde hele historikken i messages.
Derfor legger De, etter en tool_use-runde, både assistentens innhold for verktøykallet OG verktøyresultatene tilbake i messages før neste forespørsel. Modellen leser gjennom hele samtalen på nytt og avgjør om flere verktøy trengs, eller om den kan avslutte med end_turn.
Hvis De utelater historikken, mister modellen tråden — den klarer ikke å nå en sammenhengende end_turn.
# Each request resends EVERYTHING
messages = [
{"role": "user", "content": "Refund order 4471."},
{"role": "assistant", "content": [tool_use_block]}, # prior turn
{"role": "user", "content": [tool_result_block]}, # prior turn
]
resp = client.messages.create(model=MODEL, max_tokens=1024,
tools=tools, messages=messages)tool_use er ikke et stopp
En vanlig feil er å behandle tool_use som en sluttstatus. Det er det ikke. Det betyr «sett på pause, kjør dette verktøyet, og kom deretter tilbake til meg».
Når De ser tool_use, skal De:
- Kjøre de forespurte verktøyene i Deres egen kode.
- Legge
tool_result-blokkene til imessages. - Sende forespørselen på nytt slik at modellen kan fortsette.
Bare end_turn betyr at arbeidet i denne runden faktisk er ferdig.
if resp.stop_reason == "tool_use":
tool_results = []
for block in resp.content:
if block.type == "tool_use":
output = dispatch(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": output,
})
messages.append({"role": "user", "content": tool_results})
# loop continues -> next requestBeslutninger styres av modellen
Det dypere prinsippet er: la modellen avgjøre når den er ferdig. Modellen har hele konteksten — brukerens mål, verktøyresultatene og samtalen så langt. Den er bedre posisjonert enn en hardkodet regel til å vurdere om oppgaven er fullført.
Deres oppgave som arkitekt er å tilby gode verktøy og tydelige instruksjoner, og deretter stole på signalet end_turn. Bruk hardkodet kontrollflyt for garantier De ikke kan overlate til sannsynligheten.
Iterasjonsgrensen er et sikkerhetsnett
De bør fortsatt legge inn en grense for maksimalt antall iterasjoner — men forstå hvilken rolle den har. En iterasjonsgrense er et sikkerhetsnett som skal forhindre løkker som løper løpsk eller uforutsette kostnadsøkninger. Den er IKKE den primære stoppmekanismen.
Det primære stoppet er alltid end_turn. Grensen utløses bare i det sjeldne, patologiske tilfellet der modellen aldri konvergerer. Hvis løkken Deres er avhengig av grensen for å avsluttes normalt, er utformingen feil.
MAX_ITERS = 20 # safety net, NOT the normal exit
for i in range(MAX_ITERS):
resp = client.messages.create(model=MODEL, max_tokens=1024,
tools=tools, messages=messages)
messages.append({"role": "assistant", "content": resp.content})
if resp.stop_reason == "end_turn":
break # normal exit
# ... handle tool_use ...
else:
log.warning("Hit iteration cap without end_turn")Håndtering av max_tokens
max_tokens er et særtilfelle som krever egen håndtering. Det betyr at svaret ble avkortet midt i genereringen — modellen rakk ikke å fullføre tanken.
Hvis De behandler dette som en ren fullføring, avbryter De agentens arbeid i stillhet. Avhengig av utformingen kan De øke max_tokens, be modellen om å fortsette eller markere runden. Det De IKKE må gjøre, er å fortsette som normalt og anta at oppgaven er ferdig.
if resp.stop_reason == "max_tokens":
# output was cut off - NOT a completion
log.warning("Response truncated; consider raising max_tokens or continuing")
# handle explicitly; do not treat as end_turnHvor hardkodet logikk hører hjemme
Hvis modellstyrte beslutninger er standarden, når bør De bruke deterministisk kode?
For garantier — resultater som må gjelde hver eneste gang, uavhengig av modellens vurdering. Eksempler er en forutsetning som blokkerer en refusjon til get_customer returnerer en bekreftet ID, eller en hook som avviser alle refusjoner over en terskel fastsatt i retningslinjene.
Dette er 100 % deterministiske håndhevingspunkter. Avslutning er derimot en modellstyrt beslutning som De leser fra stop_reason. Ikke bland de to: hardkod garantier, og stol på end_turn for kontrollflyten.
Slik henger det sammen
En agentløkkke klar for produksjon kombinerer alle delene:
- Gren på
stop_reason— aldri på tekst. - Send hele historikken på nytt i hver runde (modellen er tilstandsløs).
tool_use→ kjør, legg til, fortsett.end_turn→ stopp.- Håndter
max_tokenseksplisitt — avkorting er ikke fullføring. - Behold en iterasjonsgrense som et sikkerhetsnett, og ikke noe mer.
Dette er ryggraden i enhver pålitelig agent De utformer.
for _ in range(MAX_ITERS):
resp = client.messages.create(model=MODEL, max_tokens=2048,
tools=tools, messages=messages)
messages.append({"role": "assistant", "content": resp.content})
if resp.stop_reason == "end_turn":
break
if resp.stop_reason == "max_tokens":
handle_truncation(resp); break
if resp.stop_reason == "tool_use":
messages.append({"role": "user",
"content": run_tools(resp.content)})
continueKort kontroll: avslutte løkken
En supportagent bygget på Agent SDK går noen ganger i løkke for alltid og stopper andre ganger før den kaller et nødvendig verktøy. Løkken avsluttes nå når teksten fra assistenten inneholder ordet «resolved». Hva er den riktige løsningen?
Oppsummering: stol på signalet
Viktigste punkter:
- Avslutt på
stop_reason, aldri ved å analysere tekst etter ord som «done» eller «resolved». end_turnavslutter løkken;tool_usebetyr at De skal kjøre verktøy, legge til resultatene og fortsette.- Håndter
max_tokenseksplisitt — avkorting er ikke fullføring. - Modellen er tilstandsløs: send hele meldingshistorikken på nytt i hver runde.
- Avslutning er en modellstyrt beslutning; iterasjonsgrensen er bare et sikkerhetsnett.
- Begrens hardkodet håndheving til garantier (forutsetninger, hooker), ikke til å avslutte løkken.
La end_turn avslutte løkken. Denne ene disiplinen gjør agentene Deres forutsigbare og klare for produksjon.
Lær deg Python med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 26
- Leksjoner
- 104
Ofte stilte spørsmål
Er leksjonen «Avslutte ved stop_reason» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Claude Architect, inkludert «Avslutte ved stop_reason», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Claude Architect inneholder totalt 4 leksjoner.
Hva lærer jeg i «Avslutte ved stop_reason»?
La end_turn avslutte løkken, ikke strengsammenligning. Du øver på Claude Architect med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Claude Architect?
Ingen tidligere erfaring er nødvendig. Claude Architect på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «Avslutte ved stop_reason»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Claude Architect-leksjonen?
Ja. Alle Claude Architect-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Kjerneløkken
- Avslutte ved stop_reason
- Antimønster: Analysere tekst for å finne fullføring
- Antimønster: Vilkårlige grenser for antall iterasjoner