Cruxly › AI engineering › Agentic Systems
The Agent Loop in Depth: ReAct, Plan-and-Execute, Reflection and Stop Conditions
per-step reliability compounds, context cost grows quadratically, and the stop decision never belongs to the model alone
Open the interactive lessonPrompt: "We want an agent that triages a customer complaint: look up the order, check the policy, draft a reply, and issue a refund under Rs 2,000. Should this be an agent or a workflow? If an agent, show me the loop, tell me how it stops, and tell me what you would look at when a 40-step run goes wrong."
40 minutes first. Put numbers on two things: how often a 12-step run succeeds when each step is 97 percent reliable, and what a 10-turn run costs when every turn re-sends the whole transcript. The trap is drawing a box called "agent" with an arrow back to itself; the interviewer wants the stop conditions, the checkpoints, and the arithmetic.
Workflow or agent: choose the simplest thing that works
The first design decision is whether the model chooses the next step at all. Anthropic's Building Effective Agents article draws the line this way: workflows are systems where models and tools are orchestrated through predefined code paths, and agents are systems where the model dynamically directs its own process and tool use. The article's advice is to start with the simplest solution, usually a direct API call, and add structure only when it demonstrably helps, and it warns that frameworks can hide the prompts and responses you need to see when debugging (the Frameworks, Protocols and Durable Execution lesson takes that up).
The article lists five workflow patterns, and an interviewer expects you to name them and to say what each buys.
- Prompt chaining. Split a task into a fixed sequence of calls, each consuming the last one's output, with optional code gates in between. You trade latency for accuracy because each call has an easier job.
- Routing. A classifier call sends the input to a specialised prompt or model, for example cheap questions to a small model and refund disputes to a careful one.
- Parallelisation. Either sectioning (independent subtasks run at once) or voting (the same task run several times and compared).
- Orchestrator-workers. A central call decides the subtasks at run time and delegates them, which suits work where you cannot list the subtasks beforehand, such as changes spread over an unknown number of files.
- Evaluator-optimizer. One call produces, another critiques against stated criteria, and the loop repeats.
An agent is the case where even the sequence is unknown, and it pays for that freedom in three ways: latency (each turn is a full model call), cost (see the token arithmetic below), and variance (two runs of the same ticket can take different paths). Use the complaint example. Order lookup, policy check, draft and refund is a four-step sequence you can write on a whiteboard, so it is a chain. The honest agentic part is smaller: "the customer's message is ambiguous, so find out what they bought," which may need two lookups or six. Give the loop to that step and keep the rest in code.
@@ 1 | Can you list the steps now? If yes, build a chain or a router. Fewer moving parts means a failed run points at one prompt.
@@ 2 | Is only one step open-ended? Wrap that step in a bounded loop and leave the rest as ordinary code.
@@ 3 | Is the whole path unknown, with a checkable end state? Now you have an agent. Budget it, gate its irreversible actions (see Guardrails for an Agent That Takes Real Actions), and measure it.
:::warn Autonomy you cannot verify is liability, not a feature The article's own condition for agents is ground truth from the environment at each step: a tool result, a test run, a database row. If nothing in the world can tell the loop it went wrong, a loop has no way to correct itself, and you have built an expensive random walk. :::
ReAct, plan-and-execute and reflection: what each one is and how it fails
Every agent loop is the same cycle: the model emits a thought or a plan, calls a tool, reads the result, and decides again. The names differ in where the reasoning sits and what you check.
ReAct (Yao et al., ReAct: Synergizing Reasoning and Acting in Language Models, arXiv 2210.03629) interleaves reasoning traces with actions: think, act, observe, think again. The paper reports that on HotpotQA and FEVER, using a simple Wikipedia API, it reduced hallucination and error propagation compared with chain-of-thought alone, and that on ALFWorld and WebShop it beat imitation and reinforcement learning baselines by absolute success-rate margins of 34 and 10 points, using only one or two in-context examples. Those are the paper's 2022-era numbers on its own benchmarks; treat them as evidence for the pattern, not as a forecast for your task. Modern tool-calling APIs have absorbed the pattern: the "thought" is often hidden or a thinking block, the "action" is a structured tool call, and the "observation" is the tool result you append.
Plan-and-execute writes the whole plan first and then runs it step by step, possibly with a cheaper model for the execution. Reflection adds a critic pass: the model reviews its own output, or a separate call does, and revises.
Each has a characteristic failure, and naming it is what separates an answer from a recital.
- ReAct fails by drifting and looping. With no plan, every turn re-decides locally. The model can chase an interesting observation away from the goal, or call the same search with the same arguments three times because each result looks almost useful. Fix with a repeated-action detector and a visible goal restated in the system prompt.
- Plan-and-execute fails by brittleness. Step 3 assumes step 1 found a file that it did not, and the executor carries on with a plan the world has already falsified. Fix by re-planning when an observation contradicts an assumption, and by letting the plan carry a check per step rather than a bare to-do list.
- Reflection fails by agreeing with itself. A critic that sees only the draft and no outside signal tends to approve what it just wrote. A critique is worth money only when it is anchored to something that can fail: a test run, a schema validator, a retrieved source, a calculation. This is the same ground-truth rule as in the previous section, applied to the review step.
- Tree or parallel search fails by cost. Branching five ways at three levels is 5 + 25 + 125 = 155 model calls before you have picked an answer. Use it where the answer is cheap to verify and the first try is often wrong, such as generated code with unit tests.
:::key Verified October 2026 The ReAct claims above are from the arXiv abstract for 2210.03629 (v3, March 2023, ICLR camera-ready), read October 2026. The success-rate margins are the authors' own, on ALFWorld and WebShop, under 2022 conditions. :::
A practical hybrid, and the one most production systems settle on, is a short plan that the loop is allowed to revise: the model writes three to six steps, executes them ReAct-style, and rewrites the remaining steps whenever an observation contradicts them. It keeps the goal visible without freezing the path.
The arithmetic of reliability: why long runs fail, and what a checkpoint buys
Per-step reliability compounds, so a run is much less reliable than any single step in it. If each of 12 steps succeeds independently with probability 0.97, the whole run succeeds with 0.97^12 = 0.694. At 6 steps it is 0.833, at 20 steps 0.544, at 40 steps 0.296. A 97 percent step sounds excellent and still loses three runs in ten at 12 steps. This is the same shape as pass^k in Guardrails for an Agent That Takes Real Actions, applied inside a single run instead of across runs.
A verification checkpoint stops an error from travelling. Split the 12 steps into three segments of four, and after each segment run a check that looks at the world (does the order exist, does the draft cite the policy clause, did the refund API return a transaction id). Assume the check catches a failed segment 80 percent of the time and the segment can be retried once.
@@ 1 | One segment on its own 0.97^4 = 0.885. It fails with probability 1 - 0.885 = 0.115.
@@ 2 | With detection and one retry The segment succeeds first time (0.885), or fails (0.115), is caught (0.8), and the retry succeeds (0.885): 0.885 + 0.115 x 0.8 x 0.885 = 0.885 + 0.081 = 0.966 (0.9665 unrounded, written 0.967 below).
@@ 3 | Three segments in a row 0.9665^3 = 0.903. (Cubing the rounded 0.967 gives 0.904; carry the unrounded value.)
Three cheap checks move the run from 69.4 percent to 90.3 percent. Notice the assumptions, because an interviewer will probe them: failures are independent, the check never raises a false alarm, and a retry is as good as the first try. In real systems failures cluster (a wrong assumption at step 2 poisons every later step), so a retry from the same wrong state helps less than the arithmetic suggests. That is why the check should reset to a known-good state, not merely re-ask.
What it costs. Suppose each check is a model call that re-reads a 6,000-token transcript: three checks add 18,000 input tokens, which at $2 per million tokens is $0.036. The retry cost is paid only on the 11.5 percent of segments that fail, so the expected extra segment work is small. Against that you avoid a 30.6 percent failure rate. Where a check can be a plain function (an assertion on the tool output, a schema validation, a test run) it costs nothing in tokens, so prefer code checks and keep model-based checks for what code cannot judge.
:::warn A checkpoint that cannot fail is theatre "Review your work so far" asked of the same model, with no new information, will usually pass. Put the check where the world can contradict it: a database read-back, a diff applied cleanly, a total that reconciles. :::
Token growth: why a ten-turn loop costs far more than ten calls
Every turn re-sends the whole transcript, so input tokens across a run grow with the square of the number of turns. The model is stateless: turn n carries the system prompt, the tool definitions, and every earlier message and tool result. Use a small loop with assumed figures: a fixed prefix of 4,000 tokens, 1,500 tokens added per turn (a tool result plus the model's reply), and an assumed $2 per million input tokens.
- Turn 1 sends 4,000 tokens. Turn 2 sends 5,500. Turn 10 sends
4,000 + 1,500 x 9 = 17,500. - Ten turns total
10 x 4,000 + 1,500 x (0 + 1 + ... + 9) = 40,000 + 67,500 = 107,500input tokens. At $2 per million tokens that is $0.215. - Twenty turns total
80,000 + 1,500 x 190 = 365,000tokens, or $0.73. Doubling the turns multiplied the input by365,000 / 107,500 = 3.4.
Output tokens are extra and linear. The quadratic term is the transcript, and it is why long agent runs are an input-cost problem. Two levers act on it. The first is Prompt Caching: Paying for the Same Tokens Once: the prefix of turn n equals the whole of turn n-1, so almost all of each request is a cache read. The coding-agent lesson later in this topic works the exact numbers on a 40-step session. The second is to shrink what goes in: truncate huge tool results, summarise or compact old turns, and push self-contained subtasks to a sub-agent that returns a short summary, all of which Multi-Turn Conversation State and Context-Window Limits covers.
Measure cost per completed task, not cost per run. Failed runs cost money too. If a 10-turn run costs $0.215 and succeeds 69.4 percent of the time (reusing the 12-step figure for simplicity, with both numbers assumed), the cost per success is 0.215 / 0.694 = $0.31, 44 percent above the headline run cost. If verification lifts the success rate to 90.3 percent, the cost per success falls to 0.215 / 0.903 = $0.24 even before you subtract the cheaper human escalations. That is the metric to put on the dashboard (see Observability and Cost Governance for LLM Systems), and it connects reliability engineering to unit economics in one number.
Stopping: budgets outside the model, and a finish decided by code
An agent that decides alone when it is finished will sometimes decide wrongly in both directions. Too early: it writes "refund issued" without calling the refund tool. Too late: it keeps searching for a better answer until the money runs out. The fix is a set of limits enforced by the harness, which the model cannot negotiate with.
- Turn budget. A hard cap on loop iterations. Building Effective Agents lists stopping conditions such as a maximum number of iterations as a standard way to keep control.
- Token or spend budget. A running total of input plus output, with a stop at a threshold, because a few giant tool results can blow a run that is within its turn limit.
- Repeated-action detector. Hash
(tool, arguments)and stop, or force a different action, on the third identical call. It catches the loop that budgets only catch after the damage. - No-progress detector. If the last N turns produced no new information (no new file read, no new fact written to the scratchpad), escalate to a human rather than continue.
- Wall-clock timeout. For user-facing runs, a deadline that returns a partial result and a handoff.
Completion is a property of the world, so check it with code. For the complaint agent, "done" means the reply draft exists, the refund API returned a transaction id, and the amount is at most Rs 2,000. The harness checks those three facts. If the model claims completion and the checks fail, the harness returns that failure as the next observation and the loop continues; if the budget is exhausted first, the run ends as failed with a reason, never as success.
:::key Verified October 2026 In the Claude Agent SDK the loop runs until the model replies with no tool calls, and you cap it with max_turns (which counts tool-use turns only) and max_budget_usd. A run that hits a cap returns a result with subtype error_max_turns or error_max_budget_usd rather than a normal success. The budget is checked after each response arrives, so spend can pass the cap by up to the cost of one response plus any sub-agents still running. Source: the Agent SDK "How the agent loop works" page, read October 2026. Other frameworks name these differently; the point is that the cap lives in the harness. :::
Make the exit reasons a closed list in your logs: completed_verified, max_turns, max_spend, repeated_action, no_progress, timeout, blocked_by_policy, needs_human. A dashboard that shows 14 percent of runs ending in repeated_action tells you which prompt to fix this week; a dashboard that shows only "success" and "error" does not.
State, resumability, and debugging a 40-step run
Decide where each piece of state lives before the first run, because the context window is the worst place for most of it. There are three homes.
- In the context. The goal, the recent turns, the current plan. It is expensive (the quadratic term above) and it is lost on a crash or a compaction.
- In a scratchpad the agent writes to. Notes, a running to-do list, facts found. It survives compaction because the loop can re-read it, and it keeps the context small.
- In a database or event log the harness writes to. Every tool call, argument, result and token count, with a run id. It survives crashes and is what you debug from. It is also what lets a failed run resume rather than restart, which the Frameworks, Protocols and Durable Execution lesson takes further.
Debug by finding the first wrong turn, not the last one. A failed 40-step transcript usually ends in an obviously bad action, but that is a symptom. The cause is the earliest turn after which the run could no longer succeed: a tool result misread at turn 7, a wrong assumption stated at turn 9 that every later step built on. A routine that works:
@@ 1 | Mark each turn: advance, neutral, or regress Read the thought and action against the observation that came back. A regress is a turn whose action contradicts evidence already in the context.
@@ 2 | Find the earliest turn the run could not recover from Replay the transcript up to turn k with a corrected action and see if it succeeds. If it does, k was the cause.
@@ 3 | Classify the cause Tool contract unclear (fix the description, see Designing Tools an Agent Can Actually Use), prompt gap, a tool returned too much and the model lost the thread, or a genuine capability limit.
@@ 4 | Turn it into a test Add the transcript as a regression case, and score the fix on repeated trials, because a single passing run proves little when pass^k matters.
Anthropic's engineering write-up on evaluating agents makes the same point from the other side: read the transcripts, and failures should seem fair, which means a failure should trace to something you can fix and not to a broken grader. Cost belongs in the same view. For every trace, log tokens in and out per turn, and flag a run whose turn-30 input is more than five times its turn-5 input as a context problem to fix before it becomes a bill.
How to say it in the interview
"First I would ask whether the path is knowable in advance. Order lookup, policy check, draft, refund is a fixed sequence, so I would build it as a workflow of four model calls and plain code, and only give the model a loop for the one step where the next action truly depends on what it finds. In the loop I would cap turns, tokens and repeated identical calls, and I would decide that the task is finished with code that checks the world, not with the model saying done. Twelve steps at 97 percent each succeed only 69 percent of the time, so I would put a verification checkpoint every four steps, which lifts it to about 90 percent for three extra checks. And I would log every turn so that when a run fails I can find the first wrong turn instead of reading the last one."
Checklist
- Wrote down why this task needs a model-chosen path, and used a chain or router wherever the steps are known
- Every agent step has an observation that can contradict the model (tool result, test, validator, read-back)
- Hard caps on turns, tokens or spend, repeated identical calls, no-progress turns and wall-clock time, enforced by the harness
- Completion decided by code that checks the world, with exit reasons from a closed list
- Computed end-to-end reliability as per-step probability to the power of steps, and put a real check every few steps
- Retries restart from a known-good state, not by re-asking from the poisoned one
- Modelled input tokens as a quadratic in turns and enabled prompt caching on the stable prefix
- Track cost per completed task, not cost per run
- State split across context, a scratchpad and a durable event log with a run id
- Failed traces are labelled turn by turn, the first unrecoverable turn is found, and the trace becomes a regression test scored over repeated trials
Related lessons
- Designing Tools an Agent Can Actually Use
- Agent Memory: Working, Episodic, Semantic and Procedural, Without the Rot
- Frameworks, Protocols and Durable Execution: MCP, A2A and Long-Running Agents
- MCP Servers, Prompt Injection, and Tamper-Evident Audit
- Guardrails for an Agent That Takes Real Actions
- Coding Agents and Computer-Use Agents: Harness, Sandbox and Verification