The Agent Loop
A turn is everything that happens from your prompt to the final answer. Inside a turn, the model asks for tools. Claude Code runs them. The model reads the results. This repeats until the model answers without a tool call. This page explains each stage. It also shows where you can act.
The Turn at a Glance
Then Claude Code runs the tool and sends the result back to the model.
The turn ends when the model answers without a tool call.
The Stages
Sources: Hooks Reference: Hook Lifecycle and Mods Reference for the events. Source: the program for the rest.
| Stage | Status | What happens | Where you can act |
|---|---|---|---|
| 1. Input | Documented: An official docs page names this item. | Claude Code reads your text. A message you type during a turn joins at a safe point. | User hook, prompt. mod event |
| 2. Command expansion | Documented: An official docs page names this item. | A slash command or skill name turns into a prompt. | User hook |
| 3. Context pickup | Documented: An official docs page names this item. | Claude Code adds nested memory, @ mentions, and file-change notes. | Instructions hook, prompt. and prompt. mod events |
| 4. Message prep | Undocumented: Only the program shows this item. It can change without notice. | Large tool results become references. Claude Code looks up the facts of the model. | Pre and Post hooks |
| 5. Auto compaction | Documented: An official docs page names this item. | Claude Code compacts the conversation if it is over the threshold. See Context and Compaction. | Pre and Post hooks |
| 6. Attachments | Undocumented: Only the program shows this item. It can change without notice. | Claude Code adds reminders and notes about the mode. | prompt. mod event |
| 7. Request build | Documented: An official docs page names this item. | Claude Code builds the system, tools, and messages parts. See Request and Cache. | prompt., prompt., and tool. mod events |
| 8. Stream | Documented: An official docs page names this item. | Claude Code sends the request and reads the events, with retries and fallbacks. See Models. | Message hook |
| 9. Tools | Documented: An official docs page names this item. | Each tool call passes the permission check and then runs. | Tool hooks (next section) |
| 10. Next round | Undocumented: Only the program shows this item. It can change without notice. | The tool results join the messages. The loop starts again at stage 3. | Post hook |
| 11. Stop | Documented: An official docs page names this item. | With no tool call, the Stop hooks run. A hook that blocks sends its reason back to the model. | Stop and Stop hooks |
The mod events turn.start, turn.step, and turn.complete wrap the whole turn.
See the Mod API pages in Extend.
The Tool Stage
Sources: Hooks Reference and Environment Variables.
| Step | Status | What happens |
|---|---|---|
| Permission check | Documented: An official docs page names this item. | Your rules and the permission mode decide to allow, ask, or deny. See Permission Flow in this section. |
Pre hook | Documented: An official docs page names this item. | The hook can block or change the call. |
Permission hook | Documented: An official docs page names this item. | The hook runs when a decision is needed. |
| Run | Documented: An official docs page names this item. | Read-only tools and subagents run in parallel, up to CLAUDE_ (default 10). Other tools run one after another. |
Post and Post hooks | Documented: An official docs page names this item. | They run after each call. |
Post hook | Documented: An official docs page names this item. | It runs after a batch of parallel calls and before the next model call. It can stop the loop. |
Recovery Inside the Loop
The loop does not fail on every error. It tries to fix the problem and continue.
| Case | Status | What Claude Code does |
|---|---|---|
The output stops at max_ | Undocumented: Only the program shows this item. It can change without notice. | It adds a nudge message and asks again, a limited number of times. |
| The response is cut off | Undocumented: Only the program shows this item. It can change without notice. | It does the same. |
A tool_ block has no valid call | Undocumented: Only the program shows this item. It can change without notice. | It drops the reply and asks once more. Then it ends with a message that the tool call could not be parsed. |
| The model sends only thinking | Undocumented: Only the program shows this item. It can change without notice. | It sends one nudge. |
| A safety refusal | Documented: An official docs page names this item. | It runs again on the fallback model of that category. See Models. |
| The context is too long | Documented: An official docs page names this item. | It lowers max_ or compacts. |
| Autocompact refills 3 times in a row | Documented: An official docs page names this item. | It ends the turn with an error that starts Autocompact is thrashing. See Troubleshooting in the official docs. |
A Stop hook blocks | Documented: An official docs page names this item. | It sends the reason back to the model. After CLAUDE_ blocks in a row (default 8), it ends the turn. |
-- is reached | Documented: An official docs page names this item. | It ends the run. See the CLI Reference in the official docs. |
How a Turn Ends
The loop returns a reason. Claude Code records it in telemetry.
The chat does not show it.
A result message of the Agent SDK and of --output-format stream-json carries it as terminal_reason.
All reasons are
reason | Meaning |
|---|---|
completed | The turn ended in the normal way. |
max_ | The turn reached the turn limit. |
aborted_, aborted_ | You stopped the turn (for example with Esc) while the model streamed or tools ran. |
hook_, stop_ | A hook stopped the turn. |
tool_ | A hook deferred a tool call. |
tool_ | Claude Code could not resume a deferred tool call. |
background_ | The turn moved to a background session. |
blocking_ | The context hit the blocked level. See Context and Compaction. |
rapid_ | Autocompact refilled the context too fast. |
model_, api_, image_ | The API or an image failed. |
malformed_ | The model sent a tool call that could not be parsed, and the retries failed too. Since 2. Claude Code retries the call up to twice (release notes). Before, the turn ended after two bad calls in a row. |
prompt_ | The prompt did not fit the context window. |
budget_ | The run used all of its budget. |
structured_ | The model did not give valid structured output after the allowed retries. |
turn_ | Claude Code failed to set up the turn. |
What You Can Change
| Goal | How |
|---|---|
| Check or edit every prompt before it runs | A User hook. |
| Block or rewrite a tool call | A Pre hook or a permission rule. |
| Force the model to keep working | A Stop hook that blocks. Mind CLAUDE_. |
| Limit tool parallelism | Set CLAUDE_. |
| Limit the number of turns | Use -- in print mode. |
| Rewrite a part of the system prompt | A mod listening to prompt. or prompt.. See The System Prompt. |
| Change the compaction point | See Context and Compaction. |
Example
This hook in .claude/settings.json runs a script before every Bash call.
If the script exits with code 2, Claude Code blocks the call. The reason goes back to the model.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": ".claude/hooks/check-bash.sh" }
]
}
]
}
}
Related Pages
- Architecture
- Request and Cache
- Context and Compaction
- Hooks, Tools, Subagents, and Mod API pages in Extend and Reference.