Skip to main content

On This Page

AI Agents: Mastering 3 Essential Patterns (ReAct)

4 min read
Share

These articles are AI-generated summaries. Please check the original sources for full details.

The ReAct Pattern (Reason + Act) – When the Agent Starts “Talking to Itself”

With the “Tool Using” pattern, AI agents gained the ability to interact with the external world. The ReAct pattern (Reason + Act), proposed in 2022, equips agents with a “functional brain” by enabling an internal monologue for more complex problem-solving.

Unlike simple stimulus-response models, ReAct allows agents to plan, investigate, and course-correct, mirroring human thought processes. This is crucial because real-world problems often require multiple steps and adaptation, whereas a linear model quickly fails when facing ambiguity or incomplete information.

Why This Matters

Traditional AI models often struggle with multi-step reasoning and can quickly become unreliable when faced with complex tasks requiring information gathering and analysis. The cost of these failures can range from inaccurate data analysis leading to poor business decisions, to critical errors in automated systems, potentially amounting to millions in losses.

Key Insights

  • ReAct introduced in 2022: Proposed by researchers at Princeton and Google, establishing a new standard in AI agent design.
  • Internal Monologue: The core concept of ReAct, allowing the agent to articulate its thought process (“Thought Trace”) before taking action.
  • Agno Framework: A tool used to implement the ReAct pattern, streamlining the Think → Act → Observe → Repeat loop, and utilized by developers for rapid prototyping.

Working Example

import os
import sys
import logging
import traceback
from typing import List, Optional
from dotenv import load_dotenv, find_dotenv
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.tavily import TavilyTools
# 1. Global Logging and Error Handling Configuration
LOG_DIR = os.path.join(os.path.dirname(__file__), "log")
LOG_FILE = os.path.join(LOG_DIR, "logs.txt")
if not os.path.exists(LOG_DIR):
    os.makedirs(LOG_DIR)
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler(LOG_FILE, encoding="utf-8"),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger(__name__)
def global_exception_handler(exctype, value, tb):
    """Captures unhandled exceptions and records them in the log."""
    error_msg = "".join(traceback.format_exception(exctype, value, tb))
    logger.error(f"Unhandled exception:\n{error_msg}")
    sys.__excepthook__(exctype, value, tb)
sys.excepthook = global_exception_handler
# 2. Environment Variables Loading
env_path = find_dotenv()
if env_path:
    load_dotenv(env_path)
    logger.info(f".env file loaded from: {env_path}")
else:
    logger.warning(".env file not found")
# 3. Tool Definitions
def calculate(expression: str) -> str:
    """
    Solves a simple mathematical expression (addition, subtraction, multiplication, division).
    Useful for calculating year or date differences.
    Args:
        expression (str): The mathematical expression to evaluate (e.g., "2024 - 1789").
    """
    try:
        # Allow only safe characters for basic eval
        allowed_chars = "0123456789+-*/(). "
        if all(c in allowed_chars for c in expression):
            result = eval(expression)
            return f"Result: {result}"
        else:
            return "Error: Disallowed characters in expression."
    except Exception as e:
        return f"Error while calculating: {str(e)}"
# 4. Agno Agent Configuration (ReAct Pattern)
model_id = os.getenv("BASE_MODEL", "gpt-4o")
agent = Agent(
    model=OpenAIChat(id=model_id),
    tools=[TavilyTools(), calculate],
    instructions=[
        "You are a researcher using the ReAct (Reason + Act) method.",
        "1. Think step-by-step about what information you need to answer the user's question.",
        "2. Use the search tool (Tavily) to find specific dates, facts, or data.",
        "3. Use the calculator ('calculate') for any mathematical operation or time calculation.",
        "4. Do not guess historical information. If you don't have a piece of data, look it up.",
        "5. Show your reasoning clearly: 'Thought:', 'Action:', 'Observation:'.",
        "6. Continue investigating until you have a complete and verified answer."
    ],
)
# 5. User Interface
def main():
    logger.info("Starting Historical Detective Agent (ReAct)...")
    print("--- Historical Detective - ReAct Pattern ---")
    print("Type 'exit' to quit.\n")
    while True:
        try:
            user_input = input("Researcher, what is your question?: ")
            if user_input.lower() == "exit":
                logger.info("The user has ended the session.")
                break
            if not user_input.strip():
                continue
            logger.info(f"User query: {user_input}")
            print("\nInvestigating...\n")
            agent.print_response(user_input, stream=True, show_tool_calls=True)
            print("\n")
        except KeyboardInterrupt:
            logger.info("Keyboard interrupt detected.")
            break
        except Exception as e:
            logger.error(f"Error in main loop: {str(e)}")
            print(f"\nAn error occurred: {e}")
if __name__ == "__main__":
    main()

Practical Applications

  • Coding Assistants: Tools like Devin and Copilot leverage ReAct to iteratively write, execute, and debug code.
  • Customer Support: Level 2 tech support systems can use ReAct to diagnose and resolve complex issues by gathering information from multiple sources.
  • Financial Analysis: ReAct enables agents to analyze market trends and generate investment recommendations by combining data from news sources and historical data.

References:

Continue reading

Next article

My First Steps into Kubernetes: From Installation to Running Pods

Related Content