How the agent loop works changedagent-sdk/agent-loop
Nearest release: v2.1.273, published 3 hours before upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Upstream edited this page at 15 Sep 2026 21:21 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 28 Sep 2026 23:37 UTC.
Upstream edited
Recorded here
Lines+48added
Lines−48removed
From line
148
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits14to this page, all time
The whole hunk
from line 148, old and new numbered
/
from line 148
148148
149149The SDK includes the same tools that power Claude Code:
150150
151| Category | Tools | What they do |
152| :------------------ | :-------------------------------------------------------------- | :-------------------------------------------------------------------------- |
153| **File operations** | `Read`, `Edit`, `Write` | Read, modify, and create files |
154| **Search** | `Glob`, `Grep` | Find files by pattern, search content with regex |
155| **Execution** | `Bash` | Run shell commands, scripts, git operations |
156| **Web** | `WebSearch`, `WebFetch` | Search the web, fetch and parse pages |
157| **Discovery** | `ToolSearch` | Dynamically find and load tools on-demand instead of preloading all of them |
158| **Orchestration** | `Agent`, `Skill`, `AskUserQuestion`, `TaskCreate`, `TaskUpdate` | Spawn subagents, invoke skills, ask the user, track tasks |
151| Category | Tools | What they do |
152| :- | :- | :- |
153| **File operations** | `Read`, `Edit`, `Write` | Read, modify, and create files |
154| **Search** | `Glob`, `Grep` | Find files by pattern, search content with regex |
155| **Execution** | `Bash` | Run shell commands, scripts, git operations |
156| **Web** | `WebSearch`, `WebFetch` | Search the web, fetch and parse pages |
157| **Discovery** | `ToolSearch` | Dynamically find and load tools on-demand instead of preloading all of them |
158| **Orchestration** | `Agent`, `Skill`, `AskUserQuestion`, `TaskCreate`, `TaskUpdate` | Spawn subagents, invoke skills, ask the user, track tasks |
159159
160160On the [models that don't get the task-tracking tools](/docs/en/agent-sdk/todo-tracking#model-availability), Claude Code provides `TaskCreate` and `TaskUpdate` only when you opt in.
161161
from line 189
189189
190190### Turns and budget
191191
192| Option | What it controls | Default |
193| :--------------------------------------------- | :--------------------------- | :------- |
194| Max turns (`max_turns` / `maxTurns`) | Maximum tool-use round trips | No limit |
192| Option | What it controls | Default |
193| :- | :- | :- |
194| Max turns (`max_turns` / `maxTurns`) | Maximum tool-use round trips | No limit |
195195| Max budget (`max_budget_usd` / `maxBudgetUsd`) | Maximum cost before stopping | No limit |
196196
197197When either limit is hit, the SDK returns a `ResultMessage` with a corresponding error subtype (`error_max_turns` or `error_max_budget_usd`). See [Handle the result](#handle-the-result) for how to check these subtypes and [`ClaudeAgentOptions`](/docs/en/agent-sdk/python#claudeagentoptions) / [`Options`](/docs/en/agent-sdk/typescript#options) for syntax.
from line 204
204204
205205The `effort` option controls how much reasoning Claude applies. Lower effort levels use fewer tokens per turn and reduce cost. Not all models support the effort parameter. See [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) for which models support it.
206206
207| Level | Behavior | Good for |
208| :--------- | :-------------------------------- | :--------------------------------------------------------------------------------------------- |
209| `"low"` | Minimal reasoning, fast responses | File lookups, listing directories |
210| `"medium"` | Balanced reasoning | Routine edits, standard tasks |
211| `"high"` | Thorough analysis | Refactors, debugging |
212| `"xhigh"` | Extended reasoning depth | Coding and agentic tasks on the [models that support it](/docs/en/model-config#adjust-effort-level) |
213| `"max"` | Maximum reasoning depth | Multi-step problems requiring deep analysis |
207| Level | Behavior | Good for |
208| :- | :- | :- |
209| `"low"` | Minimal reasoning, fast responses | File lookups, listing directories |
210| `"medium"` | Balanced reasoning | Routine edits, standard tasks |
211| `"high"` | Thorough analysis | Refactors, debugging |
212| `"xhigh"` | Extended reasoning depth | Coding and agentic tasks on the [models that support it](/docs/en/model-config#adjust-effort-level) |
213| `"max"` | Maximum reasoning depth | Multi-step problems requiring deep analysis |
214214
215215If you don't set `effort`, Claude Code resolves the effort level itself, in the order [Adjust effort level](/docs/en/model-config#adjust-effort-level) describes.
216216
from line 224
224224
225225The permission mode option (`permission_mode` in Python, `permissionMode` in TypeScript) controls whether the agent asks for approval before using tools:
226226
227| Mode | Behavior | Use case |
228| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |
229| `"default"` | Tool calls that need approval and aren't covered by allow rules trigger your `canUseTool` callback; no callback means deny | Interactive applications with a custom approval callback |
230| `"acceptEdits"` | Auto-approves file edits and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.); other Bash commands follow default rules | You trust Claude's edits and want faster iteration, such as during prototyping or when working in an isolated directory |
231| `"plan"` | Claude explores and plans without editing your source files; file edits are never auto-approved and prompt through your `canUseTool` callback | You want Claude to propose changes without executing them, such as during code review or when you need to approve changes before they're made |
232| `"dontAsk"` | Never prompts. Tools pre-approved by [permission rules](/docs/en/settings-reference#permission-settings) run, and so do calls that need no approval in `default` mode, such as file reads inside your working directories; every call that would otherwise prompt is denied. `AskUserQuestion`, connector tools [your organization set to `ask`](/docs/en/mcp#organization-controls-on-connector-tools), and MCP tools marked [`requiresUserInteraction`](/docs/en/mcp#require-approval-for-a-specific-tool) are denied even if you've allowed them | You want a fixed, explicit tool surface for a headless agent and prefer a hard deny over silent reliance on `canUseTool` being absent |
233| `"auto"` | Uses a model classifier to approve or deny permission prompts. See [Auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) for availability and behavior | Autonomous agents that still want safety guardrails on tool use |
234| `"bypassPermissions"` | Runs all allowed tools without asking, except tools matched by an explicit [`ask` rule](/docs/en/settings-reference#permission-settings), connector tools [your organization set to `ask`](/docs/en/mcp#organization-controls-on-connector-tools), and tools that require user interaction. The [cross-session messaging safeguards](/docs/en/permission-modes#skip-all-checks-with-bypasspermissions-mode) still apply. See [How permissions are evaluated](/docs/en/agent-sdk/permissions#how-permissions-are-evaluated) for the precedence order. In the TypeScript SDK, also requires `allowDangerouslySkipPermissions: true` in `options`. Can't be used when running as root on Unix. Use only in isolated environments where the agent's actions can't affect systems you care about | CI, containers, or other isolated environments |
227| Mode | Behavior | Use case |
228| :- | :- | :- |
229| `"default"` | Tool calls that need approval and aren't covered by allow rules trigger your `canUseTool` callback; no callback means deny | Interactive applications with a custom approval callback |
230| `"acceptEdits"` | Auto-approves file edits and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.); other Bash commands follow default rules | You trust Claude's edits and want faster iteration, such as during prototyping or when working in an isolated directory |
231| `"plan"` | Claude explores and plans without editing your source files; file edits are never auto-approved and prompt through your `canUseTool` callback | You want Claude to propose changes without executing them, such as during code review or when you need to approve changes before they're made |
232| `"dontAsk"` | Never prompts. Tools pre-approved by [permission rules](/docs/en/settings-reference#permission-settings) run, and so do calls that need no approval in `default` mode, such as file reads inside your working directories; every call that would otherwise prompt is denied. `AskUserQuestion`, connector tools [your organization set to `ask`](/docs/en/mcp#organization-controls-on-connector-tools), and MCP tools marked [`requiresUserInteraction`](/docs/en/mcp#require-approval-for-a-specific-tool) are denied even if you've allowed them | You want a fixed, explicit tool surface for a headless agent and prefer a hard deny over silent reliance on `canUseTool` being absent |
233| `"auto"` | Uses a model classifier to approve or deny permission prompts. See [Auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) for availability and behavior | Autonomous agents that still want safety guardrails on tool use |
234| `"bypassPermissions"` | Runs all allowed tools without asking, except tools matched by an explicit [`ask` rule](/docs/en/settings-reference#permission-settings), connector tools [your organization set to `ask`](/docs/en/mcp#organization-controls-on-connector-tools), and tools that require user interaction. The [cross-session messaging safeguards](/docs/en/permission-modes#skip-all-checks-with-bypasspermissions-mode) still apply. See [How permissions are evaluated](/docs/en/agent-sdk/permissions#how-permissions-are-evaluated) for the precedence order. In the TypeScript SDK, also requires `allowDangerouslySkipPermissions: true` in `options`. Can't be used when running as root on Unix. Use only in isolated environments where the agent's actions can't affect systems you care about | CI, containers, or other isolated environments |
235235
236236For interactive applications, use `"default"` with a tool approval callback to surface approval prompts. For autonomous agents on a dev machine, `"acceptEdits"` auto-approves file edits and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.) while still gating other `Bash` commands behind allow rules. Reserve `"bypassPermissions"` for CI, containers, or other isolated environments. See [Permissions](/docs/en/agent-sdk/permissions) for full details.
237237
from line 247
247247
248248Here's how each component affects context in the SDK:
249249
250| Source | When it loads | Impact |
251| :----------------------- | :------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
252| **System prompt** | Every request | Small fixed cost, always present |
253| **CLAUDE.md files** | Session start, via [`settingSources`](/docs/en/agent-sdk/claude-code-features) | Full content in every request (but prompt-cached, so only the first request pays full cost) |
254| **Tool definitions** | Every request; MCP schemas deferred by default | Built-in tool schemas load every request. [Tool search](/docs/en/agent-sdk/mcp#mcp-tool-search) defers MCP tool schemas by default, falling back to upfront loading on unsupported models and certain platforms. See [Configure tool search](/docs/en/agent-sdk/tool-search#configure-tool-search) for the full matrix |
255| **Conversation history** | Accumulates over turns | Grows with each turn: prompts, responses, tool inputs, tool outputs |
256| **Skill descriptions** | Session start, via setting sources | Short summaries; full content loads only when invoked |
250| Source | When it loads | Impact |
251| :- | :- | :- |
252| **System prompt** | Every request | Small fixed cost, always present |
253| **CLAUDE.md files** | Session start, via [`settingSources`](/docs/en/agent-sdk/claude-code-features) | Full content in every request (but prompt-cached, so only the first request pays full cost) |
254| **Tool definitions** | Every request; MCP schemas deferred by default | Built-in tool schemas load every request. [Tool search](/docs/en/agent-sdk/mcp#mcp-tool-search) defers MCP tool schemas by default, falling back to upfront loading on unsupported models and certain platforms. See [Configure tool search](/docs/en/agent-sdk/tool-search#configure-tool-search) for the full matrix |
255| **Conversation history** | Accumulates over turns | Grows with each turn: prompts, responses, tool inputs, tool outputs |
256| **Skill descriptions** | Session start, via setting sources | Short summaries; full content loads only when invoked |
257257
258258Large tool outputs consume significant context. Reading a big file or running a command with verbose output can use thousands of tokens in a single turn. Context accumulates across turns, so longer sessions with many tool calls build up significantly more context than short ones.
259259
from line 310
310310
311311When the loop ends, the `ResultMessage` tells you what happened and gives you the output. The `subtype` field (available in both SDKs) is the primary way to check termination state.
312312
313| Result subtype | What happened | `result` field available? |
314| :------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-----------------------: |
315| `success` | Claude finished the task normally | Yes |
316| `error_max_turns` | Hit the `maxTurns` limit before finishing | No |
317| `error_max_budget_usd` | Hit the `maxBudgetUsd` limit before finishing | No |
318| `error_during_execution` | An error interrupted the loop (for example, a cancelled request) | No |
319| `error_max_structured_output_retries` | No valid structured output was produced within the configured retry limit: every attempt failed validation, or a model fallback retracted the completed output with no successful retry | No |
313| Result subtype | What happened | `result` field available? |
314| :- | :- | :-: |
315| `success` | Claude finished the task normally | Yes |
316| `error_max_turns` | Hit the `maxTurns` limit before finishing | No |
317| `error_max_budget_usd` | Hit the `maxBudgetUsd` limit before finishing | No |
318| `error_during_execution` | An error interrupted the loop (for example, a cancelled request) | No |
319| `error_max_structured_output_retries` | No valid structured output was produced within the configured retry limit: every attempt failed validation, or a model fallback retracted the completed output with no successful retry | No |
320320
321321The `result` field holds the final text output and is only present on the `success` variant, so always check the subtype before reading it.
322322
from line 342
342342
343343[Hooks](/docs/en/agent-sdk/hooks) are callbacks that fire at specific points in the loop: before a tool runs, after it returns, when the agent finishes, and so on. Some commonly used hooks are:
344344
345| Hook | When it fires | Common uses |
346| :------------------------------- | :---------------------------------- | :----------------------------------------- |
347| `PreToolUse` | Before a tool executes | Validate inputs, block dangerous commands |
348| `PostToolUse` | After a tool returns | Audit outputs, trigger side effects |
349| `UserPromptSubmit` | When a prompt is sent | Inject additional context into prompts |
350| `Stop` | When the agent finishes | Validate the result, save session state |
351| `SubagentStart` / `SubagentStop` | When a subagent spawns or completes | Track and aggregate parallel task results |
352| `PreCompact` | Before context compaction | Archive full transcript before summarizing |
345| Hook | When it fires | Common uses |
346| :- | :- | :- |
347| `PreToolUse` | Before a tool executes | Validate inputs, block dangerous commands |
348| `PostToolUse` | After a tool returns | Audit outputs, trigger side effects |
349| `UserPromptSubmit` | When a prompt is sent | Inject additional context into prompts |
350| `Stop` | When the agent finishes | Validate the result, save session state |
351| `SubagentStart` / `SubagentStop` | When a subagent spawns or completes | Track and aggregate parallel task results |
352| `PreCompact` | Before context compaction | Archive full transcript before summarizing |
353353
354354Hooks run in your application process, not inside the agent's context window, so they don't consume context. Hooks can also short-circuit the loop: a `PreToolUse` hook that rejects a tool call prevents it from executing, and Claude receives the rejection message instead.
355355
No line in this hunk matches that.