Designing the ReAct System Prompt

~20 min read

The system prompt isn't just instructions — it's a behavioral protocol that defines the Thought → PAUSE → Action → PAUSE → Observation loop, one step at a time, and tells the model exactly when to stop.

With the Agent class handling conversation memory, the next and most important piece is the ReAct system prompt — this is what actually turns a generic conversational LLM into an agent that reasons and acts in a controlled loop. This isn't just an instruction; it's a behavioral protocol that defines exactly what structure the agent should follow, how it should reason, and when it should stop.

The prompt opens with a framing sentence: 'You run in a loop and do JUST ONE thing in a single iteration.' This single line matters a great deal — it tells the model not to rush toward a final answer in one shot, and instead to proceed step by step, following a defined pattern in a loop that mirrors exactly how a ReAct agent is meant to work.

The loop itself has five named stages, given to the model as an explicit reasoning template: (1) 'Thought' — the agent's internal monologue about the current question; (2) 'PAUSE' — instead of jumping straight to action, this forces the model to stop and hand control back, simulating the asynchronous nature of a real tool call; (3) 'Action' — the agent picks one action from the list of tools it's been given; (4) 'PAUSE' — wait again, this time specifically for the tool's actual result; (5) 'Observation' — the output returned by the action, which gets injected back into the prompt by the controller (your code, or a human) after the tool actually runs.

Splitting the loop into these explicit, separately-labeled parts is deliberate: it avoids hallucinations by forcing the model to commit to one clear stage at a time, rather than blending reasoning and acting together in a way that's harder to inspect or debug. The system prompt also needs a tool specification section (name, an example call format, and a description for each available tool) so the model knows exactly what actions exist and how to invoke them, plus a closing stop-instruction telling the model to output 'Answer: ...' once it actually has the final answer — which is the signal your controller code watches for to know the loop is done.

💻 Code example

REACT_SYSTEM_PROMPT = """
You run in a loop and do JUST ONE thing in a single iteration:
Thought, PAUSE, Action, PAUSE, Observation.

Use "Thought" to describe your thoughts about the question.
Use "PAUSE" to pause and think about the action to take.
Use "Action" to decide what action to take, from the tools below.
Use "PAUSE" again to wait for the result of the action.
"Observation" will be the result returned to you.

When you have the final answer, output it as: Answer: <your answer>

Your available actions are:

math:
  e.g. Action: math: 4 * 7 / 2
  Runs a math expression and returns the numeric result.

lookup_population:
  e.g. Action: lookup_population: India
  Returns the population of the given country.

Example session:

Question: What is India's population divided by 2?
Thought: I need to look up India's population first.
PAUSE

You will be called again with:

Action: lookup_population: India
PAUSE

You will then be given:

Observation: 1417492000

Then continue the loop, ending with:
Answer: 708746000
""".strip()

💬 Deep Dive with AI

Key points

  • The system prompt is a behavioral protocol, not just instructions — it defines the exact loop structure the model must follow
  • The 5-stage loop: Thought (internal reasoning) → PAUSE → Action (pick a tool) → PAUSE → Observation (tool result injected back in)
  • The 2 PAUSE steps aren't decorative — they force a controlled handoff instead of the model rushing straight to an answer
  • Splitting the loop into explicit, separately-labeled stages reduces hallucination by keeping reasoning and acting visibly distinct
  • A tool specification section (name, example call, description) plus a clear 'Answer:' stop-signal round out the required prompt structure