03. ReAct Pattern

Chapter 3 of 16 · 15 min

ReAct stands for Reasoning + Acting. It is an agent design pattern where the model generates interleaved thought traces and action calls. After each action, the model receives observations and continues reasoning until it has enough information to produce a final answer.

The pattern was introduced to reduce hallucinations by grounding model reasoning in real observations rather than letting it confabulate freely.

How the ReAct loop works

import json

def react_loop(model, tools, task, max_steps=15):
    """ReAct loop: think -> act -> observe -> repeat"""
    toolspec = {t.name: t for t in tools}
    messages = [
        {"role": "system", "content": (
            "You are a ReAct agent. For each step, output a JSON object with "
            "'thought', 'action', and 'action_input' keys. After action, "
            "observe results and continue reasoning."
        )},
        {"role": "user", "content": task}
    ]
    
    for step in range(max_steps):
        response = model.chat(messages, tools=tools)
        
        # Parse the model's structured output
        try:
            parsed = json.loads(response.content)
            thought = parsed.get("thought", "")
            action = parsed.get("action", "")
            action_input = parsed.get("action_input", {})
        except json.JSONDecodeError:
            return response.content
        
        messages.append({"role": "assistant", "content": response.content})
        
        if action == "finish":
            return action_input.get("answer", parsed.get("final_answer", ""))
        
        if action in toolspec:
            result = toolspec[action].invoke(**action_input)
            messages.append({
                "role": "tool",
                "content": f"Observation: {result}"
            })
        else:
            messages.append({
                "role": "tool",
                "content": f"Unknown action: {action}"
            })
    
    return "Max steps exceeded"

Thought traces in prompts

The system prompt instructs the model to output structured JSON with thought, action, and action_input. Few-shot examples dramatically improve performance. Give the model two to three examples showing the think-act-observe pattern so it learns the output format.

Common ReAct failures

  • Model stops too early: Add a finish action that the model must explicitly call
  • Model calls nonexistent tools: Limit available tools to what is actually registered
  • Infinite parsing loops: Wrap JSON parsing in try-except and fall back to regex extraction as a last resort
EXERCISE

Modify the ReAct loop to log each step's thought and action to a file. Run three different tasks and inspect the trace to spot any reasoning gaps.