What You Will Learn
- How reasoning, action, and observation alternate.
- Why observations change decisions.
- How production loops are bounded.
How to read the evidence
The 87% / 11% / 2%, 1.4-second, 14-second, 19-tool-call, and later 95% / 5% figures are presented by the linked FutureAGI article. The page does not provide an independently reproducible dataset or primary company post-mortem. Read them as a publisher-reported case, not a universal ReAct failure rate or guaranteed improvement.
Every pattern so far — chaining, routing, parallelization — followed a predefined path. ReAct is where this course crosses into Module 1’s other category: the model decides its own next step, based on what it observes, rather than following a script written in advance.
The architecture
Observe
↓
Reason
↓
Choose Action
↓
Execute Tool
↓
Observe Result
↓
Continue
This loop repeats until the model decides it has enough information to produce a final answer. Nothing about the number of iterations, or which tools get called in what order, is fixed in advance — that’s the entire point, and it’s precisely what makes this pattern genuinely more flexible, and genuinely harder to predict, than everything covered so far.
Where this comes from
It’s worth knowing the real origin precisely, and being honest about what’s research versus what’s modern practice.
ReAct — Reasoning and Acting — was introduced in a 2022 paper, ReAct: Synergizing Reasoning and Acting in Language Models, by Yao et al. The original mechanism: one model emits a Thought, picks an Action, receives an Observation from that action’s result, and repeats — Thought, Action, Observation — until it emits a Final Answer. A runtime parses the Action line, calls the actual tool, and feeds the Observation back into the next prompt. (FutureAGI, Agent Architecture Patterns in 2026)
It’s worth being precise about a genuinely important distinction here: modern, proprietary tool-using agents from major labs do not necessarily expose a literal “Thought/Action/Observation” text format the way the original research paper described it.
Structured tool calling in 2026 typically returns validated JSON matching a defined schema, not free text a runtime has to parse. (SitePoint, The 2026 Guide to Building Autonomous Systems) The underlying loop — reason, act, observe, repeat — is what modern agents actually inherited from ReAct. The specific text format of the original paper is a research artifact, not something you should assume any given production system literally reproduces.
Why this distinction is worth holding onto specifically
It’s worth being explicit about why this matters beyond historical accuracy. Claiming that a modern proprietary agent “uses ReAct” is a genuinely different, weaker claim than showing its actual documented architecture. Plenty of current tool-using systems share ReAct’s fundamental shape — think, act, observe, repeat — without ever citing the paper or exposing anything resembling its literal format.
Treating “reasons and calls tools iteratively” as automatically equivalent to “implements ReAct” would violate exactly the verified-versus-interpreted distinction this course committed to in Module 1. The honest framing: ReAct is the research origin of a now-common architectural shape, and a great many current systems share that shape — which is a real, defensible claim — without every one of them being a literal implementation of the 2022 paper’s specific mechanism.
Fully quantified production story
This is worth the deepest attention in this module, because it’s a genuinely rare thing: a complete, precise, before-and-after account of ReAct actually succeeding, actually failing, and being fixed — with real numbers at every stage.
A real refund-processing agent, built as a ReAct loop, showed this measured behavior in production:
- 87% of requests: resolved in 1.4 seconds, across three tool calls. Genuinely fast, genuinely clean.
- 11% of requests: the model got stuck comparing two refund policies in circles — burning through 14 seconds and 19 tool calls before eventually resolving.
- 2% of requests: never finished at all. The loop hit its token budget and was cut off mid-reasoning.
(FutureAGI, Agent Architecture Patterns in 2026)
Read the middle case precisely, because it’s the genuinely instructive one. The model wasn’t broken — it was reasoning, honestly, the entire time. It just had no structural mechanism forcing it to stop comparing two ambiguous policies and commit to a decision. Nineteen tool calls is nineteen honest attempts to resolve real ambiguity, not nineteen random guesses.
What fixed it
The team’s actual fix: swap the same underlying logic into a plan-then-execute shape — the exact pattern this course covers next, in Module 6. Instead of letting the model decide its next action at every single step, a planner emits the full sequence upfront — “check policy, look up order, calculate refund, escalate if over $500” — and an executor runs each step exactly once.
The measured result after the change: 95% of requests now finish in 2.1 seconds, and the remaining 5% escalate cleanly to a human, rather than looping. The source’s own conclusion is worth taking seriously: “The architecture change saved more latency and tokens than any prompt tuning would.” (FutureAGI)
This is worth holding as this module’s central lesson: ReAct’s flexibility is a genuine strength for tasks where the right next step genuinely depends on what was just observed — and a genuine liability for tasks where the ambiguity that causes looping was never going to be resolved by more observation, only by an upfront decision the model was never given the structure to make.
Three named failure modes
It’s worth knowing these precisely rather than as a vague sense that “loops can go wrong”:
Unbounded loop length — the model gets stuck retrying the same tool with the same arguments, exactly the refund-policy example above. Token blowup on long trajectories — every Thought and Observation appends to the growing context, so a long-running loop’s cost compounds with each iteration, not just its risk. Poor recoverability when downstream re-planning is needed — because there was never an explicit plan in the first place, there’s nothing to revise when the situation genuinely changes mid-task. (FutureAGI)
This isn’t one team’s isolated experience. A genuinely independent, real, documented incident: an agent called a broken tool 400 times in five minutes — the same unbounded-repetition failure mode, observed in a completely separate production system. The same independent source names the harder-to-catch variant precisely: “Silent failures — the agent produces confident output while making no real progress. Tool calls are happening. Nothing is actually changing. The hardest to catch.” (Agentic Loops Explained, Data Science Dojo)
The honest mitigation, stated precisely: “A step budget, no-progress detection, and a retry-with-different-tool rule mitigate but do not eliminate these failure modes.” Worth taking that phrasing seriously — these are damage-control measures, not a genuine fix for the underlying structural issue the refund-agent case study actually resolved by changing architecture entirely.
Current product built specifically to address this
It’s worth knowing this problem is significant enough that it’s driven real, current product features, not just guidance. Claude Code’s /goal feature, shipped May 12, 2026, lets a user set an explicit completion condition, with the agent working autonomously across multiple turns until that condition is genuinely met — tracking elapsed time, turns, and tokens as it goes. The key mechanic worth knowing precisely: “a separate evaluator model checks whether the goal condition is met at the end of each turn, and only stops the loop when it passes.” (Data Science Dojo)
This is worth recognizing directly: a separate evaluator model checking completion is precisely Module 8’s Evaluator-Optimizer pattern, now shown as the real, shipped, production answer to exactly the looping risk this module has spent its centerpiece describing.
Where ReAct fits well
It’s worth being fair to the pattern, because the failure story above is specific to one kind of ambiguity, not a universal indictment. Real, current production use spans several genuinely different domains:
Research and analysis — searching documentation, querying databases, and synthesizing findings, where each search result genuinely informs what to search for next. Customer support grounding — an agent that queries an internal knowledge base and observes the actual policy text before answering, specifically to avoid hallucinating a shipping policy rather than looking it up.
Conditional workflow automation — an agent processing expense reports, checking receipt amounts against policy limits, and flagging exceptions only when an observation actually falls outside a threshold. (DEV Community, 5 Agent Design Patterns Every Developer Needs to Know in 2026)
Industry surveys describe ReAct as remaining one of the most widely deployed agent patterns, specifically in applications where interpretability and genuinely adaptive tool use are worth more than the cost of the additional LLM calls the loop requires. (DEV Community)
Notice what distinguishes these successful cases from the refund-agent failure: in each one, the next observation genuinely changes what should happen next. A search result changes the next search query. A policy lookup changes the answer. A receipt amount changes whether escalation is needed. The refund-policy comparison failed specifically because more observation wasn’t actually resolving anything — the ambiguity was structural, not informational.
The trade-offs, stated together
It’s worth summarizing the genuine costs against the genuine benefits explicitly, rather than leaving them scattered across this module.
| Benefit | Real cost | |
|---|---|---|
| Flexibility | Adapts to genuinely novel situations without redesign | Harder to predict what the agent will actually do |
| Tool selection | Chosen dynamically, based on real context | A wrong tool choice compounds — the next step reasons over a bad observation |
| Token usage | Only pays for steps genuinely taken | Every Thought and Observation accumulates in context, uncapped by design |
| Unpredictability | Genuinely adaptive to edge cases | The refund agent’s 11% shows this can mean genuinely unpredictable cost and latency, not just unpredictable output |
None of this makes ReAct a worse pattern than a fixed workflow in general — it makes it a pattern with a genuinely different risk profile, one this module’s case study showed paying off for 87% of a real production workload and failing expensively for 13%.
Production observability for a ReAct loop
It’s worth knowing how a real ReAct trace actually gets instrumented, since Module 1 established this course won’t teach patterns as framework features — observability is genuinely part of the architecture, not an afterthought.
Current practice uses OpenTelemetry’s GenAI semantic conventions with specific, named attributes: gen_ai.agent.name to distinguish which agent produced a given span, gen_ai.agent.id to correlate every span from one request together, and gen_ai.operation.name to distinguish a reasoning step from an actual tool execution. (DEV Community, ReAct, Plan-and-Execute, or Reflection?)
This matters directly for diagnosing exactly the failure this module’s case study described — without this instrumentation, the difference between the 87% resolving in three clean tool calls and the 11% looping through nineteen would be invisible in an unstructured log, indistinguishable until someone happened to notice the aggregate latency numbers looked wrong.
What this looks like in code
Before reading the syntax, follow the execution flow: identify the incoming state, the component making the decision, the function doing the work, and the condition that returns a result or stops the loop. The code is a small teaching model of the pattern, not hidden framework magic.
def react_loop(query: str, tools: dict, max_steps: int = 10) -> str:
context = [f"Question: {query}"]
for step in range(max_steps):
thought, action, action_input = reason(context)
context.append(f"Thought: {thought}")
if action == "final_answer":
return action_input
observation = tools[action](action_input)
context.append(f"Action: {action}[{action_input}]")
context.append(f"Observation: {observation}")
# Hit max_steps without resolving — exactly the 2% case above
return escalate_to_human(context)
max_steps is the direct, concrete answer to this module’s token-blowup and unbounded-loop warnings — a hard ceiling, not a suggestion. Notice the loop’s final fallback is escalation, not an error — precisely the “5% escalate cleanly” outcome the refund agent’s fixed architecture achieved, applied here as a genuine safety net even within a pure ReAct implementation.
Interview-relevant framing
Q: When does ReAct genuinely outperform a fixed, predefined workflow?
Ans: When the correct next step genuinely depends on what the previous step actually observed — a search result changing the next query, a policy lookup changing the answer. A real production case study showed this precisely: a refund agent’s ReAct loop resolved 87% of requests cleanly in under two seconds, but 11% degenerated into the model looping for fourteen seconds across nineteen tool calls, comparing two ambiguous policies without ever being structurally forced to commit. That failure wasn’t about missing information — more observation wasn’t resolving anything. ReAct helps when observation genuinely informs the next decision, and hurts when the ambiguity was never going to be resolved by looking harder.
Q: How would you prevent a ReAct agent from looping indefinitely in production?
Ans: With a hard step budget and no-progress detection as the baseline — but I’d treat those as damage control, not a real fix, since the same underlying ambiguity that caused the loop is still there. The actual fix in a real, documented case was architectural: switching the task to a plan-then-execute shape, where a planner commits to a fixed sequence upfront instead of letting the model re-decide its next move at every step. That change took the same task from 87/11/2 percent clean-resolve/loop/timeout to 95/5 percent clean-resolve/clean-escalation — a genuinely larger improvement than tuning the ReAct prompt would have produced.
A third question worth preparing for:
Q: How would you decide, at design time, whether a task genuinely needs ReAct’s flexibility or would be better served by a fixed plan?
Ans: By asking whether the correct next step genuinely depends on information that can only be known after observing the previous step’s result, or whether the actual steps are knowable in advance even if their specific values aren’t. A research task where each search result should inform the next query genuinely needs that flexibility. A refund calculation with a fixed number of checks — verify policy, look up order, calculate amount, escalate above a threshold — doesn’t; every one of those steps is knowable in advance regardless of what any individual check returns. The refund-agent case study is exactly this second shape misclassified as the first, which is precisely why switching to a fixed plan fixed it.
Common Misconception
Incorrect idea: ReAct means an agent should keep trying until it succeeds.
Why it is incorrect: Production loops need limits for steps, time, cost, permissions, and repeated actions.
Key takeaways
- ReAct’s real research origin is Yao et al.’s 2022 paper — a Thought/Action/Observation loop, repeated until a final answer. Modern production agents inherit the underlying reason-act-observe cycle, not necessarily the original paper’s literal text format.
- A real, fully quantified production case study showed exactly where this pattern succeeds and fails: 87% of requests resolved cleanly in 1.4 seconds, 11% degenerated into 14-second, 19-tool-call loops over genuinely ambiguous policy comparisons, and 2% hit the token budget without resolving at all.
- The real fix for that failure was architectural, not a prompt tweak: switching to plan-then-execute took the same task to 95% clean resolution and 5% clean escalation — a larger, measured improvement than iterating on the ReAct prompt achieved.
- Three named failure modes — unbounded loop length, token blowup, and poor recoverability — can be mitigated with step budgets and no-progress detection, but these are damage control, not a structural fix for the underlying ambiguity.
- ReAct genuinely earns its place when the next observation actually changes what should happen next — research, grounded policy lookups, conditional workflow checks — and struggles when the model’s uncertainty is structural rather than informational.
- Production observability for a ReAct loop uses specific OpenTelemetry GenAI attributes —
gen_ai.agent.name,gen_ai.agent.id,gen_ai.operation.name— without which the difference between a clean resolution and a degenerate loop is invisible until aggregate latency numbers look wrong.
Module 6 covers the pattern the refund-agent case study actually switched to, and the direct structural alternative to everything ReAct’s failure modes exposed: Plan-and-Execute.
- Author
- TechByteByByte Editorial Team
- Reviewed by
- TechByteByByte Admin
- Published
- Last reviewed