T2 · Intermediate · 8 minMoving · Last reviewed: 2026-08-18Early draft

The ReAct Pattern — The Agent That Thinks Before It Acts

In one line · **ReAct makes the agent write a short reasoning step before every tool call and read the result before deciding the next one — so instead of acting blindly, it course-corrects as it goes.**

Glossary:ReActTool CallingTrace
TL;DR
  • An agent that fires off tools without thinking fails in three ways: wrong tool, wrong order, and completely ignoring the results coming back.
  • ReAct = Reasoning + Acting: think ("what do I need right now?") → execute a tool call → read the result (Observation) and adjust → think again... until the answer.
  • The thinking step isn't a luxury: when the model writes down what it needs before deciding, its choice of the next tool is grounded in information — not a guess.
  • ReAct is not a new invention layered on top of the agent loop — it's a prompt-level recipe for the same loop you already know, just out loud.
  • The cost is real: every Thought is billed in tokens. On multi-step tasks it pays for itself; on a single obvious tool call — save your money.
Why it matters

Picture this: an agent receives a two-part question and has 6 tools available. Without a thinking step, it does one of three things — all seen in real project reviews: it calls a tool that needs a parameter it hasn't fetched yet and gets an error, it answers half the question and ignores the other half, or — worst of all — it takes the error and retries the exact same call with the exact same inputs, because there is no moment where it asks itself "so what did that result change?"

Multi-step tasks are precisely the difference between a real agent and a chatbot with decorations. ReAct is the best-known and simplest pattern that makes those steps work — which is why "explain ReAct" has become a near-standard question in agent engineering interviews.

Before each step, the agent writes itself a line: "What do I need right now, and why?" After each tool, it reads the result and asks: "How does this change my plan?"

That thinking happens inside the conversation itself — ordinary text the model generates — not an external component or magic. Simply forcing the model to think in writing improves its decisions.

An analogy

A rushed repair technician opens the machine and swaps parts on hope: maybe the fan, maybe the power supply. Every wrong part costs time and money.

The skilled technician works differently: "The noise is coming from the fan area — I'll measure the temperature first" → measures → "Temperature is normal? Then it's not a cooling problem; let me check the bearings" → every step builds on the previous result.

Both have the same toolbox. The difference is that the first one just executes, while the second thinks → acts → observes → adjusts. ReAct turns your agent from the first into the second.

A real example

The question: "What's the price of product X, and is it in stock at the Riyadh branch?"

Without ReAct, the typical failure looks like this:

Action:  get_inventory(product_id=???, branch="Riyadh")
Observation: Error: product_id is required
Action:  get_inventory(product_id=???, branch="Riyadh")   ← same mistake again

With ReAct — same model, same tools:

Thought: The question has two parts: the price, and stock at the Riyadh branch.
         Both need the product ID first — I'll search for the product.
Action:  search_products(query="X")
Observation: [{id: "P-1042", name: "X", price: 249 SAR}]
Thought: I got both in nearly one shot: the price is 249 SAR,
         and I have the ID. All that's left is Riyadh stock.
Action:  get_inventory(product_id="P-1042", branch="Riyadh")
Observation: {branch: "Riyadh", in_stock: true, quantity: 7}
Thought: I have both parts of the answer. I can respond.
Answer:  Product X costs 249 SAR and is currently in stock at the Riyadh branch (7 units).

Note the second Thought: the model noticed that the price came back with the search result, so it didn't make a second tool call for the price. That is exactly the money the thinking saves.

How it works

The cycle has three beats, repeated until the model decides it's ready to answer:

1. Thought — think: the model writes a line or two: what's required, what I have, what's missing. 2. Action — act: based on the thought, it requests a specific tool call — and your code is what actually executes it. 3. Observation — observe: the tool result returns to the conversation and feeds raw into the next Thought.

Why does this move work at all? Two reasons:

  • Thinking improves tool selection. When the model writes "I'm missing the product ID" before choosing, the choice is conditioned on that sentence — so it picks search_products, not get_inventory. Without it, it picks whichever tool looks most like the question.
  • The Observation corrects the course. An empty result, an error, a surprising number — these are all information. In ReAct they have an official place in the cycle, so the plan adjusts instead of the agent barreling down the wrong track.

Diagram

        ┌──────────────────────────────────────────────┐
        │                                              │
        ▼                                              │
   ┌─────────┐      ┌─────────┐      ┌─────────────┐   │
   │ Thought │ ───► │ Action  │ ───► │ Observation │ ──┘
   │ "what   │      │ (tool   │      │ (read the   │
   │  next?" │      │  call)  │      │  result)    │
   └─────────┘      └─────────┘      └─────────────┘
        │
        │  "I have everything I need"
        ▼
   ┌─────────┐
   │ Answer  │
   └─────────┘

The arrow looping back from Observation to Thought is the whole pattern: the result is read before the next decision. If that arrow is broken in your system, you have an agent that executes — not an agent that thinks.

For developers

First thing to nail down: ReAct is the agent loop you already know — perceive → decide → act → observe — with one difference: the decide step becomes explicit text the model writes instead of happening implicitly inside the model. So ReAct isn't a new architecture to build — it's a prompting style for the same loop.

Second, for historical context: the original paper (2022) predates native tool calling in the APIs — they wrote Action: search[...] as plain text and parsed it. Today the Action comes out structured from the API itself, and the Thought is text preceding the call. The syntax changed — the idea is intact.

Third: Thoughts are an internal channel. Their natural home is the trace and the logs — and they are the best debugging gift you'll get: when the agent goes wrong, you read its reasoning and learn why it went wrong, not just that it did.

The code

The whole loop, with any provider and any SDK — read it as runnable pseudocode:

SYSTEM = """You are a store assistant. Solve the task step by step.
Before every tool call, write ONE short "Thought:" line stating
what you need next and why. After each tool result, reconsider
your plan before acting again. Thoughts are internal — never
show them to the user. Answer only when you have everything."""

steps = 0
while steps < MAX_STEPS:                        # always cap the loop!
    response = llm.generate(messages, tools=TOOLS)
    messages.append(response)                   # keep the Thought in context
    if not response.tool_calls:
        break                                   # model produced the Answer
    for call in response.tool_calls:
        result = execute(call)                  # your code does the acting
        messages.append(tool_result(call, result))   # the Observation
    steps += 1

Three things to watch:

  • `MAX_STEPS` is not a detail — it's the guardrail that stops "The agent that never stops" challenge from happening to you in production.
  • The Thought is kept in context (messages.append(response)) — so earlier reasoning stays in front of the model and gets built on.
  • The Observation comes back in full, including error messages — the model won't fix a mistake it can't see.
Practice

Exercise (20 minutes): Take a simple agent you have — or your Research Agent project's agent if you've started it — and run it on a two-part compound question, twice: once with no thinking instructions, and once after adding the line "Before every tool call, write one short Thought line" to the system prompt. Compare the traces: number of calls, wrong calls, and total tokens. The difference you'll see with your own eyes beats any explanation.

Common mistakes
#❌ Wrong✅ Right
1Thoughts leak to the user: "Thought: the user probably means..." shows up in chatSeparate the channels: reasoning goes to the trace; the user sees a short status ("Checking inventory...")
2A loop with no cap: the agent spins and spins while the bill counts upMAX_STEPS + a per-task cost cap — from day one, not after the first incident
3Novelistic thinking: the model writes an essay before every call and you pay for itSpecify in the system prompt: "ONE short Thought line" — a line that steers the decision, not a diary entry
4Truncating Observations: you send the model "Error" with no detailsPass the full error message — it is the raw material for course correction
5ReAct on everything: even "what's the weather?" gets a Thought and an ObservationOne obvious tool = direct call. Save the ceremony for tasks that earn it (see "When not to")

Misconceptions

1) "ReAct is the same thing as reasoning models" — ❌ Reasoning models think internally before responding. ReAct is a pattern at your application level: it structures thinking between tool calls and makes it part of the trace. They complement each other — and if you're running a strong reasoning model, you can lighten the explicit Thought format and leave the thinking internal. Experiment and measure.

2) "If it's thinking, the answer must be right" — ❌ A Thought can be beautifully argued — and wrong. Written reasoning improves the odds; it doesn't guarantee the outcome. That's why evaluation is still mandatory, and a trace with convincing reasoning needs review like any other trace.

Cost considerations

Every Thought is billed twice: as output when written, and as input on every subsequent call — because the full context is sent each time. Let's run the numbers on our inventory question (3 cycles + answer):

> 💸 Numbers subject to change *(Volatile fragment — illustrative pricing; check your provider's current rates)*: $3/million input tokens and $15/million output tokens.

ItemCalculationCost
One direct call (if the task had been simple)Input 900 + Output 150~$0.005
ReAct with four callsCumulative input: 900 + 1,150 + 1,400 + 1,650 ≈ 5,100 → $0.015; Output: 3 cycles × ~80 + answer ~150 ≈ 390 → $0.006~$0.021

So ReAct here is roughly 4× the cost of a single call. At 20,000 questions a month: ~$420 instead of ~$105.

But make the right comparison: a multi-step task doesn't get solved at all in one call — so that 4× is the price of the job getting done, not a luxury. The correct engineering question isn't "is ReAct expensive?" — it's "does this task actually need multiple steps?" If not, go back to mistake #5 above.

When to use it
  • A compound question with parts: each part needs a different tool, and the order matters.
  • Tools that depend on each other's results: the search result is the input to the next query.
  • An environment with unpredictable results: web search, external APIs, possibly incomplete data — someone has to "read and adjust."
  • You want intelligible traces: written reasoning = dramatically easier debugging — you see why the agent chose what it chose.
When NOT to use it
  • One obvious tool: "How many vacation days do I have left?" = one known call. A Thought here is tokens for nothing — skip the ceremony.
  • Steps known in advance and fixed: if you can draw the flow on paper before running it, build a plain workflow — cheaper, more reliable, easier to test.
  • Latency-critical paths: every ReAct cycle = a full LLM call. On a hot user path, every Thought is felt.
  • No tools at all: plain conversation or direct text generation — no actions means no ReAct.

💡 Tip: The practical rule: are the steps decided by the results? ReAct. Are the steps known before running? Workflow. Not sure? Start with a workflow — and revisit the "Agents vs. workflows vs. chains" concept if you get stuck.

LET'S BUILD ITDone reading — now build it yourself.Research Agent — Stage 2: the search loop
Further learning
  • Inside BuildAI (in order): Planning intro → Agent reliability → Agent cost management.
  • The original paper: *"ReAct: Synergizing Reasoning and Acting in Language Models"* — Yao et al., 2022. Read it as the history of the idea, not as an implementation guide — it predates native tool calling, and you'll notice how much of the pattern today's APIs have absorbed.
The ReAct Pattern — The Agent That Thinks Before It Acts · BuildAI