Exercises — ReAct (reasoning + acting) framework
This page is a self-test ladder. Each rung goes deeper: from recognising what a ReAct piece is, to building whole trajectories yourself. Every problem has a full solution hidden inside a collapsible callout — try first, then reveal.

Notation reminder, built from zero so no symbol is unearned:
- — the original question the user asked.
- — the toolbox: the finite set of tools the agent may call. The curly braces just mean "the collection of".
- — the action chosen at step (the subscript = "which step in time", is first).
- — the observation returned right after .
- — the whole ordered list. The Greek letter tau () is just a name for "the trajectory".
Level 1 — Recognition
L1.1
Label each line below as Thought, Action, or Observation:
Search["boiling point of water at Everest summit"]- "I don't know the altitude effect, so I should look it up."
"Water boils near 71°C at that altitude."
Recall Solution
- Action — it is an executable tool call written in
Tool["..."]form. - Thought — internal self-talk deciding what to do next; no tool is invoked.
- Observation — it is the result handed back by the tool (note it is a returned fact, not a decision).
Rule of thumb: Actions are commands, Observations are results, Thoughts are reasons.
L1.2
Which single property does a pure chain-of-thought agent lack that ReAct adds? Pick one: (a) the ability to output text, (b) grounding via real observations, (c) the ability to store a subscript .
Recall Solution
(b) grounding via real observations. Pure chain-of-thought reasons only from what is already inside the model's weights (its training memory). It never receives an from the outside world, so it cannot correct a wrong belief. ReAct's loop inserts after every , which anchors the reasoning to real data. See Retrieval-Augmented Generation (RAG) for a related "fetch real facts" idea.
Level 2 — Application
L2.1
An agent must answer: "What is 8% of the cube of 12?" Write the full ReAct trajectory using only a Calculate[...] tool and a Finish[...] action.
Recall Solution
Thought 1: I need first, because "cube of 12" is the inner quantity.
Action 1: Calculate[12 ** 3]
Observation 1: 1728
Thought 2: Now take 8% of 1728, i.e. .
Action 2: Calculate[0.08 * 1728]
Observation 2: 138.24
Thought 3: I have the value; finish.
Action 3: Finish[138.24]
Answer: 138.24. The order matters: you must cube before taking the percentage, so the first tool call is the inner operation.
L2.2
The multi-hop question is "In what year was the director of the film 'Inception' born?" Suppose only a Search[...] tool exists. Fill in the two dependent search queries a correct ReAct agent would make (you do not need real dates).
Recall Solution
Thought 1: I must first learn who directed Inception; I can't search a birth year without a name.
Action 1: Search["director of the film Inception"]
Observation 1: "Inception was directed by Christopher Nolan."
Thought 2: Now that I have the name, I can look up that person's birth year.
Action 2: Search["Christopher Nolan birth year"]
Observation 2: "Christopher Nolan was born in 1970."
Thought 3: I have the year; finish.
Action 3: Finish["1970"]
Key point: Action 2 depends on Observation 1. You literally cannot write query 2 until query 1 returns. This is what "multi-hop" means.
Cloze check — reveal after trying:
Why can't Action 2's query be written before Observation 1 arrives?
Level 3 — Analysis
L3.1
Recall the trajectory probability from the parent note: Here (capital pi) means "multiply all these together", means "everything that happened before step ", and later means "1 if true, else 0".
(a) Why is the factor special compared to the other two? (b) A 3-step trajectory has these factor values:
| step | |||
|---|---|---|---|
| 1 | 0.5 | 0.8 | 1 |
| 2 | 0.4 | 0.5 | 1 |
| 3 | 0.9 | 1.0 | 1 |
Compute .
Recall Solution
(a) is deterministic — once the action is fixed, the environment (the tool) returns exactly one observation, so this probability is (for the real observation) or (for any other). The other two factors are stochastic: the language model could have produced many different thoughts or picked many different actions, each with some probability. Only the LM factors carry real uncertainty.
(b) Multiply every entry: So . Notice the terms drop out — they never change the product.
L3.2
An action-only agent (no Thoughts) gets an Observation "No results found." after Search["Xylographic quorum flux 2024"]. Explain, in ReAct terms, why it is stuck and what a Thought would let it do.
Recall Solution
An action-only agent has no place to interpret the observation. Its next step is another action, chosen with no explicit reasoning about the failure — so it typically repeats a near-identical query or blindly moves on.
A Thought step gives the agent a slot to reason: "The query returned nothing; the phrasing may be too obscure. Let me broaden it." This produces a revised action, e.g. Search["quorum flux definition"]. This is the error-recovery property: observations flag the problem, thoughts choose the fix. Compare with Reflexion, which formalises this "reflect on failure" idea across whole episodes.
Level 4 — Synthesis
L4.1
Design a complete, minimal ReAct trajectory for a mixed task requiring two different tools: "What is 20% of the population (city limits) of the capital of Japan, in millions?" Available tools: Search[...], Calculate[...], Finish[...]. Use the placeholder city-limits figure 14.0 million from search.
Recall Solution
Thought 1: I need Japan's capital before I can look up its population.
Action 1: Search["capital of Japan"]
Observation 1: "The capital of Japan is Tokyo."
Thought 2: Now I need Tokyo's city-limits population.
Action 2: Search["Tokyo city limits population millions"]
Observation 2: "Tokyo has about 14.0 million people within city limits."
Thought 3: Compute 20% of 14.0, i.e. .
Action 3: Calculate[0.20 * 14.0]
Observation 3: 2.8
Thought 4: I have the value; finish.
Action 4: Finish["2.8 million"]
Answer: 2.8 million. This trajectory shows tool switching: two Search hops feed a Calculate hop. Each thought names exactly the next action — see Tool Use in LLMs and MRKL for how multiple tools are routed.
L4.2
Draw (in mermaid or words) the control-flow loop of ReAct, marking clearly where the loop exits.
Recall Solution
The loop repeats Thought → Action → Observation, and exits only when the chosen action is Finish[...]:
flowchart TD
Q["Question Q"] --> T["Thought t"]
T --> A["Action a_t"]
A --> Check{"is a_t Finish"}
Check -->|no| O["Observation o_t"]
O --> T
Check -->|yes| End["Return answer"]
The decision diamond is the only exit: if we stop; otherwise we get an observation and loop back to a new Thought.
Level 5 — Mastery
L5.1
A student proposes replacing ReAct's single greedy trajectory with three independent ReAct trajectories and taking the majority-voted final answer. (a) What existing technique does this combine ReAct with? (b) Under what condition does voting help, and when does it not?
Recall Solution
(a) This is ReAct combined with Self-Consistency — sample multiple trajectories, then vote on the final answers. (b) Voting helps when the errors are independent and the correct answer is the most common single outcome: if each trajectory is more likely right than any specific wrong answer, majority vote amplifies the correct one. Concretely, suppose each trajectory is correct with probability and, when wrong, wrong in scattered non-agreeing ways. Then the majority of 3 is correct if at least 2 are correct: For : — voting helped. Voting does not help when trajectories share a systematic bias (all hallucinate the same wrong fact) — then they agree on the wrong answer and voting cements the mistake. Independence of errors is the whole engine.
L5.2
You must build an agent for a live stock-price question: "Is Apple's current stock price above its 50-day average?" Explain why pure chain-of-thought cannot answer this even in principle, and sketch the ReAct trajectory (tools: GetPrice[...], GetAverage[...], Compare[...], Finish[...]).
Recall Solution
Why CoT fails in principle: the answer depends on data created after training (today's price). No amount of internal reasoning can recover a number that was never in the weights. Only an observation from a live tool can supply it — this is the grounding argument at its sharpest.
ReAct trajectory:
Thought 1: I need the current price of AAPL.
Action 1: GetPrice["AAPL"]
Observation 1: "AAPL current price = 190.00"
Thought 2: I also need its 50-day average.
Action 2: GetAverage["AAPL", 50]
Observation 2: "AAPL 50-day average = 182.50"
Thought 3: Compare 190.00 with 182.50.
Action 3: Compare[190.00, 182.50]
Observation 3: "190.00 > 182.50 → True"
Thought 4: The current price exceeds the average; finish.
Action 4: Finish["Yes, above its 50-day average"]
Every fact (, ) entered through an observation, never invented. This is exactly the Agent Architectures principle: reasoning orchestrates, tools supply truth.
Recall Quick self-audit checklist
- Can I label any line as Thought / Action / Observation? (L1)
- Can I write a dependent multi-hop trajectory without batching? (L2)
- Do I set and multiply the LM factors correctly? (L3)
- Do I always end with
Finish[...]? (L4) - Do I know when self-consistency helps vs. cements error? (L5)