1. The Master Loop
Confidence: 100% (Tier 1 - Official) Source: Anthropic Engineering Blog
Claude Code is remarkably simple:
┌─────────────────────────────────────────────────────────────┐
│ CLAUDE CODE MASTER LOOP │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ │
│ │ Your Prompt │ │
│ └──────┬───────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ CLAUDE REASONS │ │
│ │ (No classifier, no routing layer) │ │
│ │ │ │
│ └────────────────────────┬─────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ Tool Call? │ │
│ └───────┬────────┘ │
│ │ │
│ YES │ NO │
│ ┌─────────────────┴─────────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ │
│ │ Execute │ │ Text │ │
│ │ Tool │ │ Response │ │
│ │ │ │ (DONE) │ │
│ └─────┬──────┘ └────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Feed Result │ │
│ │ to Claude │──────────────────┐ │
│ └─────────────┘ │ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ LOOP BACK │ │
│ │ (Next turn) │ │
│ └────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘What This Means
The entire architecture is a simple while loop:
while (claude_response.has_tool_call):
result = execute_tool(tool_call)
claude_response = send_to_claude(result)
return claude_response.textThere is no:
- Intent classifier
- Task router
- RAG/embedding pipeline
- DAG orchestrator
- Planner/executor split
The model itself decides when to call tools, which tools to call, and when it's done. This is the "agentic loop" pattern described in Anthropic's engineering blog.
Why This Design?
- Simplicity: Fewer components = fewer failure modes
- Model-driven: Claude's reasoning is better than hand-coded heuristics
- Flexibility: No rigid pipeline constraining what Claude can do
- Debuggability: Easy to understand what happened and why
Agentic Loop API Vocabulary
The master loop diagram above shows the flow conceptually, but the Anthropic API exposes it through concrete stop_reason values. Every API response includes a stop_reason field: it's how Claude signals what should happen next. Understanding these three values is essential for building custom agents on top of the Anthropic SDK.
stop_reason | Meaning | Loop action |
|---|---|---|
tool_use | Claude wants to call one or more tools | Execute tools, feed results back, continue loop |
end_turn | Claude decided it has finished | Exit loop, return the text response |
max_tokens | Context limit reached before finishing | Rethink context strategy, likely need summarization |
The pseudocode becomes precise with these names:
messages = [{"role": "user", "content": user_prompt}]
while True:
response = client.messages.create(model=model, messages=messages, tools=tools)
if response.stop_reason == "end_turn":
return response.content[0].text # done
if response.stop_reason == "tool_use":
# Process every tool_use block in the response
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = execute_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": result
})
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})
# loop continuesThe tool_use block inside response.content has three fields you act on: id (to match results back), name (which function to call), and input (a dict of arguments). The result you send back must reference tool_use_id so the model can correlate call and response.
fork_session is a higher-level concept built on this loop: it creates an independent branch of the current conversation, sharing the same message history up to the fork point. Both branches can explore different approaches or configurations simultaneously, like git branch but for agent sessions. Each fork runs its own agentic loop independently, useful for comparing responses under different tool configurations or prompt variants without re-running the full conversation from scratch.
Controlling loop depth with max_turns
max_turns caps the number of assistant/tool iterations before the orchestrator exits. Without an explicit limit, a runaway loop can exhaust budget or context window in ways that are hard to diagnose after the fact.
Practical ranges by task type:
| Task type | Recommended max_turns |
|---|---|
| Simple retrieval (single lookup) | 5 |
| Research or multi-step coding | 20-30 |
| Extended autonomous workflows | 50 |
When max_turns is reached, the loop exits with whatever state was last written. The task may be incomplete. Always check the final stop_reason and implement a fallback path:
result = agent.run(task, max_turns=20)
if result.stop_reason == "max_turns":
# escalate or summarize partial progress
handle_incomplete(result)Setting max_turns per task type rather than globally prevents a single slow task from starving others in a multi-agent pipeline. A nightly batch job that legitimately needs 50 turns should not inherit the same cap as a quick lookup that should resolve in 5.
Native Capabilities Audit
Use this checklist to verify you understand Claude Code's full surface area. Each capability is documented in detail elsewhere in this guide.
The 11 Native Capabilities:
[ ] Event Hooks: Bash/PowerShell scripts triggered on tool execution
- PreToolUse, PostToolUse, UserPromptSubmit, Notification
- See: Section 5 Hooks
[ ] Skill-Scoped Hooks: Event hooks specific to skill execution context
- Lifecycle management per skill
- See: Ultimate Guide Section 5.11
[ ] Background Agents: Async task execution (test suites, long operations)
- Non-blocking agent spawning
- See: Section 4.2 Sub-Agent Architecture
[ ] Explore Subagent:
/explorefor codebase analysis- Read-only codebase exploration
- See: Section 4.2 Sub-Agents
[ ] Plan Subagent:
/planfor read-only planning mode- Safe architectural exploration
- See: Ultimate Guide Section 2.3
[ ] Task Tool: Hierarchical task delegation to specialized agents
- Parallel task execution, depth=1 sub-agents
- See: Section 4.2 Sub-Agent Architecture
[ ] Agent Teams: Multi-agent parallel coordination (experimental v2.1.32+)
- Git-based coordination, autonomous task claiming
- See: Ultimate Guide Section 9.20
[ ] Per-Task Model Selection: Dynamic model switching mid-session
/model opus|sonnet|haikuon task boundaries- See: Section 10 Cost Optimization
[ ] MCP Protocol Integration: Model Context Protocol for tool extensions
- Context7, Sequential, Serena, Playwright, etc.
- See: Section 6 MCP Integration
[ ] Permission Modes: Fine-grained control over tool execution
- Default, auto-accept, plan mode, custom rules
- See: Section 5 Permission & Security Model
[ ] Session Memory: Persistent context across sessions
- CLAUDE.md, memory files, project state
- See: Section 8 Session Persistence
Onboarding Tip: If you haven't explored all 11 capabilities, you're likely missing productivity opportunities. Focus on the unchecked items above.
Source: Synthesized from Gur Sannikov analysis