Sweep 22 Sep 2026 · 17:19Z Build v2.1.280 501 read Stable v2.1.267 Latest v2.1.280 Next v2.1.280 Feeds RSS JSON llms.txt Unofficial
One change · claude-code

How the agent loop works changed

agent-sdk/agent-loop

Nearest release: v2.1.267, published an hour before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Recorded here
Lines+19added
Lines−7removed
From line 17 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits11to this page, all time

The whole hunk

from line 17, old and new numbered
/
lines
from line 17
1717<img src="https://mintcdn.com/claude-code/_xqph1dUOslCOwsj/images/agent-loop-diagram-dark.svg?fit=max&auto=format&n=_xqph1dUOslCOwsj&q=85&s=afe723c52a324d3c61fa72fb02432ab6" className="hidden dark:block" alt="Diagram of the agent loop: your prompt enters the agentic loop, where Claude evaluates and either requests tool calls, whose results feed back into another evaluation, or returns the final answer" width="720" height="212" data-path="images/agent-loop-diagram-dark.svg" />
1818 
19191. **Receive prompt.** Claude receives your prompt, along with the system prompt, tool definitions, and conversation history. The SDK yields a [`SystemMessage`](#message-types) with subtype `"init"` containing session metadata.
202. **Evaluate and respond.** Claude evaluates the current state and determines how to proceed. It may respond with text, request one or more tool calls, or both. The SDK yields an [`AssistantMessage`](#message-types) containing the text and any tool call requests.
202. **Evaluate and respond.** Claude evaluates the current state and determines how to proceed. It may respond with text, request one or more tool calls, or both. The SDK yields one or more [`AssistantMessage`](#message-types) objects, one for each content block, such as a text block or a tool call request.
21213. **Execute tools.** The SDK runs each requested tool and collects the results. Each set of tool results feeds back to Claude for the next decision. You can use [hooks](/docs/en/agent-sdk/hooks) to intercept, modify, or block tool calls before they run.
22224. **Repeat.** Steps 2 and 3 repeat as a cycle. Each full cycle is one turn. Claude continues calling tools and processing results until it produces a response with no tool calls.
23235. **Return result.** The SDK yields a final [`AssistantMessage`](#message-types) with the text response (no tool calls), followed by a [`ResultMessage`](#message-types) with the final text, token usage, cost, and session ID.
from line 33
3333First, the SDK sends your prompt to Claude and yields a [`SystemMessage`](#message-types) with the session metadata. Then the loop begins:
3434 
35351. **Turn 1:** Claude calls `Bash` to run `npm test`. The SDK yields an [`AssistantMessage`](#message-types) with the tool call, executes the command, then yields a [`UserMessage`](#message-types) with the output (three failures).
362. **Turn 2:** Claude calls `Read` on `auth.ts` and `auth.test.ts`. The SDK returns the file contents and yields an `AssistantMessage`.
373. **Turn 3:** Claude calls `Edit` to fix `auth.ts`, then calls `Bash` to re-run `npm test`. All three tests pass. The SDK yields an `AssistantMessage`.
362. **Turn 2:** Claude calls `Read` on `auth.ts` and `auth.test.ts`. The SDK yields an `AssistantMessage` for each call and returns the file contents.
373. **Turn 3:** Claude calls `Edit` to fix `auth.ts`, then calls `Bash` to re-run `npm test`. All three tests pass. The SDK yields an `AssistantMessage` for each call.
38384. **Final turn:** Claude produces a text-only response with no tool calls: "Fixed the auth bug, all three tests pass now." The SDK yields a final `AssistantMessage` with this text, then a [`ResultMessage`](#message-types) with the same text plus cost and usage.
3939 
4040That was four turns: three with tool calls, one final text-only response.
from line 55
5555 * `"worker_shutting_down"`: the loop will end after the current turn because the host is exiting or Remote Control disconnected
5656 
5757 In TypeScript, each subtype other than `"init"` is its own type in the [`SDKMessage` union](/docs/en/agent-sdk/typescript#sdkmessage) rather than a subtype of `SDKSystemMessage`.
58* **`AssistantMessage`:** emitted after each Claude response, including the final text-only one. Contains text content blocks and tool call blocks from that turn.
58* **`AssistantMessage`:** emitted for each content block in Claude's responses, including the final text-only one. Each carries a single content block, such as text or a tool call, and the messages from one response share a message ID.
5959* **`UserMessage`:** emitted after each tool execution with the tool result content sent back to Claude. Also emitted for any user inputs you stream mid-loop.
6060* **`StreamEvent`:** only emitted when partial messages are enabled. Contains raw API streaming events (text deltas, tool input chunks). See [Stream responses](/docs/en/agent-sdk/streaming-output).
6161* **`ResultMessage`:** marks the end of the agent loop. Contains the final text result, token usage, cost, and session ID. Check the `subtype` field to determine whether the task succeeded or hit a limit. A small number of trailing system events, such as `prompt_suggestion`, can arrive after it, so iterate the stream to completion rather than breaking on the result. See [Handle the result](#handle-the-result).
from line 79
7979 <CodeGroup>
8080 ```python Python theme={null}
8181 import asyncio
82 from claude_agent_sdk import query, AssistantMessage, ResultMessage
82 from claude_agent_sdk import query, AssistantMessage, ResultMessage, TextBlock, ToolUseBlock
8383 
8484 
8585 async def main():
from line 86
8686 try:
8787 async for message in query(prompt="Summarize this project"):
8888 if isinstance(message, AssistantMessage):
89 print(f"Turn completed: {len(message.content)} content blocks")
89 # Each AssistantMessage carries one content block
90 for block in message.content:
91 if isinstance(block, TextBlock):
92 print(f"Claude: {block.text}")
93 elif isinstance(block, ToolUseBlock):
94 print(f"Tool call: {block.name}")
9095 if isinstance(message, ResultMessage):
9196 if message.subtype == "success":
9297 print(message.result)
from line 113
108113 try {
109114 for await (const message of query({ prompt: "Summarize this project" })) {
110115 if (message.type === "assistant") {
111 console.log(`Turn completed: ${message.message.content.length} content blocks`);
116 // Each assistant message carries one content block
117 for (const block of message.message.content) {
118 if (block.type === "text") {
119 console.log(`Claude: ${block.text}`);
120 } else if (block.type === "tool_use") {
121 console.log(`Tool call: ${block.name}`);
122 }
123 }
112124 }
113125 if (message.type === "result") {
114126 if (message.subtype === "success") {