The agentic loop is the execution heartbeat of every autonomous Claude system. Task statement 1.1 of the Claude Certified Architect — Foundations (CCA-F) exam — "Design and implement agentic loops for autonomous task execution" — lives at the centre of Domain 1 (27 % weight) for a reason: every other orchestration pattern in the exam, from coordinator-subagent fan-out to session forking to multi-step handoffs, is a structural embellishment on top of a correctly designed agentic loop. If you misread the loop primitives, you misread the rest of Domain 1.
This study note walks through the full agentic-loop surface a CCA-F candidate is expected to design at the architecture level: the perception-reasoning-action-observation cycle, the precise semantics of the stop_reason field, the four stop_reason values you must recognize by sight, safe termination conditions that prevent runaway loops, tool_result injection shape, message-history growth management, sequential-versus-parallel tool calls, the three Agent SDK loop entry points (run, stream, process), error-handling branches inside loops, and production-grade observability. A final traps section and six-question FAQ tie every abstract concept back to the four exam scenarios that exercise agentic loops: customer-support-resolution-agent, code-generation-with-claude-code, developer-productivity-with-claude, and multi-agent-research-system.
What Is an Agentic Loop? Perception, Reasoning, Action, Observation
An agentic loop is a controlled, multi-turn interaction pattern in which Claude alternates between producing a proposed action (usually a tool_use block) and receiving the observation of that action back as a tool_result, iterating until a termination condition is satisfied. The loop is the architectural unit that converts a single-turn language model into an autonomous task-execution engine. Without an agentic loop, Claude is a text completion; with an agentic loop, Claude is an agent.
The canonical four-phase cycle every CCA-F candidate should internalize is:
- Perception — Claude receives messages (system prompt, user task, prior tool results) that describe the current world state.
- Reasoning — Claude's forward pass produces an assistant message that either (a) proposes a
tool_use, (b) finalizes anend_turnanswer, or (c) hits a structural stop likemax_tokensor astop_sequence. - Action — If the assistant message contains a
tool_use, your application (client tool) or the Anthropic platform (server tool) executes the tool and captures its output. - Observation — The tool output is appended to the conversation as a
tool_resultblock inside a new user message, and the cycle returns to Perception.
The loop is explicit — your code runs the while-loop that drives Claude. This is fundamentally different from a traditional chatbot where the conversation terminates after each response. An agentic loop keeps running until Claude voluntarily emits end_turn, until your guardrail cuts it off, or until a hard limit trips.
An agentic loop is a controlled iterative process where Claude proposes tool calls, your application (or the platform) executes those tools, the results are fed back to Claude as tool_result blocks, and the cycle repeats until Claude returns stop_reason: "end_turn" or your termination guard fires. The loop is the basic execution unit of any autonomous Claude agent and is the prerequisite concept for every Domain 1 task statement.
Source ↗
Why CCA-F Puts Agentic Loops First
The exam guide lists task 1.1 as the foundation of Domain 1 because every subsequent task statement (1.2 coordinator-subagent, 1.3 spawning, 1.4 handoffs, 1.5 hooks, 1.6 task decomposition, 1.7 session state) assumes you already understand what Claude is doing between tool_use and end_turn. Community pass reports repeatedly identify "ignoring the stop_reason signal" as a top-five mistake — the kind of mistake that silently costs two to three scored questions on exam day.
Agentic Loop vs Single-Turn Inference — When to Choose Each Architecture
Not every Claude call needs a loop. A large fraction of production Claude usage is still single-turn: classify this text, summarize this document, draft this email. Choosing a loop when a single call is sufficient adds latency, cost, and failure modes for no benefit; choosing a single call when a loop is required guarantees incomplete work.
Single-Turn Inference
Single-turn inference is a one-shot prompt → one-shot response. There are no tools, no follow-up steps, and no dynamic branching based on intermediate results. Use single-turn inference when:
- The task can be completed with information already in the prompt.
- There is no external state to query, mutate, or observe.
- Output structure is known in advance (prose reply, JSON object, classification label).
Agentic Loop
An agentic loop is required when the task has epistemic uncertainty — Claude cannot know the complete answer at message time and must acquire information or take actions to make progress. Use an agentic loop when:
- The task requires reading files, querying databases, or calling external APIs.
- The outcome depends on intermediate observations (the next step is chosen based on the previous tool's output).
- The task is open-ended (fix this bug, research this topic, resolve this support ticket) and the number of steps cannot be predicted up front.
Decision Heuristic
If removing the tools from your design still allows Claude to complete the task, you do not need an agentic loop. If removing the tools makes the task impossible, you need an agentic loop.
On CCA-F scenario questions, the word "autonomous" almost always telegraphs an agentic loop. Phrases like "the agent investigates", "the agent resolves", "the agent iterates until", or "the agent gathers" signal that a loop is required. Single-turn framings use verbs like "classify", "summarize", "extract", or "format". Source ↗
stop_reason Field — Distinguishing tool_use from end_turn
The stop_reason field on every Claude response is the loop-driving signal. The agentic loop is, architecturally, a switch statement over stop_reason. Misreading this field is the single highest-frequency Domain 1 trap in the CCA-F community pool.
The Switch-Statement Mental Model
while true:
response = claude.messages.create(messages=history, tools=tools, ...)
history.append(response)
if response.stop_reason == "tool_use":
tool_results = execute_tools(response.content)
history.append({"role": "user", "content": tool_results})
continue # iterate
elif response.stop_reason == "end_turn":
break # Claude says it is done
elif response.stop_reason == "max_tokens":
handle_truncation(response)
break # or decide to continue with a follow-up
elif response.stop_reason == "stop_sequence":
break # a configured sequence matched; treat as termination
This skeleton is worth memorizing. Most real CCA-F agentic-loop questions test your ability to pick the correct branch behaviour for a given stop_reason value.
stop_reason is a field on every Claude Messages API response that indicates why Claude stopped generating. Its value determines what the agentic loop must do next: tool_use means Claude is requesting tool execution and the loop must continue; end_turn means Claude has decided the task is complete and the loop should exit; max_tokens and stop_sequence are structural interrupts that require explicit handling. Reading stop_reason correctly is the mechanical core of every agentic loop.
Source ↗
tool_use — Continue the Loop
When stop_reason == "tool_use", Claude's message content contains one or more tool_use blocks. Each block carries a name, an id, and an input object. Your loop must:
- Execute each
tool_useblock (your client code runs the tool or the Anthropic platform runs a server tool). - Package each result as a
tool_resultblock with the matchingtool_use_id. - Append a new user message to the history whose content is the array of
tool_resultblocks. - Call the Messages API again.
Seeing tool_use does NOT mean the loop is finished. On the contrary, tool_use is the only stop_reason that mandates continuation.
end_turn — Terminate the Loop
When stop_reason == "end_turn", Claude is signalling that it has completed its work on the current task and has no further tool calls to make. The final assistant message contains the user-facing answer. end_turn is the happy-path termination of an agentic loop.
tool_use and end_turn are the two primary stop_reason values that drive agentic-loop control flow. tool_use means Claude requested tool execution and the loop must continue; end_turn means Claude decided the task is complete and the loop should exit. A correct agentic-loop implementation branches on exactly this distinction. Community pass reports identify conflating these two values as one of the top five most-missed concepts on CCA-F Domain 1.
Source ↗
stop_reason Values Catalogue — tool_use, end_turn, max_tokens, stop_sequence
CCA-F expects you to recognize four stop_reason values and know the correct loop response for each.
tool_use
Claude has produced one or more tool_use blocks. The loop continues after you append matching tool_result blocks.
end_turn
Claude has decided it is done. The loop exits. The final assistant message is the answer.
max_tokens
Claude hit the configured max_tokens cap mid-response. The message is truncated — possibly mid-sentence or mid-tool_use block. max_tokens mid-loop is NOT a normal completion signal; it indicates that your output budget is too small for the task. Typical responses:
- Increase
max_tokensand retry. - Ask Claude to continue (append a short user message like "continue").
- Treat it as a failure and escalate.
stop_sequence
Claude's generation matched a string you passed in the stop_sequences parameter. This is most common in structured-output workflows where you pre-commit Claude to stopping at a known delimiter. Treat stop_sequence as termination for that structured step — but check whether your agentic loop should continue at a higher level.
Four stop_reason values, one sentence each:
tool_use— Claude wants to call tools; append tool_results and loop again.end_turn— Claude is finished; exit the loop.max_tokens— Output budget exhausted; truncated; decide to extend or abort.stop_sequence— A configured stop string matched; structured termination.
Distractor cue: if an answer claims end_turn indicates an error, or that max_tokens is a normal way for agents to finish work, it is wrong.
Source ↗
Loop Termination Conditions — Designing Safe Exit Criteria to Avoid Infinite Loops
end_turn is Claude's self-declared termination signal, but a production agentic loop must not rely solely on Claude's judgment. You design guard conditions as defense-in-depth.
Five Termination Guards Every Production Loop Should Implement
- Iteration cap — A hard maximum number of loop turns (for example, 20). Any loop without this will occasionally run forever.
- Wall-clock timeout — Maximum elapsed time across the entire loop.
- Token budget — Cumulative input + output tokens across all turns capped at a business-defined limit.
- Repeated-state detection — If Claude emits the same
tool_usewith identicalinputthree times in a row, the loop is stuck; abort. - Human escalation trigger — Conditions under which the loop voluntarily hands control back to a human (low confidence, sensitive action, out-of-scope request).
Why Safe Exits Matter
Claude is trained to be helpful and persistent. When a task is ambiguous or when tools return unhelpful errors, Claude may keep attempting new tool calls indefinitely. A loop with no iteration cap in a CI/CD context can burn through an API budget overnight. A loop with no repeated-state detection can alternate between two equivalent tool calls until tokens run out.
Every production agentic loop on CCA-F must include at least an iteration cap and one additional guard. The exam treats "add a loop iteration cap" as a baseline safety expectation; scenario answers that omit it are incorrect even when the rest of the design is sound. Community pass reports cite this as a frequent "close but wrong" pattern. Source ↗
Tool Result Injection — Feeding Observations Back as tool_result Messages
The observation phase of every loop iteration is mechanically implemented as appending a new user message whose content is an array of tool_result blocks. Getting the shape of this message wrong is a common implementation-level exam trap.
The tool_result Block Shape
Each tool_result block contains:
type: "tool_result"tool_use_id— theidfrom the correspondingtool_useblock in the previous assistant message.content— a string or array of content blocks (text, image) representing the tool output.is_error— optional boolean;truesignals that the tool call failed in a way Claude should react to.
One user Message, Many tool_result Blocks
When Claude emits multiple tool_use blocks in a single assistant message (parallel tool calls), your next user message must contain all of the matching tool_result blocks in a single message — one block per outstanding tool_use_id. Sending one at a time or interleaving with new user text breaks the API contract.
Errors as Structured Signals
When a tool fails, return is_error: true with a concise, actionable error string in content. This tells Claude the tool call did not succeed and gives it enough context to decide whether to retry, switch to an alternative tool, or escalate. Structured error responses (with explicit errorCategory and isRetryable fields inside the content) are a Domain 2 pattern but their consumption happens inside the agentic loop.
Every tool_use block in an assistant message must be matched by exactly one tool_result block (with the same tool_use_id) in the next user message. Missing or mis-matched IDs will either produce an API error or silently confuse Claude into re-emitting the same tool call. On CCA-F, any answer that omits the tool_use_id field on tool_result is wrong.
Source ↗
Message History Growth — Managing Accumulating Context Across Loop Iterations
Every loop iteration appends at least two messages to the conversation history (the assistant turn and the user tool_result turn). Long agentic loops can therefore accumulate significant context — a 30-iteration loop with moderate tool outputs easily fills tens of thousands of tokens.
Three Pressures Created by Growing History
- Cost — Every subsequent API call pays for the full history as input tokens on top of the new generation.
- Latency — Input processing time scales with context length.
- Attention degradation — Beyond a certain scale, Claude exhibits the "lost in the middle" effect where mid-context information is weighted less than start/end content.
Mitigation Strategies Inside the Loop
- Trim verbose tool outputs — If a tool returns a 50 000-token document, summarize or extract before storing the result in history.
- Clear superseded tool results — Newer tool results often subsume older ones; context-editing features (beta for Claude 4) can drop obsolete results.
- Use subagents — Delegate high-token sub-tasks to a subagent with its own isolated context (covered in task 1.2 / 1.3).
- Compaction / handoff — At a checkpoint, summarize the loop so far into a structured state blob and start a new session.
These techniques are covered in depth in the Context Management topics (Domain 5), but an agentic-loop architect must know they exist and when to invoke them.
Parallelism in Loops — Sequential Tool Calls vs Parallel Fan-Out Execution
When Claude emits multiple tool_use blocks in a single assistant message, you have two execution choices.
Sequential Execution
Run each tool call one after the other, waiting for each to complete before starting the next. Simpler. Required when tool A's output feeds tool B's input.
Parallel Execution
Run all tool calls concurrently. Faster. Safe when the tool calls are independent (different files, different database queries, different search terms).
When Claude Emits Parallel Tool Calls
Modern Claude models aggressively parallelize tool calls when they can identify that the calls are independent. A research agent looking up four topics will often emit four tool_use blocks in one message. Your application must be prepared to execute them in parallel and return all four tool_result blocks in the next user message.
Architectural Implication
The agentic loop is not strictly "one tool per turn." A single assistant turn may contain N tool_use blocks, and the corresponding user turn must contain N matching tool_result blocks. An implementation that serializes parallel calls into N separate turns wastes substantial latency and violates the standard pattern.
Agent SDK Loop Primitives — run(), stream(), and process() Entry Points
The Claude Agent SDK (formerly Claude Code SDK) provides an automated agentic loop so you do not have to hand-write the switch statement every time. CCA-F expects recognition of the three entry points and when to use each.
run() — Blocking Full-Loop Execution
run() runs the entire agentic loop from start to termination and returns the final result. Use when you want a synchronous, "give me the answer" shape and do not need intermediate events. Simplest. Appropriate for scripted tasks, batch jobs, and short-lived integrations.
stream() — Incremental Event Stream
stream() yields events as the loop progresses — assistant text chunks, tool_use proposals, tool_result appends, loop iteration boundaries. Use when you need to render partial output (chat UI), instrument mid-loop decisions, or run user interface updates while the agent is still working.
process() — Low-Level Programmatic Control
process() exposes per-message hooks, lets you inject arbitrary state transitions, and supports custom agentic-loop architectures (for example, a loop that pauses between turns to await external approval). Use when run() and stream() are too opinionated for your design.
Automated Loop vs Manual Loop — Trade-Offs
The SDK's automated loop handles the switch statement, tool_result construction, and termination conditions for you. The trade-off is reduced visibility into per-turn decisions and less flexibility for exotic architectures. A large fraction of production systems use run() or stream() and never touch process(). Writing a manual loop against the Messages API directly is appropriate when you need fine-grained control that the SDK hides — a common case in custom multi-agent orchestrators.
CCA-F scenario questions regularly ask you to choose between SDK entry points. The decision rule: pick run() for batch/non-interactive work, pick stream() when a human is waiting on incremental output, pick process() only when the other two cannot express the loop shape you need. Choosing the lowest-level primitive by default is a design smell — the exam penalizes over-engineering.
Source ↗
Error Handling Inside Loops — Retry, Skip, or Abort on Tool Failure
Tool calls fail constantly in production: network blips, rate limits, expired credentials, logical errors in tool inputs. A well-designed agentic loop has three response options for every tool failure.
Retry
Return a tool_result with is_error: true and a message indicating the error is transient (for example, "network timeout — retry after 1 second"). Claude will typically re-emit the same or a slightly-modified tool_use. Retry is appropriate when the underlying condition is expected to resolve itself.
Skip
Return a tool_result with is_error: true and a message indicating the specific request cannot be fulfilled but alternatives may work. Claude will then try a different approach. Skip is appropriate for permission errors on specific resources, malformed inputs for specific queries, or out-of-scope items.
Abort
Terminate the loop from the application side. Appropriate for non-recoverable errors (auth completely invalid, tool backend entirely down, critical guard condition tripped).
Structured Error Categorization
Pair every is_error: true response with a structured category (transient, business, permission, internal) and an isRetryable boolean. This is formally a Domain 2 pattern but its consumption lives in the agentic loop's error-handling branch. Generic error strings trigger Claude into long retry storms; structured errors let Claude make correct routing decisions.
Returning a tool error as a normal (non-error) text string without is_error: true is one of the most common architectural mistakes. Claude treats non-error tool_result content as legitimate observation data and may base further planning on fabricated facts. Always mark failures with is_error: true and keep the error message actionable.
Source ↗
Loop Observability — Logging tool_use and tool_result for Debugging
Agentic loops are notoriously hard to debug without instrumentation. Every CCA-F candidate should know the minimum observability surface for a production loop.
What to Log on Every Iteration
- Iteration index — which turn of the loop this is.
- stop_reason — the driving signal for the switch statement.
- Every tool_use block — tool name, input arguments, tool_use_id.
- Every tool_result block — tool_use_id, is_error, truncated content preview, latency.
- Token counts — input and output tokens per turn; cumulative totals.
- Timing — per-turn wall clock; cumulative wall clock.
Why All of These Matter
When an agent misbehaves in production, the first diagnostic is "what did Claude decide to do at each step?" The tool_use stream tells that story. The tool_result stream reveals whether the environment cooperated. Token and timing counts reveal economic and latency pathologies. Without this data, every debugging session starts from scratch.
PostToolUse and PreToolUse Hooks
The Agent SDK exposes PreToolUse and PostToolUse hooks that run before and after every tool execution. These are the clean place to attach logging, metrics, and policy checks. Hooks are formally a task 1.5 topic but their existence is part of the agentic-loop observability surface.
Plain-English Explanation
Abstract loop mechanics become intuitive when you anchor them to physical systems most candidates already know. Three very different analogies cover the full sweep of the agentic loop.
Analogy 1: The Kitchen Line — Perception, Reasoning, Action, Observation
Picture a head chef working the line during service. A ticket comes in (perception — "table 12 wants a medium-rare steak with rosemary potatoes"). The chef thinks through what is needed (reasoning — "I will need the grill for the steak, the oven for the potatoes, and garnish from the cold station"). The chef fires a command to each station (action — the tool_use blocks). Moments later the stations return plates, timers, and status updates (observation — the tool_result blocks). The chef looks at what came back and decides whether the dish is done or needs another step. The whole service shift is an agentic loop. tool_use is the chef shouting "fire the steak!". end_turn is the chef hitting the expo bell and saying "pick up". max_tokens is the kitchen running out of plates mid-service and having to stop. stop_sequence is the chef's manager walking in and saying "we are closing the kitchen at 10 pm sharp." The head chef never writes down a full plan in advance — they iterate one ticket at a time, observing what comes back from each station. That is exactly the shape of an agentic loop.
Analogy 2: The Detective Investigation — Epistemic Uncertainty Drives the Loop
A detective working a case starts with limited information — a victim, a location, a timeline. They cannot solve the case in one shot because they do not yet know what they do not know. They follow a lead (interview a witness, pull a phone record, visit a scene), observe what comes back, update their hypotheses, and follow the next lead. Sometimes a lead dead-ends (is_error: true), and they try a different angle (skip). Sometimes a phone call does not connect the first time (transient failure), and they call again (retry). The investigation is over when the detective is confident they have the answer (end_turn) or when the chief pulls the plug because the overtime budget is gone (iteration cap). The detective does not pre-plan every step; they react to observations. An agentic loop is a detective investigation where Claude is the detective, tools are the investigative actions, and your application is the precinct that supplies the budget and the rules.
Analogy 3: The Driving-Route Loop — When Single-Turn Is Not Enough
A GPS navigation system illustrates why an agentic loop beats single-turn inference whenever the world can change. A paper map (single-turn inference) gives you a route at departure time and assumes nothing about the drive will change. A live GPS (agentic loop) recomputes at every step: it observes your current position (perception), decides the next turn (reasoning), instructs you to turn (action), and waits to see whether you actually turned (observation). If traffic appears, it reroutes. If you miss an exit, it adjusts. If you reach the destination, it says "you have arrived" (end_turn). If you run out of gas (max_tokens), it cannot keep navigating no matter how good the map was. The paper map works for a one-time query with no uncertainty. The live GPS — the agentic loop — works when reality can surprise you between steps. CCA-F scenarios that contain surprises almost always require a loop, not a single-turn call.
Which Analogy Fits Which Exam Question
- Questions about the four-phase cycle → kitchen line analogy.
- Questions about why a loop is needed → detective investigation analogy.
- Questions about agentic loop vs single-turn → driving-route analogy.
Common Exam Traps
CCA-F Domain 1 consistently exploits five recurring trap patterns around agentic loops. All five are documented in community pass reports and appear disguised as plausible distractor choices.
Trap 1: Treating end_turn as an Error
end_turn is the correct, successful termination of an agentic loop — it means Claude has decided the task is complete and has nothing further to do. Distractor answers frame end_turn as "the model gave up" or "the loop failed." Both framings are wrong. end_turn is the happy path.
Trap 2: Treating max_tokens as Normal Completion
max_tokens mid-loop is a truncation signal, not a graceful finish. The response was cut off because the output budget was exhausted. Treating max_tokens as if it were end_turn — for example, returning the truncated content to the user as if it were the final answer — produces broken outputs. Correct handling is to extend the budget, ask Claude to continue, or abort with an explicit error.
Trap 3: Missing tool_use_id on tool_result
Every tool_result block must carry the tool_use_id that matches the originating tool_use block. Answers that describe tool_result injection without the ID field are wrong. Without the ID, the API rejects the message or Claude re-emits duplicate tool calls because it cannot see that the last ones were answered.
Trap 4: No Iteration Cap on Production Loops
A loop that terminates only on end_turn has no defense against runaway behaviour. Agents occasionally get stuck in repeated-state cycles, oscillating between two tool calls until tokens run out or bills explode. Every production agentic loop must have an explicit iteration cap plus ideally a wall-clock timeout. Answers that omit the cap are unsafe.
Trap 5: Choosing process() When run() Suffices
CCA-F penalizes over-engineering. A batch-mode extraction agent should use run(), not process(). A chat UI rendering partial output should use stream(), not process(). process() is for architectures the other two cannot express — custom pause-and-resume, external approval gates, novel multi-agent shapes. Picking the lowest-level primitive by default is a design smell.
Practice Anchors
Agentic-loop concepts show up most heavily in two of the six CCA-F scenarios. Treat the following as the architecture spine for scenario-cluster questions.
Customer-Support-Resolution-Agent Scenario
In this scenario, a customer-support agent ingests an inbound ticket, investigates by calling knowledge-base lookup tools, CRM query tools, and account-status tools, and either resolves the ticket autonomously or escalates to a human. The agentic loop is the backbone: each tool call observes a different system, and the sequence of calls cannot be planned in advance because it depends on what each lookup returns. Expect questions that test whether you correctly branch on stop_reason, whether you mark unreachable back-ends with is_error: true, and whether you implement an iteration cap plus a human-escalation trigger.
Developer-Productivity-With-Claude Scenario
In this scenario, a developer uses an SDK-driven agent to perform autonomous tasks across a large codebase — bug investigation, multi-file refactors, test authoring. The agent calls Read, Grep, Glob, Edit, and Bash tools in a long loop that can stretch to dozens of iterations. Expect questions that test tool_result injection shape, message-history management (when to compact, when to spawn a subagent), parallel tool call handling (Claude will frequently fan out file reads), and the correct SDK entry point (run() for scripted batch, stream() for an IDE UI). The multi-agent-research-system scenario also exercises agentic loops but shifts primary weight to task 1.2 (coordinator-subagent orchestration).
FAQ — Agentic Loops Top 6 Questions
What exactly is an agentic loop in the context of Claude?
An agentic loop is a controlled iterative process that repeatedly calls the Claude Messages API, feeding back tool execution results as tool_result messages, until Claude returns stop_reason: "end_turn" (natural termination) or your guard condition fires (iteration cap, timeout, token budget). The loop is the structural difference between a single-turn chatbot and an autonomous agent. CCA-F Domain 1 is almost entirely about getting this loop right, and every subsequent Domain 1 pattern (multi-agent orchestration, subagent spawning, handoffs) is an embellishment on top of it.
What is the difference between tool_use and end_turn as stop_reason values?
tool_use means Claude has proposed one or more tool calls and is waiting for your application (or the platform) to execute them and return tool_result blocks; the loop must continue. end_turn means Claude has decided the task is complete and has no further actions to take; the loop exits and the final assistant message is the answer. Confusing these two values is the most-cited CCA-F Domain 1 mistake. A correct loop is, mechanically, a switch statement on stop_reason that continues on tool_use and terminates on end_turn.
How do I handle a max_tokens stop_reason mid-loop?
max_tokens means Claude's response was truncated because the output budget was hit. This is NOT a normal completion. Three response options: (1) increase max_tokens and retry the last call; (2) append a short user "continue" message and let Claude finish in the next turn; (3) abort the loop with an explicit error if your business logic cannot tolerate truncation. Treating max_tokens as if it were end_turn — returning the truncated content to users as the final answer — is a common architectural bug and is directly tested on CCA-F.
When should I use the Agent SDK run() instead of stream() or process()?
Use run() for batch, non-interactive, scripted agent execution where you want a single "give me the final result" return value. Use stream() when a human is watching and you need to surface incremental output — chat UIs, live dashboards, IDE integrations. Use process() only when the other two cannot express your loop shape — custom pause-and-resume patterns, external approval gates mid-loop, exotic multi-agent orchestrations. The exam rewards picking the simplest primitive that fits; defaulting to process() out of flexibility-seeking is a design smell.
How do I prevent an agentic loop from running forever?
Implement at least two guards: (1) a hard iteration cap (typical values 15–30 turns) that exits the loop regardless of stop_reason; (2) one additional guard from the list of wall-clock timeout, cumulative token budget, repeated-state detection, or human-escalation trigger. Relying solely on end_turn is insufficient because Claude occasionally gets stuck oscillating between equivalent tool calls. CCA-F treats "add an iteration cap" as a baseline safety expectation; scenario answers that omit it are incorrect even when the rest of the design is sound.
How should I feed a tool error back to Claude inside an agentic loop?
Return a tool_result block with tool_use_id matching the original tool_use, is_error: true, and a concise, actionable error message in content. Ideally the error message includes a structured category (transient, business, permission, internal) and an isRetryable hint so Claude can decide whether to retry, try an alternative approach, or escalate. Returning a tool failure as a non-error string without is_error: true is the worst anti-pattern — Claude treats the content as legitimate observation data and may plan further actions on fabricated facts.
Further Reading
- Tool use with Claude — overview and agentic loop: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview
- Agent SDK overview: https://docs.anthropic.com/en/docs/claude-code/sdk/sdk-overview
- Handle tool calls — tool_result format: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
- Building effective agents — agentic loop reference: https://docs.anthropic.com/en/docs/build-with-claude/agentic-loop
- Writing tools for agents — Anthropic Engineering Blog: https://www.anthropic.com/engineering/writing-tools-for-agents
Related ExamHub topics: Multi-Agent Orchestration with Coordinator-Subagent Patterns, Task Decomposition Strategies, Session State, Resumption, and Forking, Agent SDK Hooks for Tool Call Interception.