Lesson 4.2: Reasoning patterns: ReAct, reflection and self-correction
Learn the main ways agents reason: thinking before acting, ReAct, reflection, voting across samples and verification, and what each gains and costs.
By the end of this lesson you will be able to describe the main reasoning patterns used in agents, explain what the ReAct loop adds to plain reasoning, work out when asking a model to critique its own answer helps and when it hurts, calculate how voting across several samples raises accuracy, and decide when a check by a tool is worth more than any amount of extra thinking. You will see that taking the majority of five independent answers lifts a 70 per cent accurate model to 83.7 per cent, that the same trick makes a 40 per cent accurate model worse, and that a self-critique step lifts an 80 per cent agent to 87.6 per cent while a check by a tool lifts it to 93.6 per cent. You should have read Lessons 1.2 and 4.1, which cover the loop and planning. A little Python helps for the code example. The mathematics is probability and a short sum.
Planning decides what to do. Reasoning is how the agent thinks while doing it: how it weighs a result, chooses a tool, spots a mistake and decides whether it is finished. Language models can be prompted, or trained, to reason in different ways, and each has a different effect on accuracy, cost and speed. This lesson covers the patterns that matter in practice. None is magic, and most are a trade: more model calls for more reliability. Knowing the trade is what lets you spend only where it pays.
Reasoning before acting
The simplest pattern is to let the model think before it answers. Asked a question that needs several steps, a model that writes out its working first is usually more accurate than one that jumps straight to the answer. This is called chain of thought: the model produces intermediate steps in text, and each step is available to condition the next. For arithmetic, logic and multi-part judgements, the improvement can be large.
In an agent, this shows up in two ways. Some models have a built-in reasoning mode in which they produce a hidden or visible stretch of thinking before they reply, often with a setting for how much thinking to allow. Others are simply prompted: "Think through the problem step by step, then give your answer." In both cases, thinking costs tokens and time. A model that thinks for 800 tokens before each of ten steps spends 8,000 extra tokens a run, and delays every step.
Two cautions are worth knowing from the start.
More thinking is not always better. For a simple lookup, thinking adds cost and sometimes introduces errors by overcomplicating. Match the amount of thinking to the difficulty of the step.
Stated reasoning is not a guaranteed account of what happened inside. The text a model produces as its reasoning is useful to the model and to you as a clue, but it may not faithfully reflect the true cause of its choice. Treat it as evidence to inspect, never as proof. Where correctness matters, verify the outcome and not the explanation.
ReAct: reasoning that touches the world
Thinking alone has a weakness. A model reasoning from its own knowledge can reason fluently to a wrong conclusion, because nothing outside it corrects the facts. An agent can do better by alternating thought with action. ReAct, short for reasoning and acting, is the pattern in which the agent repeats three things:
1. Thought: a short statement of what it knows, what it needs and what it will do next.
2. Action: a tool call.
3. Observation: the result, which feeds the next thought.
Here is a short ReAct trace for the invoice agent.
Step · Thought · Action · Observation1 · The supplier asks why 8841 was rejected. I need the invoice record first. · getinvoice(8841) · Rejected, code E12
2 · The code is E12. I do not know what it means, so I should look up the rule rather than guess. · getrule(E12) · Purchase order number missing or invalid
3 · I now know the reason and the fix. I can reply. · finish(reply) · (done)
This is the agent loop of Lesson 1.2 with the thinking made explicit, and it is how most tool-using agents work. The thought written before each action does three useful things. It makes the model commit to a reason for the next step, which reduces random choices. It surfaces what the model still does not know, which prompts a lookup instead of a guess, as in step 2. And it leaves a readable trace for the person debugging.
The thought is not free, and it need not be long. One or two sentences are enough. A very long thought before every action drives up cost and latency without improving results, so many agents ask for "a brief note of your reasoning" before each tool request.
Predict first: an agent keeps answering a question about a customer's balance from memory, wrongly, instead of calling the lookup tool. Would asking it to think harder fix this, or would it be better to change the pattern? Decide before reading on.
Change the pattern. Thinking harder about a fact the model does not have produces a more confident wrong answer. The fix is structural: make the instructions say that account facts come only from tools, ask the model to name the tool it will use in its thought, and have the harness reject any final answer that cites a figure no tool returned. Reasoning improves how information is used. It cannot supply information that is missing.
Reflection: checking its own work
A second family of patterns adds a step after the answer: the agent reflects. It critiques its own draft, finds problems and revises. The loop is draft, critique, revise, and it may repeat. Reflection is attractive because it needs no extra tools, only another model call or two.
Whether it helps depends on three rates:
Detection: how often the critique spots a real error. Call it d.
Fix: how often a spotted error is corrected properly. Call it f.
False alarm: how often the critique flags a correct answer as wrong, and how often that causes damage. A false alarm can lead the model to "fix" something that was right.
Suppose the base agent is right 80 per cent of the time. The reflection step detects 60 per cent of errors and fixes 80 per cent of those it detects. It also raises a false alarm on 5 per cent of correct answers, and half of the time a false alarm leads to a change that makes the answer wrong. Then:
Correct answers that stay correct: 0.80 × (1 − 0.05 × 0.5) = 0.80 × 0.975 = 0.780.
Wrong answers that become correct: 0.20 × 0.60 × 0.80 = 0.096.
New accuracy: 0.780 + 0.096 = 0.876, or 87.6 per cent.
An improvement of 7.6 points for one extra call is a good trade. But look at what drives it. If the critique is poor, with a false alarm rate of 20 per cent, accuracy is 0.80 × (1 − 0.2 × 0.5) + 0.096 = 0.72 + 0.096 = 81.6 per cent, hardly better than doing nothing, and it costs a call. The weakness of self-critique is that the critic is the same model, with the same blind spots as the author. It tends to agree with its own work, and it may miss exactly the errors it made.
The cure is to give the critic something better than its own opinion, a signal from outside:
A tool check: run the code and see whether it passes the tests; recompute the total; look the fact up again; validate the output against a schema. Suppose the check detects 90 per cent of errors and has a false alarm rate of 2 per cent. Accuracy becomes 0.80 × (1 − 0.02 × 0.5) + 0.20 × 0.90 × 0.80 = 0.792 + 0.144 = 93.6 per cent.
A separate critic: a different prompt, or a different model, with the explicit job of finding faults and a checklist to follow.
A reference: compare the draft with the source document, line by line.
Reflection has practical rules. Limit the rounds: one or two are plenty, and a loop of critique after critique can drift away from a good answer. Give the critic specific questions ("Does every figure in the reply appear in a tool result?") rather than "Is this good?". Keep the draft and the critique both in the trace. And always prefer a check that does not depend on the model's judgement when one exists.
Voting: ask several times and take the majority
A third pattern uses the model's variation. Ask the same question several times, with some randomness, and take the majority answer. This is called self-consistency. It works when there is a definite answer that can be compared, such as a number, a category or a yes or no.
The arithmetic is the arithmetic of a jury. Suppose each answer is independently right with probability 0.70. The majority of three is right if at least two are right. The probability is 3 × 0.7² × 0.3 + 0.7³ = 0.441 + 0.343 = 0.784, or 78.4 per cent. With five answers it is 83.7 per cent, with nine 90.1 per cent and with fifteen 95.0 per cent. For a model that is right 60 per cent of the time, five votes give 68.3 per cent and fifteen give 78.7 per cent.
Two conditions limit the gain.
The model must be better than chance on this question. If each answer is right only 40 per cent of the time, a majority of three is right 0.4³ + 3 × 0.4² × 0.6 = 0.352, or 35.2 per cent, which is worse than a single answer. Voting amplifies whichever way the model leans.
The answers must be reasonably independent. The arithmetic assumed it. In reality, the same model makes correlated mistakes: if it misreads the question, it misreads it every time, and voting just agrees on the error. Real gains are smaller than the table, and they are smaller still for systematic mistakes.
And voting costs n times as many calls. A decision that matters, such as a classification that triggers a refund, may justify five calls. A routine lookup does not.
Verification: the strongest pattern
Across all these patterns one lesson stands out. The most dependable improvement comes not from asking the model to think more, criticise itself or vote, but from verifying the result with something that is not the model. Examples:
Run the code. If the agent writes code, run it and run the tests. A test cannot be talked into passing.
Recompute. Add the numbers with a calculator tool, not with a second opinion.
Check against the source. Confirm that a quoted figure appears in the tool result, using string matching.
Validate the format. A schema check on the output catches missing fields at no cost.
Cross-check two sources. If two systems should agree, compare them.
Ask a person when the check cannot be automated and the stakes warrant it.
A verification step also gives the agent a reliable signal to act on: if the check fails, revise; if it keeps failing, escalate. This is the practical answer to the compounding errors of Lesson 1.2.
Choosing a pattern
Situation · Pattern · WhyA step needs facts the model lacks · ReAct with the right tool · Reasoning cannot supply missing facts
A multi-part judgement or calculation · Think before answering, or a calculator tool · Working out intermediate results helps; exact tools are better still
A draft that can be checked against rules or sources · Reflection with a checklist or a tool · An outside signal beats self-opinion
A single, discrete answer where an error is costly · Voting, if the model is clearly better than chance · The majority reduces random errors
Code, numbers, formats, quotes · Verification by a tool · Exact, cheap, not dependent on the model
A simple lookup or fixed step · None; act directly · Extra reasoning adds cost and sometimes error
A sensible default: reason briefly before actions, use tools for facts and arithmetic, verify anything that can be verified in code, add one reflection pass with a checklist for work that matters, and keep voting for the few high-stakes decisions where one wrong answer is expensive.
The patterns in code
python
from math import comb
import re
def majorityaccuracy(p, n):
"""Chance that more than half of n independent answers, each right with probability p, are right."""
return sum(comb(n, k) p k (1 - p) (n - k) for k in range(n // 2 + 1, n + 1))
def accuracyaftercheck(p, detect, fix, falsealarm, harm):
"""Accuracy after a checking step: correct answers that survive plus errors found and fixed."""
return p (1 - falsealarm harm) + (1 - p) detect fix
print([round(100 majorityaccuracy(0.7, n), 1) for n in (1, 3, 5, 9, 15)])
print([round(100 majorityaccuracy(0.4, n), 1) for n in (1, 3, 5)]) # voting amplifies a weak model's errors
print(round(100 accuracyaftercheck(0.8, 0.6, 0.8, 0.05, 0.5), 1), # good self-critique
round(100 accuracyaftercheck(0.8, 0.6, 0.8, 0.20, 0.5), 1), # weak self-critique
round(100 accuracyaftercheck(0.8, 0.9, 0.8, 0.02, 0.5), 1)) # check by a tool
a ReAct loop that reads the model's text: Thought, Action, then the harness supplies the Observation
SCRIPT = iter([
"Thought: I need the invoice record first.\nAction: getinvoice 8841",
"Thought: Code E12 is unfamiliar; look up the rule instead of guessing.\nAction: getrule E12",
"Thought: I have the reason and the fix.\nAction: finish Rejected because the purchase order number is missing; add it and resubmit.",
])
TOOLS = {"getinvoice": lambda arg: f"rejected, code E12, invoice {arg}",
"getrule": lambda arg: "Purchase order number missing or invalid"}
def react(maxsteps=6):
transcript = []
for in range(maxsteps):
text = next(SCRIPT) # a real model call goes here
thought = re.search(r"Thought: (.)", text).group(1)
name, arg = re.search(r"Action: (\w+) ?(.)", text).groups()
transcript.append(("Thought", thought))
if name == "finish":
transcript.append(("Final", arg))
return transcript
runtool = TOOLS[name]
transcript.append(("Action", f"{name} {arg}"))
transcript.append(("Observation", runtool(arg)))
return transcript
for kind, line in react():
print(f"{kind:12} {line}")
Run it. The vote table reproduces the figures above, the third line shows why an outside check beats self-criticism, and the ReAct transcript reads as a story of what the agent knew, did and learned.
Common mistakes
Asking for more thinking when facts are missing. Reasoning cannot invent information. Add a tool or a source.
Long thoughts before every step. One or two sentences are enough; more costs time and tokens.
Self-critique with no outside signal. The critic shares the author's blind spots. Give it a checklist, a tool or a source.
Unlimited reflection loops. Cap at one or two rounds.
Voting on a weak model. Below 50 per cent accuracy, majority voting makes answers worse.
Assuming independent samples. Systematic errors are repeated in every sample. Expect smaller gains.
Trusting stated reasoning as proof. The text may not explain the real cause. Verify outcomes.
Reasoning on trivial steps. Fixed lookups need no extra thought.
Skipping tool verification. Code, arithmetic, formats and quotes can be checked exactly and cheaply.
Key takeaways
Thinking before acting helps multi-part judgements, but costs tokens and time, and cannot supply facts the model lacks. Stated reasoning is a clue, not proof.
ReAct alternates thought, action and observation. It makes the model commit to a reason, notice what it does not know and leave a readable trace.
Reflection helps if the critique detects real errors more often than it raises harmful false alarms. A good self-critique lifts 80 per cent to 87.6 per cent, a weak one to 81.6, and a tool check to 93.6.
Voting helps if the model is better than chance and its mistakes are independent. The majority of five answers at 70 per cent accuracy is right 83.7 per cent of the time; at 40 per cent accuracy it is worse than one answer.
Verification by something that is not the model is the strongest pattern: run the code, recompute, check the source, validate the format.
Match the pattern to the step, and spend extra calls only where an error is costly.
Check yourself
1. What are the three parts of a ReAct step?
Thought, action and observation.
2. A model is right 65 per cent of the time on a yes or no question. What is the accuracy of a majority of three independent answers?
3 × 0.65² × 0.35 + 0.65³ = 0.4436 + 0.2746 = 0.718, about 71.8 per cent.
3. Why does a check by a tool usually beat self-critique?
The model shares its own blind spots and tends to agree with its draft. A tool gives an independent signal that is not influenced by the model's confidence.
4. A check detects 50 per cent of errors and fixes 100 per cent of those. It has no false alarms. The agent starts at 90 per cent. What is the accuracy after?
0.90 + 0.10 × 0.50 × 1.0 = 0.95, or 95 per cent.
5. An agent answers account balances from memory, wrongly. Name a structural fix.
Make account facts available only through a tool, say so in the instructions, and have the harness reject any answer that cites a figure no tool returned.
Try this
Set aside seventy-five minutes.
1. Take your agent from Module 3. List its steps and mark, for each, whether it needs a fact, a calculation, a judgement or a fixed lookup.
2. Choose a reasoning pattern for each step from the table in this lesson, and write why.
3. Write a ReAct instruction that asks for a one- or two-sentence thought before each action. Run the transcript code and adapt the script to your tools.
4. Pick one output of your agent that can be verified in code, such as a total, a format or a quoted figure. Write the check.
5. Estimate the detection, fix and false-alarm rates for a self-critique step on your agent, from the trace of ten runs. Use the check simulator to find the gain.
6. Decide whether any decision in your agent justifies voting. Compute the accuracy for three and five samples at your estimated single-answer accuracy, and the extra cost.
7. Write the cap on reflection rounds and what the agent does when the check still fails.
A good result is a table assigning a reasoning pattern to each step, at least one exact verification written in code, an estimate of whether a self-critique step pays and a cap on checking loops. The next lesson turns to the other half of long work: how to keep the right information in front of the model as a run grows.
Tags: Agentic AI ReAct Reflection Self-consistency Agent reasoning