docs
This guide covers creating and using tools to give agents the ability to take actions.
import { tool } from "langchain";
import { z } from "zod";
const calculator = tool(
async ({ expression }) => {
try {
return String(eval(expression));
} catch (error) {
return `Error: ${error.message}`;
}
},
{
name: "calculator",
description: "Evaluate mathematical expressions. Use for arithmetic calculations.",
schema: z.object({
expression: z.string().describe("The mathematical expression to evaluate"),
}),
}
);import { tool } from "langchain";
import { z } from "zod";
const searchDatabase = tool(
async ({ query, filters, limit }) => {
const results = await database.search({
query,
filters,
limit,
});
return JSON.stringify(results, null, 2);
},
{
name: "search_database",
description: "Search the database with optional filters and result limit",
schema: z.object({
query: z.string().describe("Search query string"),
filters: z.object({
category: z.string().optional(),
dateFrom: z.string().optional(),
dateTo: z.string().optional(),
}).optional().describe("Optional filters"),
limit: z.number().default(10).describe("Maximum number of results"),
}),
}
);import { tool } from "langchain";
import { z } from "zod";
const getWeather = tool(
async ({ location, units }) => {
const response = await fetch(
`https://api.weather.com/${location}?units=${units}`
);
if (!response.ok) {
return `Error: Failed to fetch weather data`;
}
const data = await response.json();
return JSON.stringify(data);
},
{
name: "get_weather",
description: "Get current weather for a location",
schema: z.object({
location: z.string().describe("City name or zip code"),
units: z.enum(["celsius", "fahrenheit"]).default("celsius"),
}),
}
);import { tool } from "langchain";
import { z } from "zod";
const sendEmail = tool(
async ({ to, subject, body }) => {
try {
await emailService.send({ to, subject, body });
return `Email sent successfully to ${to}`;
} catch (error) {
return `Failed to send email: ${error.message}`;
}
},
{
name: "send_email",
description: "Send an email to a recipient",
schema: z.object({
to: z.string().email().describe("Recipient email address"),
subject: z.string().describe("Email subject"),
body: z.string().describe("Email body content"),
}),
}
);import { tool } from "langchain";
import { z } from "zod";
const apiCall = tool(
async ({ endpoint, method, body }) => {
try {
const response = await fetch(endpoint, {
method,
headers: { "Content-Type": "application/json" },
body: body ? JSON.stringify(body) : undefined,
});
if (!response.ok) {
return `Error: HTTP ${response.status} - ${response.statusText}`;
}
const data = await response.json();
return JSON.stringify(data);
} catch (error) {
return `Error: ${error.message}`;
}
},
{
name: "api_call",
description: "Make an API call to a specified endpoint",
schema: z.object({
endpoint: z.string().url().describe("API endpoint URL"),
method: z.enum(["GET", "POST", "PUT", "DELETE"]).default("GET"),
body: z.any().optional().describe("Request body for POST/PUT"),
}),
}
);import { tool } from "langchain";
import { z } from "zod";
const personalizedGreeting = tool(
async ({ name }, config) => {
// Access runtime configuration
const userId = config?.configurable?.user_id;
const preferences = await loadUserPreferences(userId);
return `Hello ${name}! ${preferences.greeting_style}`;
},
{
name: "personalized_greeting",
description: "Generate a personalized greeting",
schema: z.object({
name: z.string().describe("Name to greet"),
}),
}
);import { createAgent, tool } from "langchain";
import { z } from "zod";
const calculator = tool(
async ({ expression }) => String(eval(expression)),
{
name: "calculator",
description: "Evaluate mathematical expressions",
schema: z.object({
expression: z.string(),
}),
}
);
const agent = createAgent({
model: "openai:gpt-4o",
tools: [calculator],
});
const result = await agent.invoke({
messages: [{ role: "user", content: "What is 25 * 4?" }],
});import { createAgent, tool } from "langchain";
import { z } from "zod";
const add = tool(
async ({ a, b }) => String(a + b),
{
name: "add",
description: "Add two numbers",
schema: z.object({ a: z.number(), b: z.number() }),
}
);
const multiply = tool(
async ({ a, b }) => String(a * b),
{
name: "multiply",
description: "Multiply two numbers",
schema: z.object({ a: z.number(), b: z.number() }),
}
);
const divide = tool(
async ({ a, b }) => {
if (b === 0) return "Error: Division by zero";
return String(a / b);
},
{
name: "divide",
description: "Divide two numbers",
schema: z.object({ a: z.number(), b: z.number() }),
}
);
const agent = createAgent({
model: "openai:gpt-4o",
tools: [add, multiply, divide],
});
const result = await agent.invoke({
messages: [{ role: "user", content: "What is (10 + 5) * 3?" }],
});// Organize tools by category
const mathTools = [addTool, multiplyTool, divideTool];
const searchTools = [webSearchTool, databaseSearchTool];
const communicationTools = [sendEmailTool, sendSlackTool];
// Create agent with all tools
const agent = createAgent({
model: "openai:gpt-4o",
tools: [...mathTools, ...searchTools, ...communicationTools],
});import { tool } from "langchain";
import { z } from "zod";
const longTask = tool(
async ({ taskId }) => {
// Start background job
const job = await jobQueue.submit(taskId);
// Wait for completion
const result = await job.wait({ timeout: 30000 });
return `Task ${taskId} completed: ${result}`;
},
{
name: "long_task",
description: "Execute a long-running background task",
schema: z.object({
taskId: z.string().describe("Task identifier"),
}),
}
);import { tool } from "langchain";
import { z } from "zod";
const createUser = tool(
async ({ email, age, username }) => {
// Additional runtime validation
if (await userExists(email)) {
return "Error: User with this email already exists";
}
const user = await database.createUser({ email, age, username });
return `User created: ${user.id}`;
},
{
name: "create_user",
description: "Create a new user account",
schema: z.object({
email: z.string().email(),
age: z.number().min(13).max(120),
username: z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/),
}),
}
);import { tool } from "langchain";
import { z } from "zod";
import { RateLimiter } from "limiter";
const limiter = new RateLimiter({ tokensPerInterval: 10, interval: "minute" });
const apiCall = tool(
async ({ endpoint }) => {
// Check rate limit
const allowed = await limiter.removeTokens(1);
if (!allowed) {
return "Error: Rate limit exceeded. Please try again later.";
}
const response = await fetch(endpoint);
const data = await response.json();
return JSON.stringify(data);
},
{
name: "rate_limited_api",
description: "Make rate-limited API call",
schema: z.object({
endpoint: z.string().url(),
}),
}
);import { tool } from "langchain";
import { z } from "zod";
const cache = new Map();
const expensiveOperation = tool(
async ({ input }) => {
// Check cache
if (cache.has(input)) {
return cache.get(input);
}
// Perform expensive operation
const result = await performExpensiveComputation(input);
// Cache result
cache.set(input, result);
return result;
},
{
name: "expensive_operation",
description: "Perform cached expensive operation",
schema: z.object({
input: z.string(),
}),
}
);import { tool } from "langchain";
import { z } from "zod";
const resilientApiCall = tool(
async ({ url }) => {
const maxRetries = 3;
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
return JSON.stringify(data);
} catch (error) {
lastError = error;
if (i < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
return `Error after ${maxRetries} attempts: ${lastError.message}`;
},
{
name: "resilient_api_call",
description: "Make API call with automatic retries",
schema: z.object({
url: z.string().url(),
}),
}
);import { DynamicTool } from "langchain";
const weatherTool = new DynamicTool({
name: "get_weather",
description: "Get weather for a location (pass location as string)",
func: async (input: string) => {
const response = await fetch(`https://api.weather.com/${input}`);
const data = await response.json();
return JSON.stringify(data);
},
});import { DynamicStructuredTool } from "langchain";
import { z } from "zod";
const weatherTool = new DynamicStructuredTool({
name: "get_weather",
description: "Get weather for a location",
schema: z.object({
location: z.string().describe("City name"),
units: z.enum(["celsius", "fahrenheit"]).default("celsius"),
}),
func: async ({ location, units }) => {
const response = await fetch(
`https://api.weather.com/${location}?units=${units}`
);
const data = await response.json();
return JSON.stringify(data);
},
});import { Tool } from "langchain";
class CustomTool extends Tool {
name = "custom_tool";
description = "A custom tool implementation";
async _call(input: string): Promise<string> {
// Implement tool logic
return `Processed: ${input}`;
}
}
const tool = new CustomTool();import { StructuredTool } from "langchain";
import { z } from "zod";
class CustomStructuredTool extends StructuredTool {
name = "custom_structured_tool";
description = "A custom structured tool";
schema = z.object({
query: z.string(),
limit: z.number().optional(),
});
async _call({ query, limit = 10 }): Promise<string> {
// Implement tool logic
const results = await search(query, limit);
return JSON.stringify(results);
}
}
const tool = new CustomStructuredTool();search_web, create_task, send_email.describe() on all fields to help the LLMz.enum() for constrained choicesSee Tool API Reference for complete API documentation.