Mid · 6 chapters
ReAct as history
Why native tool calling superseded hand-parsed Thought:/Action: strings
ReAct is useful history, but implementing its text protocol today adds parsing and recovery failures without a compensating capability.
Read these first
What you will know
Run a minimal ReAct trace that alternates Thought, Action, and Observation, then identify where parsing controls execution.
A single malformed delimiter, quoted argument, or unexpected model reply can turn the transcript into an invalid or unsafe command.
Compare a hand-parsed Thought:/Action: loop with native tool calling using malformed, missing, and extra arguments.
The useful comparison includes schema validation, provider behavior, retry handling, and whether invalid model output reaches the tool.
Recognise ReAct-style string parsing in existing code as legacy
Search for delimiters, regular expressions, or branches on labels such as Thought and Action; these are protocol clues even when the code has different names.
Write a migration note that maps ReAct's Thought, Action, and Observation loop to messages, tool calls, and tool results.
The control-flow idea survives, while private reasoning need not be exposed as a text field that downstream code must parse.
Decline to implement it
A successful toy demo can conceal escaping bugs, ambiguous retries, prompt injection paths, and poor observability once tools have side effects.
Chapters
- 1
ReAct's real content was a text protocol, not a prompt style
Thought, Action, Observation: three labels inside a completion, a stop sequence set on the observation label, and a regular expression that pulls the action back out. Running a minimal trace makes the crucial point visible — the parser, not the provider, decides which command executes. Calling ReAct "telling the model to think before acting" stops at the prompt and never reaches the part that actually changed.
- 2
A schema rejects a bad call before dispatch; a regex does not
Feed both designs the same three abuses — a malformed argument, a missing required one, an extra one nobody declared — and the difference stops being a matter of taste. Native tool calling validates against a declared schema and refuses the call; the hand-parsed loop hands whatever it extracted to the tool and finds out afterwards. Retry behaviour splits the same way: one has a typed failure to report, the other has a string.
- 3
A parsed transcript is a control channel attackers can write to
When execution depends on splitting text, any text that reaches the transcript can steer it. A retrieved web page containing the observation label, a quoted argument with an embedded newline, a tool result echoing user input — each can append a second action the model never requested. Trace that path from a fetched page through to a shell command, and see why one more validation regex only patches the symptom while the transcript remains the control channel. Then triage it on a one-day budget: what you do immediately about the shell tool's reach and the sandbox it runs in, and what has to wait for the protocol replacement the rest of this topic sets out.
- 4
A stop sequence on "Observation:" dates the code you inherited
Codebases rarely announce their protocol. What gives it away is a stop sequence set to an observation label, a split on an action label, branches keyed to words like Thought, or a prompt template spelling the cycle out in prose — even when every identifier has been renamed to something local. Recognising the pattern tells you which failures to expect before you have read the rest of the file.
- 5
Thought becomes content nothing branches on; Action becomes a call
The migration is a mapping, not a rewrite of the idea: the alternation of reasoning, action and result survives intact as assistant turns, tool calls and tool results. What does not survive is Thought as a parsed field, and that is the point — preserving it as an audit trail turns self-reported model prose into a load-bearing artifact. Say instead what you would record as real evidence of why the agent acted.
- 6
One remaining reason to hand-parse, and what it costs you
A local model with no tool-calling API is the honest exception, and it is still not an argument for parsing prose: schema-constrained decoding gets a validated JSON call out of that same model, which is the middle option most teams never put on the table. Take the parser instead and you have adopted escaping, argument validation, retry semantics and an injection surface as your own code, plus traces carrying a blob of text where structure should be. This chapter is the argument you make when the demo works and someone proposes shipping it.
External resources
- ReAct: Synergizing Reasoning and Acting in Language Modelsarxiv.org
The original Thought/Action/Observation paper you are inheriting from.
- Tool Calling Is Not a Solved Problem - by Jae Lisubstack.com
This is a substantive practitioner explainer that details tool-calling mechanics and introduces ReAct alongside CodeAct, providing relevant context for understanding ReAct as an agent-history pattern.
- Function callingdevelopers.openai.com
The native replacement: typed tool schemas instead of parsing model prose.
- ReAct agent from scratch with Gemini 2.5 and LangGraphphilschmid.de
A from-scratch ReAct agent with Gemini 2.5 and LangGraph, including modern function calling.
- ReAct Promptingpromptingguide.ai
Explains ReAct’s Thought/Action history and why native tool calling superseded hand-parsed strings.
- ReAct Prompting: How We Prompt for High-Quality Results from LLMswidth.ai
Explains ReAct’s Thought–Action–Observation loop and its evolution toward structured tool calling.
- ReAct AI Agents, clearly explained!Akshay Pachaar
Shows the hand-parsed ReAct loop so you recognise it in legacy code.
- What is Tool Calling? Connecting LLMs to Your DataIBM Technology
Explains native tool calling mechanics and why it is more reliable.
- Context Engineering vs. Prompt Engineering: Smarter AI with RAG & AgentsIBM Technology
Explains why modern agents moved beyond hand-parsed ReAct strings toward structured tool calling.