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
Calculator
tool that can evaluate mathematical expressions - Initializing an OpenAI language model with temperature=0 for deterministic responses
- Creating the agent using the
ZERO_SHOT_REACT_DESCRIPTION
agent 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.