ReAct: The Core Pattern
The foundational agent loop: decide when ReAct earns its cost over simpler patterns, understand the token math behind each iteration, learn the five ways it fails in production, and ship it with create_agent, cost controls, and eval.
Quick Reference
- →ReAct = the LLM alternates between reasoning (what should I do next?) and acting (tool calls) until it has enough information to respond — the LLM decides when to stop
- →LangGraph implements ReAct as a cycle: agent node (LLM) → tool node → agent node → ... → END, gated by tools_condition
- →Each loop iteration re-sends the full message history — a 5-tool-call chain sends 6x the system prompt in cumulative tokens
- →Tool descriptions are the LLM's only guide for tool selection — ambiguous descriptions cause wrong tool calls, not failed tool calls
- →Default recursion_limit is 25 (node visits, not tool calls) — at 2 nodes per tool call that's roughly 12 tool calls
- →create_agent (langchain.agents) is the production API — it adds middleware, checkpointing, and ToolRuntime over hand-built StateGraph
- →The three ways ReAct fails in production: infinite loops (no progress), wrong tool selection (plausible but incorrect results), and context overflow (too many tool results fill the window)
Should I Use ReAct?
ReAct earns its cost only when all three conditions hold
Most articles open with the mechanics. Start one step earlier: is ReAct the right pattern for this task? ReAct adds a loop, variable cost, and non-deterministic behavior. Half the time, a prompt chain or a deterministic workflow is cheaper and more reliable.
ReAct (Reason + Act) is the foundational agent pattern: the LLM generates a thought about what to do next, executes a tool action, observes the result, and repeats until it has enough information to respond.
| Situation | Why ReAct underperforms | Use this instead |
|---|---|---|
| Task steps are always the same | You're paying for dynamic routing through a fixed path | Prompt chaining |
| Only one tool, always called | The loop adds latency without adding decision value | Single LLM call with tool bound |
| Deterministic branching (if/else on inputs) | LLM is deciding what code could decide for free | Conditional edges without agent loop |
| Task requires delegation to specialists | ReAct is single-agent — it can't hand off work | Supervisor or Orchestrator-Worker |
| Pattern | LLM calls | Cost shape | Step count | Best for |
|---|---|---|---|---|
| Prompt chain | Fixed N | Predictable | Known | Sequential generation with gates |
| Router | 1 + routed | Low, fixed | 1–2 | Classifying and dispatching inputs |
| ReAct | Variable | Super-linear | Unknown | Dynamic tool use with unknown steps |
| Orchestrator-Worker | 1 + N workers | High, parallel | 1 + parallel | Delegating subtasks to specialized agents |
ReAct earns its keep when the number of steps and which tools to call are genuinely unknown at design time. If you can write a checklist of the steps before the agent runs, use a chain.