Skip to main content

Overview

Tools allow language models to interact with external systems, APIs, and databases. LangChain provides flexible tool abstractions for defining and using tools.

Tool Function

The simplest way to create a tool: Import:
import { tool } from "@langchain/core/tools";
import { z } from "zod";
Example:
const weatherTool = tool(
  async ({ location }) => {
    // Implementation
    return `Weather in ${location}: Sunny, 72°F`;
  },
  {
    name: "get_weather",
    description: "Get the current weather for a location",
    schema: z.object({
      location: z.string().describe("The city name")
    })
  }
);

const result = await weatherTool.invoke({ location: "San Francisco" });

StructuredTool

Class-based tool definition with schema validation.
import { StructuredTool } from "@langchain/core/tools";
import { z } from "zod";

class CalculatorTool extends StructuredTool {
  name = "calculator";
  description = "Evaluate a mathematical expression";
  
  schema = z.object({
    expression: z.string().describe("The expression to evaluate")
  });

  async _call({ expression }: z.infer<typeof this.schema>) {
    try {
      return String(eval(expression));
    } catch (error) {
      return `Error: ${error.message}`;
    }
  }
}

const calculator = new CalculatorTool();

DynamicTool

Create tools without schema validation:
import { DynamicTool } from "@langchain/core/tools";

const simpleTool = new DynamicTool({
  name: "random_number",
  description: "Generate a random number",
  func: async () => String(Math.random())
});

DynamicStructuredTool

Create structured tools without extending a class:
import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";

const searchTool = new DynamicStructuredTool({
  name: "web_search",
  description: "Search the web for information",
  schema: z.object({
    query: z.string(),
    limit: z.number().optional()
  }),
  func: async ({ query, limit = 10 }) => {
    // Perform search
    return `Found ${limit} results for "${query}"`;
  }
});

Tool Properties

name
string
required
The tool name (must be unique)
description
string
required
Description of what the tool does (helps the model choose when to use it)
schema
ZodSchema
required
Zod schema defining the tool’s input parameters
returnDirect
boolean
If true, return tool output directly without further model processing Default: false

Tool Response Formats

Content-Only Response

const tool = tool(
  async ({ query }) => {
    return "Search results...";
  },
  { name: "search", schema: z.object({ query: z.string() }) }
);

Content + Artifact Response

const tool = tool(
  async ({ code }) => {
    const result = executeCode(code);
    return {
      content: `Executed successfully. Output: ${result.output}`,
      artifact: result.fullData
    };
  },
  { 
    name: "code_executor",
    schema: z.object({ code: z.string() }),
    responseFormat: "content_and_artifact"
  }
);

Using Tools with Models

import { ChatOpenAI } from "@langchain/openai";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const tools = [
  tool(
    async ({ a, b }) => String(a + b),
    {
      name: "add",
      description: "Add two numbers",
      schema: z.object({
        a: z.number(),
        b: z.number()
      })
    }
  ),
  tool(
    async ({ a, b }) => String(a * b),
    {
      name: "multiply",
      description: "Multiply two numbers",
      schema: z.object({
        a: z.number(),
        b: z.number()
      })
    }
  )
];

const model = new ChatOpenAI().bindTools(tools);

const response = await model.invoke([
  ["human", "What is 25 + 17?"]
]);

if (response.tool_calls && response.tool_calls.length > 0) {
  const toolCall = response.tool_calls[0];
  const tool = tools.find(t => t.name === toolCall.name);
  const result = await tool.invoke(toolCall.args);
  console.log(result); // "42"
}

Runtime Context

Access runtime information in tools:
import { tool } from "@langchain/core/tools";

const contextTool = tool(
  async ({ query }, config) => {
    const userId = config?.configurable?.userId;
    return `Searching for ${query} (user: ${userId})`;
  },
  {
    name: "search",
    schema: z.object({ query: z.string() })
  }
);

await contextTool.invoke(
  { query: "cats" },
  { configurable: { userId: "alice" } }
);

Tool Collections

Organize related tools:
const mathTools = [
  addTool,
  subtractTool,
  multiplyTool,
  divideTool
];

const searchTools = [
  webSearchTool,
  documentSearchTool,
  imageSearchTool
];

const allTools = [...mathTools, ...searchTools];

const model = new ChatOpenAI().bindTools(allTools);

Error Handling

const safeTool = tool(
  async ({ expression }) => {
    try {
      return String(eval(expression));
    } catch (error) {
      return `Error: ${error.message}. Please provide a valid expression.`;
    }
  },
  {
    name: "calculator",
    description: "Evaluate mathematical expressions",
    schema: z.object({ expression: z.string() })
  }
);

Creating Tools Guide

Complete guide to building tools

Agents

Using tools with agents

Build docs developers (and LLMs) love