If you are building an agent, you are almost certainly building on one of two loops — and confusing them is why teams over-engineer cheap tasks and under-engineer the ones that actually need a retry. ReAct reasons and acts inside a single attempt. Reflexion retries the same task and writes itself a note about what went wrong. The question is never which is smarter. It's whether you have a way to tell success from failure, and whether you can afford the second attempt.

Here is the short version before the detail: use ReAct as your default; add Reflexion only around tasks where a cheap, reliable success signal exists.

ReAct: reason and act, in one pass#

ReAct — Synergizing Reasoning and Acting in Language Models, Yao et al., ICLR 2023 — interleaves two things a plain LLM does separately. Instead of reasoning in one block and then acting, it runs a repeating loop:

The reasoning traces let the model plan, track progress, and handle exceptions; the actions let it pull in facts it doesn't have. On the paper's interactive benchmarks, ReAct beat imitation- and RL-based methods by an absolute 34% success rate on ALFWorld and 10% on WebShop using only one or two in-context examples, and it was competitive with chain-of-thought on knowledge tasks like HotpotQA and FEVER while being far less prone to hallucinating its way to an answer.

The important property for your architecture: ReAct does not learn between attempts. Every run starts clean. Within a run it self-corrects — a bad observation can prompt a better next thought — but if the whole attempt goes wrong, nothing carries forward to the next one. That is exactly what makes it cheap: one pass, no memory to maintain, low latency. For most tool-using agents, that is the correct default.

Reflexion: fail, reflect, retry the same task#

Reflexion — Language Agents with Verbal Reinforcement Learning, Shinn et al., NeurIPS 2023 — adds an outer loop around an actor. It has three parts:

On the next attempt at the same task, that note is fed back into context. The agent tries again, now carrying the lesson. Crucially, no model weights change — the authors call it verbal reinforcement learning. Improvement is stored as text, not gradients, which is why Reflexion works with any capable frozen model behind an API.

Reflexion doesn't make the model smarter. It makes the attempt smarter, by letting a failed run leave a note for the next one.

Where a clean success signal exists, this pays off. The paper reports 91% pass@1 on HumanEval, above the 80% GPT-4 baseline it compares against, and gains on ALFWorld and HotpotQA over repeated iterative steps. The reason it works on code is that code has a free, reliable evaluator built in: the unit tests either pass or they don't.

The decision: it's about the signal and the budget#

The two loops aren't rivals — Reflexion usually wraps a ReAct actor. (They're also not the only two: ReAct vs Plan-and-Execute vs Reflexion puts a third loop shape next to these, and the reflection step itself has variants worth knowing — see Reflexion vs self-refine vs critic vs LATS.) The real decision is whether to pay for the outer loop, and that comes down to two prerequisites ReAct doesn't have:

  1. A reliable success/failure signal. Reflexion reflects on failure. If you can't cheaply tell whether an attempt failed — no tests, no task-completion check, no verifiable answer — the reflection step has nothing trustworthy to work from, and a noisy evaluator will happily write down the wrong lesson and reinforce it on every retry. This is the failure mode to fear.
  2. A retry budget. Reflexion runs the task multiple times and grows its memory each round. That's more tokens, more latency, more money. On a task that only needs one competent pass, you're paying for attempts you don't need.

What it means for how you ship: start with ReAct everywhere. It's the cheaper loop and it's enough for the bulk of tool-using work — retrieval-augmented QA, web navigation, general agents that need one good attempt. Then find the specific tasks in your product that have a cheap, honest correctness check — code that must pass tests, an environment with a clear done-state, an answer you can verify — and wrap those in a Reflexion-style retry with a hard cap on attempts. That cap matters: unbounded retries are how a self-improving loop turns into a latency and cost sink.

The mistake isn't picking the "wrong" one. It's paying Reflexion's price on a task with no signal to reflect on — or running bare ReAct on the one task where a single automated retry would have saved the run.