Building a Simple ReAct Agent with LangChain
Learn how to create a ReAct agent using LangChain's agent framework to combine reasoning and action for enhanced problem-solving capabilities.
LangChain's agent framework provides powerful abstractions for building AI systems that can interact with tools and make decisions. In this tutorial, we'll explore how to create a ReAct agent, which combines reasoning and action to enhance the problem-solving capabilities of language models.
Understanding ReAct Agents
ReAct (Reasoning + Acting) is a paradigm that enhances language models by combining:
- Reasoning: The model explains its thought process
 - Acting: The model uses tools to gather information or perform actions
 
This approach allows agents to better handle complex tasks by breaking them down into a series of thoughts and actions, similar to how humans approach problem-solving.
Implementing a Basic ReAct Agent
Let's start by implementing a simple agent that can solve math problems using a calculator tool:
from langchain.agents import AgentType, initialize_agent
from langchain.tools import BaseTool
from langchain.llms import OpenAI
# Define your custom tools
class Calculator(BaseTool):
    name = "Calculator"
    description = "Useful for performing mathematical calculations"
    
    def _run(self, query):
        try:
            return eval(query)
        except Exception as e:
            return f"Error: {e}"
            
    def _arun(self, query):
        raise NotImplementedError("This tool does not support async")
# Initialize the LLM
llm = OpenAI(temperature=0)
# Create the agent
tools = [Calculator()]
agent = initialize_agent(
    tools, 
    llm, 
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True
)This code creates a ReAct agent by:
- Defining a 
Calculatortool that can evaluate mathematical expressions - Initializing an OpenAI language model with temperature=0 for deterministic responses
 - Creating the agent using the 
ZERO_SHOT_REACT_DESCRIPTIONagent type 
Testing the Agent
Now let's test our agent with a simple math problem:
agent.run("What is the result of (17 * 42) / 3.5?")
# Output:
# > Entering new AgentExecutor chain...
# I need to calculate (17 * 42) / 3.5.
# First, I'll calculate 17 * 42 = 714.
# Then, I'll divide 714 by 3.5.
# Action: Calculator
# Action Input: (17 * 42) / 3.5
# Observation: 204.0
# I now know the final answer.
# Final Answer: The result of (17 * 42) / 3.5 is 204.
# > Finished chain.
Notice how the agent:
- First reasons about the problem: "I need to calculate (17 * 42) / 3.5..."
 - Decides to use the Calculator tool: "Action: Calculator"
 - Observes the result: "Observation: 204.0"
 - Provides the final answer after reasoning
 
Adding Multiple Tools
ReAct agents become more powerful when they can choose between multiple tools. Let's add a search tool to our agent:
from langchain.utilities import SerpAPIWrapper
from langchain.tools import Tool
# Set up the search tool
search = SerpAPIWrapper()
search_tool = Tool(
    name="Search",
    func=search.run,
    description="Useful for searching the web for information"
)
# Create a more capable agent
tools = [Calculator(), search_tool]
agent = initialize_agent(
    tools, 
    llm, 
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True
)
# Test with a more complex query
agent.run("What is the population of France divided by the square root of 25?")With this enhanced agent, it can now:
- Search the web to find the population of France
 - Use the calculator to compute the square root of 25
 - Perform the division operation
 - Combine these steps to arrive at a final answer
 
Understanding Agent Execution Trace
One of the benefits of ReAct agents is their transparency. The verbose=True flag allows you to see the complete execution trace, revealing:
- The agent's reasoning process
 - The sequence of tool calls
 - How the agent integrates information from tool responses
 
Customizing the Agent's Behavior
You can customize the agent's behavior by adjusting parameters like:
agent = initialize_agent(
    tools, 
    llm, 
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True,
    max_iterations=5,
    early_stopping_method="generate",
    handle_parsing_errors=True
)These parameters control:
- max_iterations: Maximum number of steps the agent can take
 - early_stopping_method: How to handle reaching max iterations
 - handle_parsing_errors: Whether to gracefully handle parsing errors
 
Best Practices for ReAct Agents
When building ReAct agents, consider these best practices:
- Clear tool descriptions: Make sure each tool has a clear, specific description
 - Use temperature=0: For deterministic and more reliable reasoning
 - Add error handling: Implement robust error handling in your tools
 - Monitor and log: Track your agent's performance using LangSmith
 - Use human-in-the-loop: For complex tasks, consider adding human oversight
 
Conclusion
ReAct agents combine the reasoning power of LLMs with the ability to take actions, creating a powerful paradigm for solving complex problems. By following the approach outlined in this tutorial, you can create agents that can perform a wide range of tasks by reasoning through problems step by step.
In our next article, we'll explore how to create multi-agent systems using LangGraph, which allows for even more complex reasoning patterns through agent collaboration.