TypeScript framework for building LLM-powered applications with agents, tools, middleware, and model interoperability
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
docs