0Pricing
Claude Architect · 강의

중지 이유 이해하기

end_turn, tool_use, max_tokens 및 stop_sequence를 다룹니다

중지 이유 이해하기은(는) CoddyKit의 무료 Claude Architect 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Claude Architect 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Claude Architect 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Why Stop Reasons Matter

Every time you call the Claude API, the response comes back with a stop_reason field. It tells you why the model stopped generating.

This one field drives your whole control flow. A reliable agent inspects stop_reason after each turn and decides what to do next based on it.

There are four values you must know: end_turn, tool_use, max_tokens, and stop_sequence. Let's learn each one.

Where to Find It

The stop_reason lives on the response object returned by messages.create.

Read it directly. Do not scan the text output for words like "done" or "finished" to decide what happened. The model controls stop_reason; text is just content.

from anthropic import Anthropic

client = Anthropic()
response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello"}],
)

print(response.stop_reason)  # "end_turn"

end_turn — Complete

end_turn means Claude finished its response naturally. It said everything it wanted to say.

This is the normal completion signal. In an agent loop, end_turn is your cue to stop looping and return the answer to the user.

if response.stop_reason == "end_turn":
    # Claude is done. Return the answer.
    print(response.content[0].text)

tool_use — Run a Tool

tool_use means Claude wants to call one of the tools you gave it. The response is not finished — Claude is waiting for a tool result.

Your job: run the requested tool, append the result to the message history, and call the API again so Claude can continue.

if response.stop_reason == "tool_use":
    tool_call = next(b for b in response.content if b.type == "tool_use")
    result = run_tool(tool_call.name, tool_call.input)
    # Append the result and loop again (next scenes show how)

max_tokens — Truncated

max_tokens means the response was cut off because it hit the max_tokens limit you set in the request.

The output is incomplete — it stopped mid-thought, not because Claude was done. The fix is to raise max_tokens, or stream the response for very long outputs.

Never treat max_tokens as a successful completion.

if response.stop_reason == "max_tokens":
    # Output was truncated. Retry with a higher max_tokens,
    # or use client.messages.stream(...) for long outputs.
    print("Response was cut off — increase max_tokens.")

stop_sequence — Custom Stop

stop_sequence means Claude hit a custom stop string that you defined in your request via stop_sequences.

Generation halts the moment that string is produced. This is useful when you want the model to stop at a known boundary, such as "###" or "END".

response = client.messages.create(
    model="claude-opus-4-8",
    max_tokens=1024,
    stop_sequences=["###"],
    messages=[{"role": "user", "content": "List three colors, then ###"}],
)

if response.stop_reason == "stop_sequence":
    print("Stopped at a custom sequence.")

The Four at a Glance

Here is the full set for this lesson:

  • end_turn — Claude finished naturally. Stop the loop.
  • tool_use — Claude wants a tool. Run it, append the result, call again.
  • max_tokens — Output truncated. Raise the limit or stream.
  • stop_sequence — Hit a custom stop string you defined.

Two of these (end_turn, stop_sequence) mean the turn is complete. One (tool_use) means continue. One (max_tokens) means something went wrong with your limit.

The Agentic Loop

An agent is just a loop driven by stop_reason:

Send a request, inspect stop_reason. If it is tool_use, run the tools, append the results to the history, and repeat. Keep going until stop_reason is end_turn.

The model keeps no state between calls, so you must send the full message history every turn.

messages = [{"role": "user", "content": user_input}]

while True:
    response = client.messages.create(
        model="claude-opus-4-8",
        max_tokens=4096,
        tools=tools,
        messages=messages,
    )
    if response.stop_reason == "end_turn":
        break
    if response.stop_reason == "tool_use":
        messages.append({"role": "assistant", "content": response.content})
        results = run_tools(response.content)
        messages.append({"role": "user", "content": results})

Terminate on the Signal, Not the Text

The single most important rule: terminate the loop on stop_reason, never by parsing text for words like "done", "finished", or "complete".

Text-matching is fragile — the model might say "I'm done thinking, let me check one more file" and your code would stop too early. The stop_reason is the model's structured, reliable signal.

Iteration Caps Are a Safety Net

You may add a maximum iteration count to your loop so a runaway agent cannot loop forever. That is good practice.

But an iteration cap is a safety net, never the primary way you stop. The primary stop is always end_turn. Decisions about when work is done are model-driven; the cap only catches the rare case where something goes wrong.

MAX_ITERS = 25  # safety net only

for _ in range(MAX_ITERS):
    response = client.messages.create(...)
    if response.stop_reason == "end_turn":
        break  # the real, primary stop
    # ... handle tool_use ...
else:
    log.warning("Hit iteration cap — investigate.")

Putting It Together

A robust handler branches on every stop reason explicitly:

  • end_turn → return the result.
  • tool_use → execute tools, append results, continue.
  • max_tokens → the output is truncated; raise the limit and retry rather than using a partial answer.
  • stop_sequence → handle the known boundary you defined.

Handling all branches is what separates a reliable agent from one that silently breaks on edge cases.

def handle(response):
    sr = response.stop_reason
    if sr == "end_turn":
        return finish(response)
    if sr == "tool_use":
        return continue_with_tools(response)
    if sr == "max_tokens":
        return retry_with_more_tokens(response)
    if sr == "stop_sequence":
        return handle_boundary(response)

Quick Check

An agent loop returns a response with stop_reason == "tool_use". What is the correct next action?

Recap

Key takeaways:

  • end_turn — complete; stop the loop and return.
  • tool_use — run the tool, append the result, call again.
  • max_tokens — truncated; raise the limit or stream, don't use the partial output.
  • stop_sequence — hit a custom stop string you defined.

Always drive your control flow from stop_reason, never from parsing text. Terminate on end_turn; keep iteration caps as a safety net only. Master this and the agentic loop becomes simple and reliable.

자주 묻는 질문

“중지 이유 이해하기” 강의는 무료인가요?

네 — “중지 이유 이해하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Claude Architect 강의 전체를 잠금 해제할 수 있습니다. Claude Architect 강의에는 총 4개의 강의가 포함되어 있습니다.

“중지 이유 이해하기”에서 뭘 배우나요?

end_turn, tool_use, max_tokens 및 stop_sequence를 다룹니다 브라우저에서 직접 실행하는 실습 코드로 Claude Architect을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Claude Architect을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Claude Architect은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“중지 이유 이해하기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Claude Architect 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Claude Architect 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. Claude 모델 제품군
  2. API 요청의 구조
  3. 중지 이유 이해하기
  4. 토큰, 컨텍스트 창 및 비용
← Claude Architect(으)로 돌아가기