跳到内容

工具

工具是一种封装函数及其输入 schema 的方式,可以将其传递给支持工具调用的聊天模型。这允许模型请求使用特定的输入执行此函数。

您可以定义自己的工具,或使用 LangChain 提供的预构建集成

定义工具

您可以使用 tool 函数创建工具

import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const multiply = tool(
  async (input: { a: number; b: number }) => {
    return input.a * input.b;
  },
  {
    name: "multiply",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Multiply two numbers.",
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [multiply],
});

有关其他自定义,请参阅自定义工具指南

向模型隐藏参数

某些工具需要仅在运行时使用的参数(例如,用户 ID 或会话上下文),这些参数不应由模型控制。

您可以将这些参数放在代理的 stateconfig 中,并在工具内部访问此信息

import { z } from "zod";
import { tool } from "@langchain/core/tools";
import {
  getCurrentTaskInput,
  LangGraphRunnableConfig,
} from "@langchain/langgraph";
import { MessagesAnnotation } from "@langchain/langgraph";

const myTool = tool(
  async (input: {
    // This will be populated by an LLM
    toolArg: string,
  },
  // access static data that is passed at agent invocation
  config: LangGraphRunnableConfig
) => {
    // Fetch the current agent state
    const state = getCurrentTaskInput() as typeof MessagesAnnotation.State;
    doSomethingWithState(state.messages);
    doSomethingWithConfig(config);
    // ...
  },
  {
    name: "myTool",
    schema: z.object({
      myToolArg: z.number().describe("Tool arg"),
    }),
    description: "My tool.",
  }
);

禁用并行工具调用

某些模型提供商支持并行执行多个工具,但允许用户禁用此功能。

对于支持的提供商,您可以通过 model.bindTools() 方法将 parallel_tool_calls 设置为 false 来禁用并行工具调用

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

const add = tool(
  async (input: { a: number; b: number }) => {
    return input.a + input.b;
  },
  {
    name: "add",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Add two numbers.",
  }
);

const multiply = tool(
  async (input: { a: number; b: number }) => {
    return input.a * input.b;
  },
  {
    name: "multiply",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Multiply two numbers.",
  }
);

const llm = new ChatOpenAI({ model: "gpt-4.1" });

const tools = [add, multiply];
const agent = createReactAgent({
  // disable parallel tool calls
  llm: llm.bindTools(tools, { parallel_tool_calls: false }),
  tools,
});

const response = await agent.invoke(
  { messages: [ { role: "user", content: "what's 3 + 5 and 4 * 7?" } ] }
);

直接返回工具结果

使用 returnDirect: true 可以立即返回工具结果并停止代理循环

import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const add = tool(
  async (input: { a: number; b: number }) => {
    return input.a + input.b;
  },
  {
    name: "add",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Add two numbers.",
    returnDirect: true
  }
);

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [add],
});

const response = await agent.invoke(
  { messages: [ { role: "user", content: "what's 3 + 5?" } ] }
);

强制使用工具

要强制代理使用特定工具,您可以在 model.bindTools() 中设置 tool_choice 选项

import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const greet = tool(
  async (input: { userName: string }) => {
    return `Hello ${input.userName}!`;
  },
  {
    name: "greet",
    schema: z.object({
      userName: z.string().describe("Name of the user to greet"),
    }),
    description: "Greet user.",
    returnDirect: true
  }
);

const llm = new ChatAnthropic({ model: "claude-3-7-sonnet-latest" });
const tools = [greet];

const agent = createReactAgent({
  llm: llm.bindTools(tools, { tool_choice: { type: "tool", name: "greet" } }),
  tools,
});

const response = await agent.invoke({
  messages: "Hi, I am Bob"
});

避免无限循环

在没有停止条件的情况下强制使用工具可能会产生无限循环。请使用以下任一安全措施

处理工具错误

默认情况下,代理会捕获工具调用期间引发的所有异常,并将这些异常作为工具消息传递给 LLM。要控制错误的处理方式,您可以使用预构建的 ToolNode(即在 createReactAgent 内部执行工具的节点)的 handleToolErrors 参数

import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";

const multiply = tool(
  async (input: { a: number; b: number }) => {
    if (input.a === 42) {
      throw new Error("The ultimate error");
    }
    return input.a * input.b;
  },
  {
    name: "multiply",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Multiply two numbers.",
  }
);

// Run with error handling (default)
const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agent = createReactAgent({
  llm,
  tools: [multiply],
});

const response = await agent.invoke(
  { messages: [ { role: "user", content: "what's 42 x 7?" } ] }
);
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { initChatModel } from "langchain/chat_models/universal";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
import { ToolNode } from "@langchain/langgraph/prebuilt";

const multiply = tool(
  async (input: { a: number; b: number }) => {
    if (input.a === 42) {
      throw new Error("The ultimate error");
    }
    return input.a * input.b;
  },
  {
    name: "multiply",
    schema: z.object({
      a: z.number().describe("First operand"),
      b: z.number().describe("Second operand"),
    }),
    description: "Multiply two numbers.",
  }
);

const toolNode = new ToolNode({
  tools: [multiply],
  handleToolErrors: false, // (1)!
});

const llm = await initChatModel("anthropic:claude-3-7-sonnet-latest");
const agentNoErrorHandling = createReactAgent({
  llm,
  tools: toolNode,
});

const response = await agentNoErrorHandling.invoke(
  { messages: [ { role: "user", content: "what's 42 x 7?" } ] }
);
  1. 这将禁用错误处理(默认已启用)。

预构建工具

LangChain 支持广泛的预构建工具集成,用于与 API、数据库、文件系统、Web 数据等进行交互。这些工具扩展了代理的功能,并支持快速开发。

您可以在LangChain 集成目录中浏览所有可用集成的完整列表。

一些常用的工具类别包括

  • 搜索:Exa、SerpAPI、Tavily
  • 代码解释器:Python REPL
  • 数据库:SQL、MongoDB、Redis
  • Web 数据:Web 抓取和浏览
  • API:Discord、Gmail 及其他

可以使用上面示例中所示的相同 tools 参数配置这些集成并将其添加到您的代理中。