Best on a larger screen — the animation and controls have more room to breathe.
Inputs

ReAct Loop

The ReAct loop is the agent pattern that interleaves reasoning with tool use: a language model alternates Thought → Action → Observation, writing what it needs next, asking a tool to fetch it, and reading the result before reasoning again. Retrieval answers what the weights alone cannot; grounding each thought in a fresh observation leaves a checkable audit trail.

The picture to keep is a researcher with a legal pad. The model has no memory beyond a growing transcript — everything it "knows" mid-task is literally the text on the pad: the question, its own thoughts, its actions, and whatever the tools wrote back. Each turn it re-reads the whole pad and adds its next lines. A good researcher's notes cite their sources; the whole drama of this lesson is what the notes do and don't contain.

Everything the model says in this lesson is real: each policy's run was recorded from claude-opus-5-5 and curated — one run selected per policy for the phenomenon it shows, with not a word edited. The tool side re-executes live against the same knowledge base, so every observation on screen is the search function's actual return value.

How the ReAct Loop Works

The loop body is three moves under a turn budget. The model continues the transcript with a Thought: line — the next step standing between it and the answer — followed, in the same completion, by an Action: line, a structured command like search["Mara Voss"] or finish[1974]. A finish ends the loop with an answer. A tool call is executed by the runtime — not the model — and the result is appended as an Observation: line.

That division of labor is load-bearing. The model only ever writes text; the runtime parses the action string, runs the tool, and appends what came back. In the animation, every query and every result crosses a dashed boundary through a small runtime gate — the model's context on the left, the world on the right. A model that "executes its own tools" is a model writing its own observations, which is hallucination with extra steps.

Grounding falls out of the ordering. A thought written after an observation can quote it: the recorded run's "The film's director is Mara Voss" is copied off a retrieved page, not recalled from training, and the animation draws a link from each observation to the thought standing on it. The lesson runs three policies against the same two-hop question — Which year was the director of Aurora Run born? — over the same four-page knowledge base. The first page is a deliberate trap: it is the entry for the novel Aurora Run, and it dangles a decoy in exactly the answer's format — the novelist's "born 1951" — one clause away from the fact that actually matters, "the 2011 film was directed by Mara Voss."

ReAct Loop Step by Step

The default run is the full ReAct policy — the recorded model run, beat for beat. Page numbers refer to the knowledge base as the animation labels it (1–4).

  1. Start. The pad holds one line: the question. The knowledge base sits unread on the right.
  2. Turn 1 — Thought. "First I need to find out who directed Aurora Run." A sub-goal, not an answer.
  3. Turn 1 — Action. search["Aurora Run"] is written onto the pad. Nothing has run yet; an action is just text until the runtime executes it.
  4. Turn 1 — Lookup. The query crosses to the knowledge base and page 1's title matches.
  5. Turn 1 — Observation. The result crosses back: "Aurora Run is a 1998 novel by Henrik Dahl (born 1951); the 2011 film was directed by Mara Voss." A real fact is on the pad — along with the decoy year.
  6. Turn 2 repeats the cycle one level deeper: the thought "The film's director is Mara Voss; Henrik Dahl, born 1951, wrote the novel, so I need Voss's birth year." names the decoy and sets it aside in writing, quoting the right clause — watch the solid link into the observation above it — and search["Mara Voss"] retrieves page 2: "Mara Voss (born 1974) is a Norwegian film director."
  7. Turn 3 — Thought. "Mara Voss directed the 2011 film and was born in 1974." Anchored, again, to the page just read.
  8. Turn 3 — Action. finish[1974] ends the loop.
  9. Verdict. 1974 is correct, and every hop is traceable to a retrieved page.

Now switch policies. Reason only thinks twice and never calls a tool — and the recorded model does something more honest than the textbook hallucination: it admits, in writing, that it doesn't reliably remember the film or its director, then — the answer format forcing a specific year — calls its answer "a low-confidence guess for a typical contemporary director" and guesses 1975. Close, and still wrong — and a final reveal beat lights pages 1 and 2, the truth that sat unconsulted the whole time. Act only runs the same two searches as ReAct and answers 1974 — correct. It even walks past the "born 1951" decoy. So look at its transcript gutter: not a single grounding link, because not a single thought is on the record. The reasoning that chose "Aurora Run", extracted "Mara Voss", and skipped the decoy all happened inside the model, invisibly — and the closing beat points at that silence. The signal to track across all three runs is the link structure: solid links into every ReAct thought after the first, dashed red thought-on-thought chains in reason-only, and a bare gutter in act-only.

Why Agents Loop Instead of Plan

The question is two-hop on purpose. Hop two — search["Mara Voss"] — cannot even be phrased until hop one's result is on the pad, because the name comes from the retrieved page. A plan written entirely up front would need to contain a fact the planner doesn't have yet. Looping is not a stylistic preference; it is what lets each decision condition on evidence that did not exist a turn ago.

So what do the written thoughts buy, if act-only gets the same answer? Not correctness — auditability. A chat model re-reads the whole pad every turn, so on a task this small its silent reasoning crosses both hops just fine (across the act-only runs we recorded while building this lesson, the model usually crossed both hops with no visible struggle). What act-only cannot do is show its work. When ReAct skips the decoy year, the thought that skipped it is on the pad, linked to the page it quotes; when act-only skips it, you learn nothing about why — and the day it answers 1951, there is no written sub-goal to point at and no reasoning step to debug — only the tool calls and observations it left behind. Reason-only fails in the opposite direction: no tool ever touches the world, so even a model honest enough to say "I cannot verify this" is reduced to a forced guess. One policy can't check the world; the other leaves its reasoning unwritten.

The loop's bill is worth knowing: one LLM call per turn (it writes the thought and the action together), at most one tool call, and a context that grows linearly — every line on the pad is re-read on every call, so long episodes get more expensive per step. Here the budget is max_turns = 4 and each recorded episode finishes inside it. The thoughts add tokens to every call, not extra calls — that is the price of the audit trail, and on a two-hop toy task it buys you no extra accuracy. The bet ReAct makes is that as tasks get longer and messier, the written sub-goals start paying for themselves twice: once as scaffolding the model itself conditions on, and once as the only record you can inspect afterward.

One framing to carry out of this lesson: the loop belongs to the agent, not to you. Your code supplies the tools, parses each action, and feeds the observation back — the harness — but it never decides what to think or which tool to reach for. That judgment is the model's, learned in training, and the "runtime" box this lesson draws deliberately makes none of those choices. Confusing the two is the classic agent-building mistake: people try to engineer the reasoning with branching glue code, when choosing the next step is the model's job and the harness's job is to execute, observe, and enforce limits.

Edge Cases

  • A search that misses returns "No matching page found." — a normal observation, not an error, and a competent agent responds by reformulating the query. None of the three recorded runs needed to; the protocol handles it the same way either way.
  • The budget runs out. If no finish arrives within max_turns, the loop exits without an answer. The recorded episodes all finish in time.
  • A malformed action — text the runtime can't parse as a tool call — has no handler in this minimal trace. Real runtimes must catch it and feed an error observation back so the model can recover.
  • Grounding is not infallibility. ReAct anchors thoughts to what the tool returned; if the knowledge base itself were wrong, the agent would be confidently wrong with excellent citations. Grounding buys traceability.

Common Mistakes

  • Assuming the agent has state. There is no hidden memory — only the pad. Anything not written into the transcript is gone by the next turn.
  • Letting the model write its own observations. The runtime executes tools. Skip that boundary and you have rebuilt reason-only, hallucinations included.
  • Reading "same answer" as "same agent". Act-only matching ReAct on a two-hop toy task does not generalize to your production task — and even where it does, you are shipping a system whose reasoning you cannot inspect, replay, or debug.
  • Reading confidence as correctness — or hedging as safety. The reason-only run hedges honestly and still ends in a wrong, specific year, because the output format demands one. What makes an answer trustworthy is its anchors, not its tone.
  • Checking finish after the tool call. The guard must run first — otherwise the loop ships the final answer to the search tool as if it were a query.

A Note on Simplification

The world here is deliberately tiny: two tools, a small knowledge base, a task two hops deep. The transcripts are real — each policy's run was recorded from claude-opus-5-5 with no words edited, and the tool side re-executes live — but a production ReAct agent adds machinery this lesson skips: tool schemas in the system prompt, a parser hardened against malformed actions, retries, token budgets, and transcripts that need summarizing long before they get interesting. The loop you watched is the whole skeleton; production is that skeleton plus armor.