Phase 2Intermediate⏱ 90 minutes

Agents &
Tools Integration

Build intelligent AI agents that can reason, plan, and use tools to solve complex problems. Learn how to create autonomous systems that combine LLMs with external capabilities.

🎯

Learning Objectives

  • Understand the concept and architecture of LangChain agents
  • Integrate built-in tools like calculators and web search
  • Create custom tools for specific business needs
  • Build a multi-functional AI assistant with autonomous decision-making

📋 Prerequisites: Ready for Advanced LangChain?

This intermediate-level tutorial assumes you have:

  • • Completed lessons 5-8 (LangChain basics, chains, memory)
  • • Strong Python programming skills
  • • Understanding of LangChain prompts and chains
  • • Familiarity with async programming concepts (helpful)
🤖

Understanding AI Agents: Core Concepts and Architecture

An agent is an AI system that can reason about problems, plan actions, and use tools to accomplish goals. Unlike simple chains that follow predefined steps, agents can dynamically decide what to do next.

❌ Traditional Chains:

→ Fixed sequence

→ No decision making

→ Can't use external tools

→ Limited problem solving

✅ Intelligent Agents:

→ Dynamic planning

→ Tool selection

→ External API integration

→ Multi-step reasoning

🧠 Agent Reasoning Process:

1Thought: "I need to find current weather information"
2Action: Use weather API tool
3Observation: Received weather data
4Final Answer: Formatted response to user
🛠️

How to Build Your First LangChain Agent: Step-by-Step Tutorial

Zero-Shot Agent with Calculator

Let's start with a simple agent that can perform calculations and reasoning:

🔍 Understanding the Components:

  • Agent Type: ZERO_SHOT_REACT_DESCRIPTION uses reasoning and acting
  • Tools: Calculator tool for mathematical operations
  • Verbose Mode: Shows the agent's reasoning process
  • Max Iterations: Prevents infinite loops in agent reasoning
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.tools import Tool
from langchain.prompts import PromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
import os
import math
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Initialize the LLM
llm = ChatGoogleGenerativeAI(
    model="gemini-2.0-flash",
    temperature=0  # Lower temperature for more consistent tool usage
)

# Create a simple calculator tool
def calculate(expression: str) -> str:
    """Evaluate a mathematical expression"""
    try:
        # Use Python's eval for calculations
        # Only allow safe math operations
        allowed_names = {
            k: v for k, v in math.__dict__.items() if not k.startswith("__")
        }
        # Add power operator
        allowed_names['__builtins__'] = {'pow': pow}
        
        # Basic safety check
        if any(word in expression for word in ['import', 'exec', 'eval', 'open', 'file']):
            return "Invalid expression - contains restricted keywords"
        
        result = eval(expression, {"__builtins__": {}}, allowed_names)
        return str(result)
    except Exception as e:
        return f"Error calculating: {str(e)}"

# Create tool
calculator_tool = Tool(
    name="Calculator",
    func=calculate,
    description="Useful for mathematical calculations. Input should be a valid Python mathematical expression."
)

# Create the ReAct prompt
react_prompt = PromptTemplate.from_template("""Answer the following questions as best you can. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {input}
Thought: {agent_scratchpad}""")

# Create the agent
agent = create_react_agent(
    llm=llm,
    tools=[calculator_tool],
    prompt=react_prompt
)

# Create agent executor
agent_executor = AgentExecutor(
    agent=agent,
    tools=[calculator_tool],
    verbose=True,
    max_iterations=3,
    handle_parsing_errors=True
)

# Test the agent with math problems
test_queries = [
    "What is 15% of 2847?",
    "If I invest $10,000 at 7% annual interest, how much will I have after 5 years with compound interest?",
    "A pizza has 8 slices. If 3 people each eat 2.5 slices, how many slices are left?"
]

for query in test_queries:
    print(f"\n{'='*50}")
    print(f"Query: {query}")
    print(f"{'='*50}")
    
    try:
        result = agent_executor.invoke({"input": query})
        print(f"\nFinal Answer: {result['output']}")
    except Exception as e:
        print(f"Error: {e}")

# Example of agent reasoning output:
print(f"\n{'='*50}")
print("What you'll see in verbose mode:")
print(f"{'='*50}")
print("""
> Entering new AgentExecutor chain...
I need to calculate 15% of 2847.

Action: Calculator
Action Input: 2847 * 0.15

Observation: 427.05
Thought: I now know the final answer.
Final Answer: 15% of 2847 is 427.05
""")

💡 Agent Reasoning Process:

The agent follows the ReAct (Reasoning + Acting) pattern:

  • Thought: Analyzes the problem
  • Action: Chooses and uses appropriate tool
  • Observation: Processes tool result
  • Final Answer: Provides formatted response

🎯 Expected Results:

When you run this code, you'll see the agent solving each problem step by step:

Query 1: "What is 15% of 2847?"

→ Agent calculates: 2847 × 0.15 = 427.05

Query 2: Compound Interest

→ Agent applies formula: 10,000 × (1.07)^5 = $14,025.52

Query 3: Pizza Problem

→ Step 1: 3 people × 2.5 slices = 7.5 slices eaten
→ Step 2: 8 slices - 7.5 slices = 0.5 slices left

📖 Code Explanation:

  • Calculator Tool: A custom function that safely evaluates mathematical expressions using Python's eval with restricted scope
  • ReAct Prompt: Defines the exact format the agent should follow for reasoning and tool usage
  • Agent Executor: Manages the agent's execution, handles iterations, and provides verbose output
  • Safety Features: Keywords like 'import' and 'exec' are blocked to prevent code injection

⚠️ Modern Implementation Note:

This example uses the latest LangChain patterns. The deprecated initialize_agent and load_toolshave been replaced with create_react_agent and custom tool creation.

🔧

Creating Multi-Tool Agents: Combining Multiple Capabilities

Agent with Web Search and Calculator

Let's create an agent that can search the web and perform calculations:

🔍 Available Tools:

  • InfoSearch: Mock search for demonstration (simulates web/wiki search)
  • Calculator: Mathematical calculations using Python eval
  • Tool Selection: Agent automatically chooses appropriate tool based on the task
  • No External APIs: This example works without API keys for easier learning
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.tools import Tool
from langchain.prompts import PromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
import os
import math
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Initialize the LLM
llm = ChatGoogleGenerativeAI(
    model="gemini-2.0-flash",
    temperature=0
)

# Create a simple calculator tool
def calculate(expression: str) -> str:
    """Evaluate a mathematical expression"""
    try:
        allowed_names = {
            k: v for k, v in math.__dict__.items() if not k.startswith("__")
        }
        allowed_names['__builtins__'] = {'pow': pow}
        
        if any(word in expression for word in ['import', 'exec', 'eval', 'open', 'file']):
            return "Invalid expression"
        
        result = eval(expression, {"__builtins__": {}}, allowed_names)
        return str(result)
    except Exception as e:
        return f"Error calculating: {str(e)}"

# Create a mock information search tool (simulates web/wiki search)
def search_info(query: str) -> str:
    """Search for information (mock implementation for demo)"""
    # In production, this would use real APIs
    mock_data = {
        "tokyo population": "Tokyo metropolitan area has approximately 37.4 million people (2024)",
        "japan population": "Japan's total population is approximately 124.8 million (2024)",
    }
    
    query_lower = query.lower()
    # Check if any key words match the query
    for key, value in mock_data.items():
        # Check if all words in key are present in query
        key_words = key.split()
        if all(word in query_lower for word in key_words):
            return value
    
    return f"No specific information found for '{query}'. Try rephrasing your search."

# Create tools
calculator_tool = Tool(
    name="Calculator",
    func=calculate,
    description="Useful for mathematical calculations. Input should be a valid mathematical expression."
)

search_tool = Tool(
    name="InfoSearch",
    func=search_info,
    description="Search for general information like population data, distances, stock prices. Input should be a search query."
)

# Create the ReAct prompt for multi-tool usage
react_prompt = PromptTemplate.from_template("""Answer the following questions as best you can. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

IMPORTANT: Always use this exact format:
Action: ToolName
Action Input: your input here

Never write Action: ToolName(input) or any other format.

Example:
Question: What is 2 + 2?
Thought: I need to calculate 2 + 2
Action: Calculator
Action Input: 2 + 2
Observation: 4
Thought: I now know the final answer
Final Answer: 2 + 2 equals 4

Begin!

Question: {input}
Thought: {agent_scratchpad}""")

# Create the agent
agent = create_react_agent(
    llm=llm,
    tools=[search_tool, calculator_tool],
    prompt=react_prompt
)

# Create agent executor
agent_executor = AgentExecutor(
    agent=agent,
    tools=[search_tool, calculator_tool],
    verbose=True,
    max_iterations=5,  # Allow more iterations for complex tasks
    handle_parsing_errors=True
)

# Test query that requires multiple tools
test_query = "What is the population of Tokyo and what percentage is that of Japan's total population?"

print(f"\n{'='*60}")
print(f"Query: {test_query}")
print(f"{'='*60}")

try:
    result = agent_executor.invoke({"input": test_query})
    print(f"\nFinal Answer: {result['output']}")
except Exception as e:
    print(f"Error: {e}")

# Note: The verbose=True parameter above will show the actual reasoning process
# Similar to this example output:
"""
Example output (when verbose=True):

> Entering new AgentExecutor chain...
I need to find Tokyo's population and Japan's total population, then calculate the percentage.

Action: InfoSearch
Action Input: Tokyo population

Observation: Tokyo metropolitan area has approximately 37.4 million people (2024)
...
"""

# The actual output will vary based on the agent's reasoning

💡 Tool Selection Logic:

The agent intelligently selects tools based on the task:

  • Information needed: Uses InfoSearch tool
  • Calculations required: Uses Calculator tool
  • Multi-step problems: Combines multiple tools in sequence
  • Error handling: Retries with different approaches

🎯 Expected Result:

When you run this code, the agent will demonstrate multi-tool usage:

Tokyo Population Query - Complete Multi-Tool Flow:

  1. InfoSearch: Find Tokyo population → 37.4 million
  2. InfoSearch: Find Japan population → 124.8 million
  3. Calculator: Calculate percentage → 37.4 ÷ 124.8 × 100 = ~30%

Final Answer: Tokyo has 37.4M people, which is ~30% of Japan's 124.8M total

📖 Code Explanation:

  • Mock InfoSearch: Simulates web search without external APIs - perfect for learning
  • Smart Matching: Uses word-based matching to handle various phrasings
  • Multi-Tool Coordination: Agent automatically decides which tool to use
  • Production Ready: Replace mock data with real APIs when needed

⚠️ Troubleshooting:

If searches fail, the agent may:

  • • Retry with different phrasings
  • • Hit iteration limit (max_iterations=5)
  • • Need more specific mock data entries

Solution: Add more key-value pairs to mock_data or use real search APIs.

⚙️

How to Create Custom Tools for LangChain Agents in Python

Building Domain-Specific Tools

Create custom tools tailored to your specific business needs:

🔍 Custom Tool Components:

  • @tool decorator: Marks function as an agent tool
  • Type hints: Help agent understand input/output types
  • Docstrings: Describe tool purpose and usage for the agent
  • Error handling: Graceful failure modes
from langchain.tools import tool
from langchain.agents import create_react_agent, AgentExecutor
from langchain_core.prompts import PromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
import os
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Custom tool example - Weather information
@tool
def get_weather(city: str) -> str:
    """
    Get current weather information for a specified city.
    Useful when you need to find weather conditions, temperature, or forecast.
    
    Args:
        city: The name of the city to get weather for
        
    Returns:
        Weather information as a string
    """
    # Mock implementation - Replace with real weather API (OpenWeatherMap, etc.)
    mock_weather_data = {
        "tokyo": "Sunny, 22°C, humidity 65%, light breeze",
        "london": "Cloudy, 15°C, humidity 80%, chance of rain",
        "new york": "Partly cloudy, 18°C, humidity 60%, windy",
    }
    
    city_lower = city.lower()
    if city_lower in mock_weather_data:
        return f"Weather in {city}: {mock_weather_data[city_lower]}"
    
    return f"Weather data not available for {city}"

# Initialize LLM
llm = ChatGoogleGenerativeAI(
    model="gemini-2.0-flash",
    temperature=0
)

# Create ReAct prompt (same as before)
react_prompt = PromptTemplate.from_template("""Answer the following questions as best you can. You have access to the following tools:

{tools}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {input}
Thought: {agent_scratchpad}""")

# Create agent with custom tool
agent = create_react_agent(
    llm=llm,
    tools=[get_weather],
    prompt=react_prompt
)

# Create agent executor
agent_executor = AgentExecutor(
    agent=agent,
    tools=[get_weather],
    verbose=True,
    handle_parsing_errors=True
)

# Test the custom tool
query = "What's the weather like in Tokyo?"
print(f"Query: {query}")
print("-" * 50)

try:
    result = agent_executor.invoke({"input": query})
    print(f"\nAnswer: {result['output']}")
except Exception as e:
    print(f"Error: {e}")

💡 Key Concepts Explained:

  • @tool decorator: Converts a Python function into a LangChain tool
  • Docstring is crucial: The agent reads this to understand when/how to use the tool
  • Type hints: Help with validation (city: str) → (str)
  • Simple is better: Start with mock data, add real APIs later

🎯 Expected Output:

Query: "What's the weather like in Tokyo?"
Action: get_weather
Action Input: Tokyo
Result: Weather in Tokyo: Sunny, 22°C, humidity 65%, light breeze

🚀 Extending to Real APIs:

# Real weather API example
@tool
def get_real_weather(city: str) -> str:
    """Get real weather data from OpenWeatherMap API"""
    api_key = os.getenv("OPENWEATHER_API_KEY")
    url = f"https://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}"
    
    try:
        response = requests.get(url)
        data = response.json()
        temp_celsius = data['main']['temp'] - 273.15
        return f"Weather in {city}: {data['weather'][0]['description']}, {temp_celsius:.1f}°C"
    except:
        return f"Unable to fetch weather for {city}"
🎛️

LangChain Agent Types: Choosing the Right Agent for Your Use Case

Choosing the Right Agent Type

Different agent types are optimized for different use cases:

🤖 ZERO_SHOT_REACT_DESCRIPTION

Best for: Most general cases

Reasoning: Explicit thought process

Performance: Good balance

Tools: Works with any tools

🧠 CONVERSATIONAL_REACT_DESCRIPTION

Best for: Chat applications

Reasoning: More conversational

Performance: Great for dialogue

Memory: Built-in conversation history

⚡ STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION

Best for: Complex tool inputs

Reasoning: Structured format

Performance: Better with complex tools

Tools: Multi-parameter tools

🎯 SELF_ASK_WITH_SEARCH

Best for: Research tasks

Reasoning: Question decomposition

Performance: Great for complex queries

Tools: Requires search tool

💡 Selection Guidelines:

  • Starting out: Use ZERO_SHOT_REACT_DESCRIPTION
  • Chat applications: Use CONVERSATIONAL_REACT_DESCRIPTION
  • Complex tool inputs: Use STRUCTURED_CHAT variants
  • Research/QA: Use SELF_ASK_WITH_SEARCH

✨ Agent Development Best Practices

Tool Design

  • • Write clear, descriptive tool docstrings
  • • Use specific parameter names and types
  • • Handle errors gracefully with helpful messages
  • • Keep tools focused on single responsibilities

Agent Configuration

  • • Set appropriate max_iterations to prevent loops
  • • Use lower temperature for consistent tool usage
  • • Enable verbose mode during development
  • • Implement proper error handling and logging

🎨Common Agent Patterns

Research Agent

Web search + Calculator + Summarization tools for comprehensive research tasks

Business Assistant

Database queries + Email notifications + Calendar integration + Reporting tools

DevOps Agent

Server monitoring + Deployment tools + Log analysis + Alert management

🎉 Next Step

You've mastered agents and tools! Next, you'll learn about Document Processing & Text Splitting - the foundation for building powerful RAG (Retrieval-Augmented Generation) applications that can work with documents and knowledge bases.