The loop we built a few posts ago has a name. The pattern is called ReAct, short for reason and act, and it sits underneath most agents you will meet.
The idea is small. Instead of answering everything at once, an agent alternates between reasoning about what it needs and taking an action to get it.
How you would answer the question yourself
Take our running question: how many staff-hours would routing routine tickets to an agent free, and does the saving cover the model calls?
You would not answer in one breath. You would think "I need the ticket counts first", go and read the export, think "now I need the current token price", look that up, then do the arithmetic. Reason, act, observe what came back, reason again.
ReAct is that cycle, written down.
The cycle, traced
Here is a ReAct agent working the question, with every step made explicit.
Thought: I need the routine ticket counts for last quarter.
Action: read_tickets(quarter="2026-Q2")
Observe: password_reset: 118 tickets, 6.2 min avg; billing: 74; ...
Thought: Now I need the current price per million input tokens.
Action: search_web(query="input token price per million current")
Observe: Pricing page: <rate> per 1M input tokens
Thought: I have both. Time to work out the hours.
Action: calculate(expression="118 * 6.2 / 60")
Observe: 12.19
Thought: I have enough to answer.
Answer: Password resets alone freed about 12 staff-hours last quarter...
Read the shape rather than the numbers. Each step states a thought, takes one concrete action, and reads the result before deciding the next move.
Reason, act, observe, repeat. The loop continues until the agent has enough to answer.
The power is in the third column. When the first search comes back unhelpful, the agent reasons about that and tries a different query. When a number looks wrong, it can check it. A fixed script breaks the moment something unexpected happens; a ReAct agent reads what actually came back and adjusts. That is the same way a person works a multi-step problem, and it is why the pattern generalises so well.
The part that changed
Early ReAct agents had a fragile job to do. The model had to print its steps in an exact text format,
something like Action: search["query"], and your code parsed that text to find the tool call.
Thought: I need the ticket counts
Action: read_tickets["2026-Q2"]
A missing bracket broke it. An extra space broke it. A slightly reworded keyword broke it. People spent real effort writing prompts that begged the model to format perfectly, and it still failed often, because you were parsing free text and free text varies.
Tool calling removed that whole class of problem. Instead of printing text you parse, the model emits a structured tool call, and the format is guaranteed by the API rather than hoped for.
# what the model returns now, structured, not text to parse
reply.tool_calls[0] # name="read_tickets", arguments={"quarter": "2026-Q2"}
Old ReAct printed text you had to parse. Tool calling makes the call structured and reliable.
If the "Thought" line is gone, is it still ReAct?
Yes, and the reason is worth holding onto.
The reasoning did not disappear. It moved inside the model. As covered earlier in this series, models
are trained on large numbers of tool-calling examples, so choosing a tool and filling its arguments
is the reasoning step, done internally. When the model picks read_tickets and supplies the
quarter, it has already reasoned about what it needs.
So the visible Thought: text is gone, and the cycle is unchanged: reason about what is needed, act
to get it, observe the result, repeat. Agents built on tool calling are still called ReAct agents
across every major framework, because the principle is the same.
| Text-based ReAct | Tool-calling ReAct | |
|---|---|---|
| How the model asks for a tool | Prints Action: tool["args"] as text | Emits a structured tool call |
| Who guarantees the format | Nobody; you parse and hope | The API |
| What breaks it | A bracket, a space, a synonym | Much less |
| Where the reasoning lives | An explicit Thought: line | Inside the model, in the tool choice |
| Still ReAct? | Yes | Yes |
What to take from this
- ReAct is reason, act, observe, repeat. Most agents are an implementation of it.
- The loop from earlier in this series already does this. ReAct is the name for what it does.
- Modern agents dropped the parsed
Thought:text because tool calling made it unnecessary, not because the reasoning went away. It moved inside the model.
The loop we have is deliberately small. Turning it into something you would actually run, debug and extend needs a few more parts, and the first is somewhere to keep everything that happens during a run.