ReAct prompting is a pattern where a language model alternates between reasoning and acting: it writes a thought about what to do, takes an action such as a search or a tool call, reads the result, and only then decides the next step. The name is short for Reason + Act and comes from Yao et al. 2022, "ReAct: Synergizing Reasoning and Acting in Language Models". It is unrelated to React, the JavaScript library for building user interfaces.
Most AI agents that browse, run code or edit files run some version of this loop. Once you have walked through it by hand, agent behaviour becomes much easier to predict and to debug.
The Thought, Action, Observation loop
A ReAct prompt asks the model to write in three kinds of lines.
- Thought: reasoning about the current situation and what information is missing.
- Action: one tool call in a fixed format, such as
search[query],read_file[path]orfinish[answer]. - Observation: the result of that action. The model does not write this line. Your program (or you) runs the action and adds the real output to the transcript.
Then the whole transcript goes back to the model, which writes the next Thought. The loop ends when the model chooses the finish action. The model never runs a tool itself; it only asks, and the code around it decides whether to carry out the request.
Why reasoning plus acting beats either one
The paper compared ReAct with prompts that only reason (chain of thought) and prompts that only act (tool calls with no written reasoning). On question answering and fact checking with a Wikipedia search tool, reasoning alone often built a confident argument on a fact the model had made up, while ReAct could look the fact up, and the best question answering results came from combining ReAct with chain of thought, falling back from one to the other when the first did not produce a confident answer. Acting alone struggled to decompose the goal and pull what it found into an answer; the written thoughts kept the plan visible. On two interactive tasks, a text-based household game and a simulated shopping site, ReAct prompted with one or two examples did better than the trained baselines the authors compared against.
The general lesson: chain of thought helps a model plan, tools give it facts, and neither is enough for a task that needs both.
A ReAct agent, turn by turn
The block below is a small coding agent with two tools. Each tab is the same conversation one step later: the Observation lines are what the program pasted back after running the previous action. Read the replies in order.
Thought: I don't know which test fails or how. Running the tests will show the exact assertion before I read any code. Action: run_tests[tests/test_cart.py]
Notice two things. The first action is a test run, not a guess: the model gathered evidence before reading code. And each thought refers to the latest observation, which is the part chain of thought cannot do.
Try ReAct in a chat app
You do not need code to see the loop. In ChatGPT, Claude or Gemini you can be the tool: the model asks for an action, you perform it and paste back the result.
Thought: A loud fan at idle usually means something is using the CPU in the background, or the fan is struggling to cool (dust, blocked vents). Checking CPU usage first separates these two cases.
Action: Open Task Manager (Ctrl+Shift+Esc on Windows) or Activity Monitor (Applications > Utilities on a Mac). Sort processes by CPU, wait 30 seconds, and tell me the top three processes and their CPU percentages.
The same instructions, with a real function behind each action, are an agent.
A minimal ReAct loop in Python
In code, the program sends the transcript, finds the Action line in the reply, runs the matching function, appends the Observation and repeats. This sketch uses the OpenAI Python SDK and the system prompt from the coding agent above.
import re
import subprocess
from pathlib import Path
from openai import OpenAI
client = OpenAI()
MODEL = "your-model-id" # e.g. from your provider's model list
PROJECT = Path.cwd().resolve()
READABLE = {".py", ".md", ".txt", ".toml", ".cfg"}
def inside_project(arg):
# The model chooses arg: resolve it and refuse anything outside the project.
path = (PROJECT / arg).resolve()
if not path.is_relative_to(PROJECT):
raise ValueError(f"{arg} is outside the project")
return path
def run_tests(arg):
path = inside_project(arg)
if not (path.is_file() and path.name.startswith("test_") and path.suffix == ".py"):
raise ValueError(f"{arg} is not a test file")
result = subprocess.run(["pytest", str(path), "-q"], capture_output=True, text=True)
return result.stdout[-2000:]
def read_file(arg):
path = inside_project(arg)
if not path.is_file() or path.suffix not in READABLE:
raise ValueError(f"{arg} is not a file this agent may read")
return path.read_text()[:20000]
TOOLS = {"run_tests": run_tests, "read_file": read_file}
def react(task, system_prompt, max_steps=8):
transcript = f"Task: {task}\n"
for _ in range(max_steps):
response = client.chat.completions.create(
model=MODEL,
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": transcript},
],
temperature=0,
)
text = response.choices[0].message.content
match = re.search(r"Action: (\w+)\[(.*)\]", text)
if not match:
return text
transcript += text[: match.end()] + "\n"
tool, arg = match.groups()
if tool == "finish":
return arg
try:
observation = TOOLS[tool](arg) if tool in TOOLS else f"Unknown tool: {tool}"
except Exception as error: # a missing file becomes an observation, not a crash
observation = f"Error: {error}"
transcript += f"Observation:\n{observation}\n"
return "Stopped after max_steps without an answer."
Four details matter. The transcript is cut right after the Action, because models sometimes keep writing and invent their own Observation. A failing tool (a wrong file name, say) becomes an Observation the model can react to, instead of crashing the loop. The step limit stops a model that loops forever. And the test output is trimmed, since a huge test log would fill the context window; deciding what goes into that window is context engineering.
The two tools also check their argument before they do anything. The model chooses that argument, so the tool is where the limits belong: inside_project refuses any path that resolves outside the project folder (../ tricks included), run_tests accepts only test_*.py files, and read_file opens only a few source and text file types and returns at most 20,000 characters, so a .env file or an SSH key never reaches the next request. Running pytest still executes your project's own code, so run an agent like this in a container or a throwaway checkout, never on a machine that holds secrets.
Current APIs from OpenAI, Anthropic and Google also offer native tool calling: you describe each tool with a name and a JSON schema, and the model returns a structured tool call instead of an Action: line. The loop is identical; only the parsing disappears.
Safety in a ReAct loop
An agent reads text it did not write: web pages, files, tool output. Any of it can contain instructions aimed at the model, which is prompt injection. Give each tool the least access it needs (read-only where possible), ask a human to confirm anything that deletes, sends or pays, and treat the model's requested actions as untrusted input to check, not commands to run blindly.
Frequently Asked Questions
What is ReAct prompting?
ReAct (short for Reason + Act) is a prompting pattern where a language model writes a short piece of reasoning, then an action such as a search or a tool call, then reads the result before reasoning again. It comes from Yao et al. 2022, "ReAct: Synergizing Reasoning and Acting in Language Models". It has nothing to do with the React JavaScript library.
What are Thought, Action and Observation in ReAct?
A Thought is the model's reasoning about what to do next. An Action is a tool call in a fixed format, for example search[python 3.13 release notes]. The Observation is the tool's output, which your program runs the action to get and adds to the prompt. The loop repeats until the model takes a finish action with its answer.
What is the difference between ReAct and chain of thought?
Chain of thought reasons from what the model already knows, so a wrong fact early in the chain stays wrong. ReAct interleaves reasoning with actions that fetch real information, so the model can check a fact, see a test fail or read a file before continuing. The ReAct paper found that grounding the reasoning in search results cut down on the invented facts that chain of thought alone produced.
Do AI agents still use ReAct?
The loop, yes. Most agents today reason, call a tool, read the result and decide again, which is the ReAct cycle. What changed is the format: instead of parsing Action: lines out of text, current APIs have native tool calling, where the model returns a structured tool request and your code sends back the result.
Can I use ReAct in ChatGPT without code?
Yes, by playing the tool yourself. Ask the model to reply with one Thought and one Action and then stop. You run the action (search, open a file, run a command), paste the result as the Observation, and repeat. It is slow, but it shows exactly how an agent decides what to do next.