ReAct Pattern: Interleaving Reasoning and Action for LLM Agents › The Thought-Action-Observation Loop

Michael BrenndoerferFebruary 3, 20266 min read
Language AI HandbookAll chapters
Part 48 of 67Tool Use and Agents
Chapter 365ReAct Pattern: Interleaving Reasoning and Action for LLM Agents › The Thought-Action-Observation Loop
Reading section 3 of 14 · The Thought-Action-Observation Loop · 6 minSection 3 of 14 · 6 min

Book contents

Section 3 of 14 · 6 min read

ReAct Pattern: Interleaving Reasoning and Action for LLM Agents › The Thought-Action-Observation LoopOne section · Sections in this chapter3 / 14 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

The ReAct loop operates as a finite state machine with three distinct phases per iteration. Understanding each phase's precise role helps clarify why the pattern succeeds where simpler, linear approaches fail to maintain coherence across complex tasks. But before we drill into each phase, it helps to see the entire loop from the outside.

At the start of each iteration, the model receives the full trajectory so far (system prompt, the original question, all prior thoughts and actions plus their observations) as a single long prompt. It then generates a thought, followed immediately by an action. The system intercepts the action, executes it using the appropriate tool, appends the observation, and feeds the whole updated prompt back to the model. This continues until the agent calls finish or hits the maximum iteration limit.

The simplicity is deliberate. There is no separate planning module, no memory retrieval system, no explicit belief state. Everything the agent knows is in the context window, written out as text. This makes ReAct straightforward to implement and debug, and it uses the model's strongest capability: reasoning over text.

Thought: Explicit Reasoning

The thought phase generates a natural language string that serves multiple cognitive functions simultaneously. A well-constructed thought does several things at once:

  • State tracking: The model explicitly records what it has determined so far. For example: "I have confirmed that Ernest Hemingway wrote 'The Old Man and the Sea.'"
  • Gap identification: The model identifies what remains unknown. For example: "I still need to find his birthplace."
  • Action justification: The model commits to a next step and explains why. For example: "I should search for 'Ernest Hemingway birthplace' to find this."
  • Error acknowledgment: When something goes wrong, the thought registers it and proposes a correction. For example: "The previous search returned no relevant results; I should try a more specific query."

By forcing the model to articulate its reasoning explicitly in natural language, we create an audit trail that human operators can inspect and verify. This explicitness reduces hallucinated actions because the model must justify each tool invocation before executing it. If a thought does not justify the action that follows it, the generated trajectory looks incoherent compared to the few-shot examples, which creates implicit pressure toward sensible reasoning.

The thought also acts as a persistent scratchpad that accumulates across iterations, maintaining context and intermediate conclusions that might otherwise be diluted by attention mechanisms across a very long context. When the model generates thought t3t_3, it can look back at t1t_1, o1o_1, t2t_2, o2o_2, and everything else to reconstruct its current understanding. Writing things down is not just useful for humans.

Prompt Engineering for Thoughts

ReAct prompting typically uses few-shot examples showing the exact format expected:

Thought: [reasoning about current state]
Action: [tool_name]([parameters])
Observation: [result from environment]

The model learns to generate thoughts that logically precede and justify actions, creating a coherent narrative flow. This structured prompting is needed for reliable parsing: if the model generates a thought that runs into the action line without a clear separator, the parser breaks. Good few-shot examples prevent this by showing the expected structure consistently.

Action: Structured Tool Use

The action phase translates abstract thought into concrete, executable commands. As we covered in Function Calling, modern LLMs can generate structured JSON, domain-specific languages, or simple command syntax for tool invocation. In ReAct, the action must be parseable and executable by the environment without ambiguity.

The specific action space is task-dependent and must be clearly defined in the system prompt. For question-answering tasks, the action space might include:

  • search[query]: Web search or document retrieval to find factual information
  • lookup[keyword]: Search within previously retrieved documents for specific terms
  • calculate[expression]: Mathematical evaluation for numerical reasoning
  • finish[answer]: Terminate the session with the final response

The syntax must be rigid enough for reliable parsing but intuitive enough for the model to generate correctly. A useful heuristic: if you would have to read the format specification twice to understand it, the model probably will too. Simple bracket notation (tool[params]) works well for most tasks. JSON objects are better when parameters are complex or multiple arguments are needed.

One subtlety that matters enormously in practice: the action format must be consistent across all few-shot examples. Models are exquisitely sensitive to format inconsistency. If one example uses search["query in quotes"] and another uses search[query without quotes], the model will sometimes generate one format and sometimes the other, causing parsing failures. Pick one format and stick to it throughout all examples and the system prompt.

Observation: Environmental Feedback

The observation phase closes the loop by giving factual grounding from external systems. Unlike the thought and action phases, which are generated by the LLM, observations come from external systems: search APIs, databases, calculators, sensors, or software interfaces. The model reads observations but does not generate them.

Observations serve as ground truth anchors that prevent the model from drifting into hallucination or maintaining false assumptions. If the model mistakenly thinks "The capital of France is London" based on some confused reasoning, a search observation returning "Paris" creates immediate corrective pressure on the next thought phase. The model must reconcile its internal belief with the external fact, and in practice, models do update their beliefs when observations contradict their assumptions.

This grounding is the key feature that distinguishes ReAct from pure reasoning approaches. By tethering the reasoning process to verifiable external facts, we create a system that can correct its own misconceptions and build conclusions on solid foundations rather than parametric memory alone. The model's parametric knowledge becomes a heuristic for guiding retrieval, not a substitute for it.

There is an important engineering detail here: the observation should be presented to the model as coming from the environment, not from the model itself. The prompt format typically wraps observations in a way that makes this clear:

Thought: I should search for the population of Paris. Action: search[population of Paris] Observation: The population of Paris is approximately 2.1 million. Thought: I now have the population. I can provide the final answer.

The model sees this entire string in its context window. The Observation: prefix signals that the following text is authoritative environmental data, not model-generated content. This framing makes a meaningful difference: models tend to trust observations more than their own prior assertions, which is exactly the behavior we want.