10 LangChain Tools: Web Search, Calculator, Python REPL
Master 10 essential LangChain tools including SerpAPI, TavilySearch, Calculator, Python REPL, and custom tools with @tool decorator for building AI agents.
Get more content like this on Telegram!
Daily AI tips, notes & resources — free
I spent a weekend building an AI research assistant that kept hitting the same wall: my LangChain agent could reason fine, but it had no way to do anything. No web access, no math, no code execution. The agent was basically a very expensive autocomplete. Once I wired in tools, the whole thing clicked. The agent started pulling live data, running calculations, and executing code to verify its own answers.
This guide covers the 10 most useful LangChain tools, with actual working code for each one. We'll start with the built-ins, cover the popular search options, and end with building your own custom tools using the @tool decorator. If you're new to agents, check out the LangChain tutorial 2025 first — it covers the foundation you'll need here.
What LangChain Tools Actually Are
A tool in LangChain is just a function wrapped with a name, description, and schema. The description is critical — it's what the LLM reads when deciding whether to use the tool. A vague description like "search tool" will cause your agent to misuse or ignore it. A precise description like "searches the web for current events, news, and real-time data" tells the agent exactly when to reach for it.
Every tool has three key parts:
from langchain.tools import BaseTool
from pydantic import BaseModel, Field
class SearchInput(BaseModel):
query: str = Field(description="The search query to look up")
class MyTool(BaseTool):
name = "web_search"
description = "Searches the web for current information. Use when you need recent news or facts."
args_schema = SearchInput
def _run(self, query: str) -> str:
# actual logic here
return f"Results for: {query}"
async def _arun(self, query: str) -> str:
# async version
return self._run(query)
You'll use the @tool decorator for simple cases, BaseTool subclasses for anything that needs error handling, async support, or complex state. Let's get into the actual tools.
Tool 1: TavilySearch (Recommended for Most Agents)
Tavily is purpose-built for AI agents. It returns clean, structured results rather than raw HTML, which means your LLM doesn't have to parse garbage. I switched from SerpAPI to Tavily for most projects and the response quality improved noticeably.
pip install langchain-community tavily-python
import os
from langchain_community.tools.tavily_search import TavilySearchResults
os.environ["TAVILY_API_KEY"] = "your-tavily-key"
# Basic setup
search_tool = TavilySearchResults(
max_results=5,
search_depth="advanced", # "basic" or "advanced"
include_answer=True, # returns a direct answer
include_raw_content=False
)
# Direct usage
results = search_tool.invoke({"query": "LangChain latest version 2026"})
for r in results:
print(r['title'])
print(r['url'])
print(r['content'][:200])
print("---")
For agents, just pass it in the tools list:
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent
llm = ChatOpenAI(model="gpt-4o", temperature=0)
tools = [search_tool]
agent = create_react_agent(llm, tools)
result = agent.invoke({"messages": [("human", "What are the newest AI models released this week?")]})
print(result["messages"][-1].content)
Tool 2: SerpAPI (Google Results for Production)
SerpAPI gives you actual Google search results. It's more expensive than Tavily but essential when you specifically need Google's ranking, news, or shopping results.
pip install google-search-results
from langchain_community.utilities import SerpAPIWrapper
from langchain.tools import Tool
os.environ["SERPAPI_API_KEY"] = "your-serpapi-key"
search = SerpAPIWrapper()
# Wrap as a LangChain tool
serpapi_tool = Tool(
name="google_search",
description="Search Google for recent results. Use for current events, news, and web information.",
func=search.run
)
# Test it
result = serpapi_tool.run("Python LangChain agent tutorial 2026")
print(result)
SerpAPI also supports params for different search types:
search_with_params = SerpAPIWrapper(
params={
"engine": "google",
"hl": "en",
"gl": "us",
"num": 10 # number of results
}
)
Tool 3: DuckDuckGo Search (Free, No API Key)
If you're prototyping and don't want to deal with API keys, DuckDuckGo is your friend. It's free, requires no setup, and works surprisingly well for general queries.
pip install duckduckgo-search
from langchain_community.tools import DuckDuckGoSearchRun, DuckDuckGoSearchResults
# Simple version — returns a string
ddg_search = DuckDuckGoSearchRun()
result = ddg_search.run("what is LangGraph")
print(result)
# Detailed version — returns structured results
ddg_results = DuckDuckGoSearchResults(num_results=5)
results = ddg_results.run("LangChain tools tutorial")
print(results)
The downside: DuckDuckGo rate-limits aggressively if you're making lots of calls. For production, upgrade to Tavily or SerpAPI.
Tool 4: Calculator / LLM Math
LLMs are notoriously bad at arithmetic. Even GPT-4 makes multiplication errors. The LLMMath tool routes math queries to a separate math-focused chain that's much more reliable.
from langchain.chains import LLMMathChain
from langchain.tools import Tool
from langchain_openai import OpenAI
llm = OpenAI(temperature=0)
math_chain = LLMMathChain.from_llm(llm=llm, verbose=True)
calculator_tool = Tool(
name="calculator",
description="Useful for answering math questions. Input should be a math expression or word problem.",
func=math_chain.run
)
# Test
result = calculator_tool.run("What is 847 * 293 + 1,847?")
print(result)
# Also works for unit conversions and word problems
result2 = calculator_tool.run("If a car travels at 65 mph for 3.5 hours, how far does it go?")
print(result2)
For simple arithmetic without the overhead of an LLM chain, you can build a lightweight calculator:
from langchain.tools import tool
@tool
def basic_calculator(expression: str) -> str:
"""Evaluates a mathematical expression. Input must be a valid Python math expression."""
try:
# safe eval with only math operations
import ast
import operator
allowed_ops = {
ast.Add: operator.add,
ast.Sub: operator.sub,
ast.Mult: operator.mul,
ast.Div: operator.truediv,
ast.Pow: operator.pow,
ast.USub: operator.neg
}
def eval_expr(node):
if isinstance(node, ast.Constant):
return node.value
elif isinstance(node, ast.BinOp):
return allowed_ops[type(node.op)](eval_expr(node.left), eval_expr(node.right))
elif isinstance(node, ast.UnaryOp):
return allowed_ops[type(node.op)](eval_expr(node.operand))
else:
raise ValueError(f"Unsupported operation")
tree = ast.parse(expression, mode='eval')
result = eval_expr(tree.body)
return str(result)
except Exception as e:
return f"Error: {str(e)}"
Tool 5: Python REPL (Code Execution)
This is the one that separates amateur agents from capable ones. The Python REPL lets your agent write and execute code, check results, and iterate. It's how you get agents that can analyze data, run simulations, or verify their own reasoning.
from langchain_experimental.tools.python.tool import PythonREPLTool
python_repl = PythonREPLTool()
# The agent can now write and run Python
result = python_repl.run("""
import pandas as pd
import json
data = {"sales": [100, 200, 150, 300, 250], "months": ["Jan", "Feb", "Mar", "Apr", "May"]}
df = pd.DataFrame(data)
print(f"Total sales: {df['sales'].sum()}")
print(f"Average: {df['sales'].mean()}")
print(f"Best month: {df.loc[df['sales'].idxmax(), 'months']}")
""")
print(result)
Security warning: The Python REPL executes arbitrary code. Never expose it to untrusted user input in production. For safer execution, use a sandboxed environment or restrict the available modules.
# Safer version with restricted imports
from langchain.tools import tool
ALLOWED_IMPORTS = {"math", "statistics", "json", "datetime", "collections"}
@tool
def safe_python_repl(code: str) -> str:
"""Executes safe Python code for data analysis. Only math, statistics, json, datetime allowed."""
import re
# Check for dangerous patterns
dangerous = ["import os", "import sys", "subprocess", "open(", "__import__", "exec(", "eval("]
for pattern in dangerous:
if pattern in code:
return f"Error: '{pattern}' is not allowed for security reasons."
try:
exec_globals = {"__builtins__": __builtins__}
exec(code, exec_globals)
return "Code executed successfully"
except Exception as e:
return f"Error: {str(e)}"
Tool 6: WikipediaQueryRun
Wikipedia is underrated as an agent tool. It's great for factual background information, definitions, historical context — things where you need reliable encyclopedic data rather than current news.
pip install wikipedia
from langchain_community.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper
wiki_wrapper = WikipediaAPIWrapper(
top_k_results=3,
doc_content_chars_max=2000 # limit content length
)
wiki_tool = WikipediaQueryRun(api_wrapper=wiki_wrapper)
# Test
result = wiki_tool.run("transformer neural network architecture")
print(result[:500])
The doc_content_chars_max parameter is important — without it, Wikipedia articles can bloat your context window and increase token costs significantly.
Tool 7: Requests / Web Scraping Tool
Sometimes you need to fetch a specific URL rather than search. The requests toolkit gives your agent the ability to GET or POST to any URL.
from langchain_community.agent_toolkits.load_tools import load_tools
# Load the requests toolkit
tools = load_tools(["requests_all"])
# Or more specifically
from langchain_community.tools.requests.tool import RequestsGetTool
from langchain_community.utilities.requests import TextRequestsWrapper
requests_tool = RequestsGetTool(
requests_wrapper=TextRequestsWrapper(headers={}),
allow_dangerous_requests=True # required flag
)
result = requests_tool.run("https://api.github.com/repos/langchain-ai/langchain/releases/latest")
print(result[:500])
Tool 8: Custom Tool with @tool Decorator
This is where things get interesting. Most production agents need at least one custom tool — something specific to your application. The @tool decorator makes this trivial.
from langchain.tools import tool
from typing import Optional
import requests
@tool
def get_weather(city: str, units: str = "metric") -> str:
"""
Gets current weather for a city.
Args:
city: The city name to get weather for
units: Temperature units - 'metric' for Celsius, 'imperial' for Fahrenheit
Returns current temperature, conditions, and humidity.
"""
api_key = os.environ.get("OPENWEATHER_API_KEY")
url = f"https://api.openweathermap.org/data/2.5/weather"
params = {"q": city, "appid": api_key, "units": units}
try:
response = requests.get(url, params=params, timeout=10)
data = response.json()
if response.status_code == 200:
temp = data["main"]["temp"]
feels = data["main"]["feels_like"]
description = data["weather"][0]["description"]
humidity = data["main"]["humidity"]
unit_symbol = "°C" if units == "metric" else "°F"
return (f"Weather in {city}: {description}, "
f"Temperature: {temp}{unit_symbol} (feels like {feels}{unit_symbol}), "
f"Humidity: {humidity}%")
else:
return f"Error: {data.get('message', 'Unknown error')}"
except Exception as e:
return f"Failed to get weather: {str(e)}"
@tool
def query_company_database(company_name: str) -> str:
"""
Queries internal company database for business information.
Use when user asks about specific company data, revenue, employees, or headquarters.
Args:
company_name: Name of the company to look up
"""
# Mock database — replace with your actual DB query
companies = {
"acme corp": {"revenue": "$50M", "employees": 200, "founded": 1995},
"techstart": {"revenue": "$5M", "employees": 25, "founded": 2020}
}
key = company_name.lower()
if key in companies:
data = companies[key]
return f"{company_name}: Revenue {data['revenue']}, {data['employees']} employees, founded {data['founded']}"
return f"No data found for {company_name}"
The docstring is your tool's sales pitch to the LLM. Write it like you're explaining to a colleague when to use this function, not like API documentation.
Tool 9: File System Tools
For agents that need to read and write files:
from langchain_community.agent_toolkits import FileManagementToolkit
import tempfile
# Create a temporary working directory for the agent
working_dir = tempfile.mkdtemp()
file_toolkit = FileManagementToolkit(
root_dir=working_dir, # restrict to this directory for safety
selected_tools=["read_file", "write_file", "list_directory"]
)
file_tools = file_toolkit.get_tools()
# Now agent can read/write files within the working directory
for tool in file_tools:
print(f"Tool: {tool.name} - {tool.description[:60]}")
Tool 10: Human-in-the-Loop Tool
Sometimes the agent genuinely can't proceed without asking a human. This tool pauses execution and waits for input:
from langchain.tools import tool
@tool
def ask_human(question: str) -> str:
"""
Ask the human user a clarifying question when you're uncertain or need additional information.
Use this when you need information that can't be found through other tools.
Args:
question: The specific question to ask the human
"""
print(f"\n[AGENT QUESTION]: {question}")
human_input = input("Your answer: ").strip()
return f"Human responded: {human_input}"
Putting It All Together
Here's a complete agent with multiple tools wired in:
import os
from langchain_openai import ChatOpenAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_community.tools import WikipediaQueryRun, DuckDuckGoSearchRun
from langchain_community.utilities import WikipediaAPIWrapper
from langchain_experimental.tools.python.tool import PythonREPLTool
from langchain.tools import tool
from langgraph.prebuilt import create_react_agent
os.environ["OPENAI_API_KEY"] = "your-key"
os.environ["TAVILY_API_KEY"] = "your-key"
# Build tool list
tavily_search = TavilySearchResults(max_results=5)
wiki = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper(top_k_results=2))
python_repl = PythonREPLTool()
@tool
def calculate(expression: str) -> str:
"""Evaluates a math expression. Input should be a valid Python arithmetic expression."""
try:
result = eval(expression, {"__builtins__": {}}, {"abs": abs, "round": round, "max": max, "min": min})
return str(result)
except Exception as e:
return f"Error: {e}"
tools = [tavily_search, wiki, python_repl, calculate]
llm = ChatOpenAI(model="gpt-4o", temperature=0)
agent = create_react_agent(llm, tools)
# Run a complex multi-tool query
messages = [("human", "Search for the current population of Tokyo, then calculate what percentage that is of Japan's total population of 125 million. Show your calculation.")]
result = agent.invoke({"messages": messages})
print(result["messages"][-1].content)
Tool Comparison Table
| Tool | API Key Required | Cost | Best For | Latency |
|---|---|---|---|---|
| TavilySearch | Yes (free tier) | Low | Agent-optimized search | ~500ms |
| SerpAPI | Yes (paid) | Medium | Google-specific results | ~800ms |
| DuckDuckGo | No | Free | Prototyping | ~600ms |
| WikipediaQueryRun | No | Free | Factual/background info | ~300ms |
| Python REPL | No | Free | Code execution, analysis | <00ms |
| LLMMath | No | LLM tokens | Word-problem math | ~1s |
| RequestsGet | No | Free | Fetching specific URLs | Varies |
| FileManagement | No | Free | File I/O | <0ms |
| Custom @tool | Depends | Depends | Application-specific | Depends |
| HumanInputTool | No | Free | Clarification | N/A |
According to LangChain's 2025 state-of-agents report, 78% of production agent deployments use between 3 and 7 tools — more than that tends to confuse the model about which tool to pick.
Common Mistakes and How to Avoid Them
Bad tool descriptions tank agent performance. I've seen agents fail repeatedly because a tool description said "search for information" — the agent had no idea when to use it over another search tool. Be specific.
Forget to handle tool errors. Network requests fail. APIs return 500s. Your tool should always return a string, even on error. If your tool throws an exception, the agent crashes rather than recovering gracefully.
Too many similar tools. If you give the agent three different search tools without clear differentiation, it'll pick randomly. Either consolidate or make the descriptions very distinct — "use for Google results", "use for Wikipedia only", "use for real-time financial data."
For more on structuring agents that use these tools effectively, see Build AI agent with LangChain and AI agent memory and planning.
If you're pairing these tools with a RAG system, the RAG system tutorial shows how to combine retrieval with tool use in a single agent. And for vector search specifically, Vector database guide covers the underlying tech.
The OpenAI API integration guide is also worth reading — most of these tools work best when paired with a well-configured OpenAI client.
Conclusion
LangChain tools are what turn an LLM from a text generator into an agent that can actually act on the world. Start with TavilySearch for web access, Python REPL for code execution, and a custom @tool function for whatever is specific to your application. Get those three working well before adding more — tool bloat is a real problem that makes agents unpredictable.
The @tool decorator is genuinely elegant. A docstring and a type hint are all the LLM needs to use your function correctly. If your tools are well-described and your errors are handled cleanly, the rest mostly takes care of itself.
Ready to go deeper? Check out the AI research agent build guide which shows a complete multi-tool research agent built from scratch, and Deploy AI model to production when you're ready to ship.
Frequently Asked Questions
What is the difference between SerpAPI and TavilySearch in LangChain?
SerpAPI scrapes Google results and requires a paid API key, making it better for production use. TavilySearch is an AI-native search tool built specifically for agents, offering cleaner structured results. Tavily is generally recommended for LangChain agents because it returns focused summaries rather than raw HTML.
Can I use LangChain tools without an agent?
Yes. You can call any LangChain tool directly by invoking tool.run('your query') or tool.invoke({'query': 'your query'}). Tools are just callable objects. Agents simply automate the decision of which tool to call and when.
How do I create a custom LangChain tool?
Use the @tool decorator on any Python function. Add a clear docstring — the agent uses this to decide when to call the tool. You can also inherit from BaseTool for more control, including custom error handling and async support.
Frequently Asked Questions
AiTechWorlds Team
✓ Verified WriterThe AiTechWorlds team is passionate about AI, technology, and education. We create high-quality, research-backed content to help you learn, grow, and succeed in the modern digital world.
Related Articles
7 AutoGen Termination Conditions (Max Rounds, Human Approval)
Master all 7 AutoGen termination conditions including is_termination_msg, max_turns, and human approval patterns to stop agent loops reliably and safely.
AutoGen Tutorial: Microsoft's Multi-Agent Framework (2026)
Learn Microsoft AutoGen from scratch in 2026 — install, first agent conversation, GroupChat, and a full comparison of AutoGen 0.2 vs 0.4 features.
AutoGen vs LangChain: Which for Multi-Agent Systems in 2026?
AutoGen vs LangChain for multi-agent systems in 2026 — feature comparison, same use case in both frameworks, and an honest verdict on when each wins.
How to Use AutoGen with Tools (Web Scraper, Calculator, File)
Learn how to equip AutoGen agents with custom tools like web scrapers, calculators, and file handlers using register_for_llm and register_for_execution.