The ReAct loop

ReAct stands for "Reasoning + Acting." It's the canonical agent pattern and, if you build an agent without thinking about it, this is probably what you'll end up with anyway. The model thinks about what to do, takes a single action, looks at the result, thinks again, and loops. That simple alternation between thought and action is what turns a chatbot into an agent. This page is about how it actually works, why it matters, and why it's harder to do well than it sounds.

The loop, in its simplest form.

Here's the entire pattern in four steps:

~ reason → act → observe → repeat ~

In code, the whole thing is about six lines:

while not done:
    thought = model.reason(context)         # what should I do next?
    action  = model.choose_tool(thought)    # which tool, with what args?
    result  = tool.execute(action)          # run it
    context += (thought, action, result)    # feed it all back in

The genius is the interleaving. The model doesn't produce a big plan and then execute it. It thinks one step, takes one step, sees the result, thinks again. This means the agent can adapt. When a tool returns something surprising, the next thought takes that into account. When a page doesn't have the info the agent expected, it searches somewhere else. Exploratory tasks work with ReAct because the agent is always reacting to what just happened.

Why ReAct became the default.

Three properties, and they all matter.

~ why ReAct wins for most tasks ~

Adaptive means the agent responds to reality as it unfolds. The plan doesn't need to be right upfront; the agent can course-correct mid-task. For most real-world work (research, debugging, exploration), the plan you'd have to write upfront is worse than the plan the agent builds incrementally.

Modular means you can add or remove tools without rewriting the agent. The loop stays the same; only the tool list changes. This is why ReAct and MCP are such good partners: MCP adds tools to the available pool and ReAct consumes them transparently.

Inspectable means the reasoning trace is explicit. Every step has a thought, an action, and an observation. When the agent does something you didn't expect, you can scroll back and see exactly why. This is the difference between debugging an agent and guessing at it.

Where ReAct breaks, and what to do about each.

ReAct is the default, but it's not bulletproof. There are five classic failure modes. If you build more than a couple of agents, you'll hit all of them. Here they are with fixes.

~ the five classic ReAct failure modes ~

Each one is a specific pattern you'll recognize after you've shipped a few agents. The fixes are small and well-understood. But you have to actually put them in place, none of them come free.

Designing the system prompt for a ReAct agent.

A ReAct system prompt has a specific shape that works. Most problems with ReAct agents trace back to one of these five elements missing from the prompt:

  1. Role and goal. What is this agent? What is it trying to accomplish? Be specific. "Research agent" is too vague; "Research agent that produces a two-page competitor analysis in markdown" is much better.
  2. Available tools. List them. For each tool, give a description and an example of when to use it. Bad descriptions cause tool confusion; good descriptions are the cheapest quality improvement you can make.
  3. Reasoning structure. Tell the agent how to think. Something like: "Before each tool call, state (1) what information you still need, (2) which tool you'll use, (3) why that tool is the right one." This keeps the reasoning trace useful for debugging and pushes the model toward better decisions.
  4. Stop conditions. When is the agent done? "Stop when you've gathered enough to answer" is weak. "Stop after 5 tool calls, or when you have three citations for the claim, whichever comes first" is strong.
  5. Error recovery. Tell the agent what to do when a tool fails. "Retry once with reformulated input. If still failing, state the error clearly and ask the user for guidance." Without this, agents either give up too early or hammer failing endpoints forever.

A concrete example: a research agent prompt.

ROLE: Research agent. Answer the user's question using web_search and fetch_url.

TOOLS:
- web_search(query)  : find relevant URLs
- fetch_url(url)     : read a specific page

REASONING (before each tool call, state):
1. What do I still need to know?
2. Is this a broad search or a specific URL fetch?
3. Call the tool.
4. After: did the result help? What's next?

STOP when:
- You can answer the user's question with citations
- You've made 5 tool calls without substantial new info
- The user's question is outside the scope of these tools

ON TOOL ERROR:
- Retry once with reformulated input
- If still erroring, state the failure and what you'd need to proceed

This prompt works because it tells the agent the shape of each step (1-4) AND the exit conditions. When you run it, you'll see the agent narrate its reasoning, call tools, and stop at the right time. That's a ReAct agent.

When ReAct isn't the right pattern.

Two cases argue for switching or layering:

But for the 80% case (exploratory work, unknown depth, adaptive behavior), ReAct is the default and the right choice. Start here; graduate to other patterns only when you have a concrete reason to.