examlab .net The most efficient path to the most valuable certifications.
In this note ≈ 27 min

Agentic Loops for Autonomous Task Execution

5,400 words · ≈ 27 min read ·

Agentic loops for autonomous task execution on CCA-F: perception-reasoning-action-observation cycle, stop_reason values, tool_use vs end_turn, loop termination, Agent SDK primitives, error handling, observability, exam traps, and FAQ.

Do 20 practice questions → Free · No signup · CCA-F

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 pattern where Claude alternates between proposing a tool_use and receiving its observation back as a tool_result, iterating until a termination condition fires. Without the loop, Claude is a text completion; with it, Claude is an agent.

The Four-Phase Cycle The Four-Phase Cycle PERCEPTION messages in: prompt + tool_result REASONING tool_use | end_turn | stop ACTION your app executes the tool OBSERVATION tool_result appended to messages Agentic Loop end_turn → exit
Figure 1 — The four-phase agentic loop. Each iteration is one trip around the circle; the loop only exits through the end_turn branch off the Reasoning node (or through a guardrail trip).

The loop is explicit — your code runs the while-loop that drives Claude, fundamentally unlike a chatbot whose conversation terminates after each response. The loop keeps running until Claude emits end_turn, your guardrail cuts it off, or 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.

When to Choose Each Architecture When to Choose Each Architecture Single-Turn Inference USER CLAUDE REPLY one prompt, one response, no iteration • summarize this • translate • extract entities Agentic Loop USER CLAUDE tool_use TOOL tool_result end_turn REPLY many turns, tool calls in between, exits on end_turn • research a topic • fix a bug • browse and book a flight
Figure 2 — Single-turn vs agentic-loop architectures. The shape of the work decides which pattern fits: stateless transformations stay single-turn; tasks that branch on intermediate results need the loop.

Single-Turn Inference

A one-shot prompt → one-shot response. Use it when the task can finish with information already in the prompt, has no external state to query, and produces output of a known shape (prose, JSON, label).

Agentic Loop

Required whenever the task has epistemic uncertainty — Claude can't know the complete answer at message time and must acquire information or take actions to make progress. Loops fit reading files, querying databases, calling APIs, and any open-ended task ("fix this bug", "resolve this ticket") whose step count can't be predicted up front.

Decision Heuristic

If removing the tools still lets Claude complete the task, you don't need a loop. If removing them makes the task impossible, you do.

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 content holds one or more tool_use blocks (each with name, id, input). Execute each, package the output as a tool_result block with the matching tool_use_id, append them as a new user message, call the API again. tool_use is the only value that mandates continuation.

end_turn — Terminate the Loop

When stop_reason == "end_turn", Claude is done — final assistant message holds the user-facing answer. This is the happy-path termination.

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.

stop_reason Decision Tree stop_reason Decision Tree What to do for each value Claude returns Inspect stop_reason stop_reason = "tool_use"
Execute tool, append tool_result, continue loop
stop_reason = "end_turn"
Exit loop. Return final response to caller.
stop_reason = "max_tokens"
Truncated. Bump max_tokens or summarize and retry.
stop_reason = "stop_sequence"
Custom stop hit. Inspect stop_sequence field for which one.
Figure 4 — The four stop_reason values and their canonical loop responses. Memorising this table is the single highest-yield CCA-F preparation for Domain 1 questions.

tool_use

Claude produced one or more tool_use blocks. Append matching tool_result blocks and the loop continues.

end_turn

Claude decided it's done. Exit the loop; the final assistant message is the answer.

max_tokens

Claude hit the configured max_tokens cap mid-response — possibly mid-sentence or mid-tool_use block. NOT a normal completion: your output budget is too small. Either bump max_tokens and retry, append a "continue" user message, or treat as failure and escalate.

stop_sequence

Claude's generation matched a string from stop_sequences. Most common in structured-output workflows where you pre-commit Claude to a known delimiter. Treat as termination for that structured step — but the higher-level agentic loop may still continue.

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.

Loop Termination Conditions Loop Termination Conditions Every loop must define all four exit paths stop_reason="end_turn" max_iterations hit tool error token budget exceeded
Success: return final assistant message
Guardrail tripped: log + escalate
Abort: surface error to user
Cost cap: summarize and exit
Loop running
Figure 3 — The four exit paths every production agentic loop must define. Only the end_turn exit is a clean success; the other three are safety valves you design before shipping.

Five Termination Guards Every Production Loop Should Implement

  1. Iteration cap — A hard maximum number of loop turns (for example, 20). Any loop without this will occasionally run forever.
  2. Wall-clock timeout — Maximum elapsed time across the entire loop.
  3. Token budget — Cumulative input + output tokens across all turns capped at a business-defined limit.
  4. Repeated-state detection — If Claude emits the same tool_use with identical input three times in a row, the loop is stuck; abort.
  5. 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. On ambiguous tasks or unhelpful tool errors, it may keep retrying indefinitely — an uncapped loop in CI/CD can burn an entire API budget overnight, or oscillate 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 — the id from the corresponding tool_use block in the previous assistant message.
  • content — a string or array of content blocks (text, image) representing the tool output.
  • is_error — optional boolean; true signals 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

  1. Cost — Every subsequent API call pays for the full history as input tokens on top of the new generation.
  2. Latency — Input processing time scales with context length.
  3. 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 vs Parallel Tool Execution Sequential vs Parallel Tool Execution Same three calls — half the wall-clock if you fan out Sequential t=0 ──────► t=Σ tool_a (2s) tool_b (3s) tool_c (1s) 0s 2s 5s 6s Total: 6s Parallel Fan-Out t=0 ──────► t=max tool_a (2s) tool_b (3s) tool_c (1s) 0s 1s 2s 3s Total: 3s (max of three)
Figure 5 — Sequential vs parallel tool execution. The wall-clock saving (6s → 3s in this example) compounds across loop iterations and is the single biggest latency lever in production agents.

Sequential vs Parallel

Sequential — run each tool call after the previous finishes. Required when tool A's output feeds tool B's input.

Parallel — run all calls concurrently. Faster, and safe whenever the calls are independent (different files, different DB queries, different search terms).

Architectural Implication

The loop is not "one tool per turn." A single assistant turn may carry N tool_use blocks, and the matching user turn must hold N tool_result blocks. Modern Claude models aggressively parallelise when they detect independence, so an app that serialises parallel calls into N separate turns wastes the latency saving Figure 5 makes obvious.

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

Runs the loop start-to-finish and returns the final result. Synchronous, "give me the answer" shape. Best for scripted tasks, batch jobs, and short-lived integrations.

stream() — Incremental Event Stream

Yields events as the loop progresses — assistant text chunks, tool_use proposals, tool_result appends, iteration boundaries. Use when a human is watching: chat UIs, instrumented mid-loop decisions, real-time UI updates.

process() — Low-Level Programmatic Control

Per-message hooks, arbitrary state transitions, custom loop shapes (e.g. a loop that pauses for external approval). Reach for it only when run() and stream() cannot express your design.

Automated vs Manual

The SDK's automated loop handles the switch statement, tool_result construction, and termination guards for you. You trade per-turn visibility and exotic-architecture flexibility for that. Most production systems live on run() or stream(); a manual loop against the Messages API is appropriate only when you need finer control than the SDK exposes — typically inside 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-Language 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

Related ExamLab topics: Multi-Agent Orchestration with Coordinator-Subagent Patterns, Task Decomposition Strategies, Session State, Resumption, and Forking, Agent SDK Hooks for Tool Call Interception.

Official sources

More CCA-F topics