# What Is the ReAct Pattern? A Deep Dive into Agent Reasoning and Action

> Explore the ReAct pattern, an iterative Reason → Act → Observe loop that empowers LLMs to tackle complex tasks. Learn how it combines reasoning and tool calls, as seen in bojieli/ai-agent-book.

- Repository: [Bojie Li/ai-agent-book](https://github.com/bojieli/ai-agent-book)
- Tags: deep-dive
- Published: 2026-07-25

---

**The ReAct pattern is an iterative Reason → Act → Observe loop that enables Large Language Models to solve complex tasks by combining internal reasoning with external tool calls, as implemented throughout the bojieli/ai-agent-book repository.**

The ReAct pattern (Reason, Act, Observe) has emerged as the foundational architecture for building autonomous AI agents that can interact with the real world. In the **bojieli/ai-agent-book** repository, this pattern is implemented across multiple chapters to demonstrate how Large Language Models (LLMs) can move beyond simple text generation to perform multi-step problem solving. This article examines how the ReAct pattern structures agent reasoning and action, with concrete code examples from the open-source implementation.

## How the ReAct Pattern Structures Agent Workflows

The ReAct pattern divides agent execution into three distinct phases that form a repeating cycle. This architectural separation keeps reasoning explicit and debuggable while enabling dynamic tool use.

### Phase 1: Reason

The LLM generates a natural-language "thought" that explicitly states what it plans to do or which tool it needs. This phase keeps the model’s reasoning transparent, making the process interpretable and easier to debug. By externalizing the thought process, developers can inspect why an agent chose a specific action before it executes.

### Phase 2: Act

Based on the generated thought, the agent invokes an external tool—such as a web search, code executor, or phone API—using either the OpenAI function-calling specification or a custom RPC format. This step empowers the agent with capabilities beyond pure text generation, transforming it into a system that can interact with external data sources and services.

### Phase 3: Observe

The tool's output (search results, execution logs, or API responses) is appended to the conversation history as new context. The LLM then updates its reasoning based on this observation, deciding whether to invoke another tool or deliver a final answer. This closes the feedback loop and enables multi-step adaptation to complex problems.

## Core Implementation: The ReAct Loop in Code

According to [`chapter2/local_llm_serving/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter2/local_llm_serving/agent.py), the generic ReAct driver implements this exact skeleton, iterating until the LLM signals completion or hits a safety limit:

```python
def react_loop(messages, tools, max_iters=10):
    for i in range(max_iters):
        response = llm.chat(messages)                     # Reason

        if tool_call := extract_tool_call(response):      # Act

            tool_result = call_tool(tool_call)            # Observe

            messages.append(format_observation(tool_result))
        else:
            return response["content"]                    # Final answer

    raise RuntimeError("ReAct loop exceeded max_iterations")

```

This implementation caps the loop at `max_iters` (default 10) to prevent infinite recursion, logging each iteration as `ReAct iteration X` for debugging purposes.

## Concrete Implementations in the ai-agent-book Repository

### Web-Search Agent (Chapter 1)

The file [`chapter1/web-search-agent/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter1/web-search-agent/agent.py) implements a classic ReAct loop for a web-search assistant. Here, the LLM emits a "Thought" and optionally a `web_search` tool call, continuing until it synthesizes a final answer:

```python
from chapter1.web_search_agent.agent import ReActWebSearchAgent

agent = ReActWebSearchAgent(
    llm_name="gpt-4o",
    max_iterations=7,
    dry_run=False                     # set True for offline deterministic demo

)

result = agent.run("Who won the 2023 Nobel Prize in Chemistry?")
print(result)

```

### Agentic RAG System (Chapter 3)

The [`chapter3/agentic-rag/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter3/agentic-rag/agent.py) file demonstrates a ReAct-based Retrieval-Augmented Generation (RAG) system. The model first reasons about which knowledge source to query, acts by invoking a retrieval tool, observes the retrieved passages, and then continues reasoning:

```python
from chapter3.agentic_rag.agent import ReActRAGAgent

rag = ReActRAGAgent(
    llm_name="gpt-4o-mini",
    retriever="faiss",                # any vector store works

    max_iterations=6
)

answer = rag.run("Explain the concept of “self‑consistency” in chain‑of‑thought prompting.")
print(answer)

```

### High-Level ChatReActAgent Wrapper (Chapter 2)

For production use, [`chapter2/prompt-engineering/tau_bench/agents/chat_react_agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter2/prompt-engineering/tau_bench/agents/chat_react_agent.py) provides the `ChatReActAgent` class, which encapsulates the ReAct logic with a clean `run()` API:

```python
from chapter2.prompt_engineering.tau_bench.agents.chat_react_agent import ChatReActAgent

# Initialise the ReAct agent (uses OpenAI function calling under the hood)

agent = ChatReActAgent(
    model="gpt-4o-mini",
    max_iterations=5,               # safety cap

    verbose=True                    # prints each Reason/Act/Observe step

)

query = "What are the latest research papers on Retrieval‑Augmented Generation?"
answer = agent.run(query)          # triggers the ReAct loop automatically

print("Final answer:", answer)

```

## Safety Mechanisms and Production Considerations

Production-grade ReAct implementations require safeguards against runaway execution. The repository enforces this through the `max_iterations` parameter, which appears consistently across [`chapter1/web-search-agent/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter1/web-search-agent/agent.py), [`chapter2/local_llm_serving/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter2/local_llm_serving/agent.py), and [`chapter3/agentic-rag/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter3/agentic-rag/agent.py).

When the iteration limit is exceeded without reaching a final answer, the system raises a `RuntimeError`, preventing resource exhaustion. Additionally, setting `verbose=True` in `ChatReActAgent` logs each Reason/Act/Observe step, enabling developers to trace decision trees for debugging or compliance auditing.

## Summary

- The **ReAct pattern** structures agents into **Reason → Act → Observe** cycles that repeat until task completion.
- **Interpretability** comes from explicit natural-language reasoning steps generated by the LLM before each action.
- **Extensibility** allows swapping tools (search, RAG, voice) without modifying the core reasoning engine, as demonstrated across [`chapter1/web-search-agent/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter1/web-search-agent/agent.py), [`chapter3/agentic-rag/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter3/agentic-rag/agent.py), and [`chapter9/phone-agent/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter9/phone-agent/agent.py).
- **Safety mechanisms** like `max_iterations` prevent infinite loops by hard-capping the number of tool invocations.
- The **bojieli/ai-agent-book** repository provides reusable implementations ranging from low-level drivers in [`chapter2/local_llm_serving/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter2/local_llm_serving/agent.py) to high-level wrappers like `ChatReActAgent`.

## Frequently Asked Questions

### How does the ReAct pattern differ from chain-of-thought prompting?

Chain-of-thought prompting generates intermediate reasoning steps but remains a single-pass text generation process. The ReAct pattern introduces an **action layer** where the agent pauses execution to invoke external tools, observes the results, and continues reasoning. This external feedback loop enables the agent to interact with dynamic environments and retrieve information not present in its training data.

### What types of tools work best with the ReAct pattern?

The pattern is tool-agnostic. The repository demonstrates implementations with **web search** ([`chapter1/web-search-agent/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter1/web-search-agent/agent.py)), **vector database retrieval** ([`chapter3/agentic-rag/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter3/agentic-rag/agent.py)), and **voice call APIs** ([`chapter9/phone-agent/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter9/phone-agent/agent.py)). Any tool that accepts structured input and returns observable output can integrate into the ReAct loop, including code executors and robotics controllers.

### How does the ReAct pattern prevent infinite loops?

The implementations enforce a **maximum iteration limit** through the `max_iters` parameter, typically defaulting to 10 iterations. After reaching this limit without producing a final answer, the agent raises a `RuntimeError`. This safety mechanism appears in [`chapter2/local_llm_serving/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter2/local_llm_serving/agent.py) and the `ChatReActAgent` class to ensure resource boundaries.

### Can the ReAct pattern work with open-source LLMs?

Yes. The [`chapter2/local_llm_serving/agent.py`](https://github.com/bojieli/ai-agent-book/blob/main/chapter2/local_llm_serving/agent.py) implementation specifically provides a generic ReAct driver that works with any LLM supporting function-calling capabilities, not just proprietary APIs. The pattern relies on standard tool-calling formats rather than model-specific features, making it compatible with locally hosted models.