类型提示是必需的,因为它们定义了工具的输入模式。文档字符串应该信息丰富且简洁,以帮助模型理解工具的用途。
服务器端工具使用: 一些聊天模型具有内置工具(网页搜索、代码解释器),这些工具由模型提供商在服务器端执行。有关详细信息,请参阅服务器端工具使用。
工具名称优先使用 snake_case(例如,使用 web_search 而不是 Web Search)。某些模型提供商对于包含空格或特殊字符的名称存在兼容性问题或会报错。坚持使用字母数字字符、下划线和连字符有助于提高跨提供商的兼容性。

自定义工具属性

自定义工具名称

默认情况下,工具名称来自函数名。当你需要更具描述性的名称时,可以覆盖它:

自定义工具描述

覆盖自动生成的工具描述,为模型提供更清晰的指导:

高级模式定义

使用 Pydantic 模型或 JSON 模式定义复杂的输入:

保留的参数名称

以下参数名称是保留的,不能用作工具参数。使用这些名称会导致运行时错误。 要访问运行时信息,请使用 @[ToolRuntime] 参数,而不是将你自己的参数命名为 config 或 runtime。 如果你使用 InjectedState、InjectedStore、get_runtime() 或 InjectedToolCallId,请参阅从旧版注入模式迁移。

访问上下文

当工具能够访问运行时信息(如对话历史、用户数据和持久化内存)时,它们最为强大。本节介绍如何从工具内部访问和更新这些信息。 工具可以通过 @[ToolRuntime] 参数访问运行时信息,该参数提供:

短期记忆 (状态)

状态代表在对话持续期间存在的短期记忆。它包括消息历史和你在图状态中定义的任何自定义字段。
在工具签名中添加 runtime: ToolRuntime 以访问状态。此参数是自动注入的,并且对 LLM 隐藏——它不会出现在工具的模式中。

访问状态

工具可以使用 runtime.state 访问当前对话状态:
runtime 参数对模型是隐藏的。在上面的例子中,模型在工具模式中只能看到 pref_name。

更新状态

使用 @[Command] 来更新智能体的状态。这对于需要更新自定义状态字段的工具很有用。 在更新中包含一个 ToolMessage,以便模型可以看到工具调用的结果:
当工具更新状态变量时,请考虑为这些字段定义一个归约器。由于 LLM 可以并行调用多个工具,归约器决定了当同一个状态字段被并发工具调用更新时如何解决冲突。

上下文

上下文提供在调用时传递的不可变配置数据。用于用户 ID、会话详情或应用程序特定设置等在对话过程中不应更改的信息。
虽然 thread_id(通过 config={"configurable": {"thread_id": ...}} 传递)界定对话:消息历史和检查点,但 context 携带的是你的工具和中间件在调用时读取的每次运行数据。在生产环境中,你通常同时传递两者:每个对话一个稳定的 thread_id,以及每次调用时传递一个 context 对象。
通过 runtime.context 访问上下文。将其与 thread_id 一起传递,以便对话在多轮次间得以持久化:

长期记忆 (存储)

@[BaseStore] 提供跨对话持久存在的存储。与状态(短期记忆)不同,保存到存储的数据在未来的会话中仍然可用。 通过 runtime.store 访问存储。存储使用命名空间/键模式来组织数据:
对于生产部署,请使用 @[PostgresStore]、MongoDBStore 或 RedisStore 等持久化存储实现,而不是 InMemoryStore。有关设置详情,请参阅记忆文档。

流写入器

在工具执行期间流式传输实时更新。这对于在长时间运行的操作中为用户提供进度反馈非常有用。 使用 runtime.stream_writer 发出自定义更新:
如果你在工具内部使用 runtime.stream_writer,则该工具必须在 LangGraph 执行上下文中调用。有关更多详细信息,请参阅流式传输。

执行信息

通过 runtime.execution_info 从工具内部访问线程 ID、运行 ID 和重试状态:
需要 deepagents>=0.5.0(或 langgraph>=1.1.5)。

服务器信息

当你的工具在 LangGraph Server 上运行时,可以通过 runtime.server_info 访问助手 ID、图 ID 和已认证的用户:
当工具未在 LangGraph Server 上运行时(例如在本地开发或测试期间),server_info 为 None。
需要 deepagents>=0.5.0(或 langgraph>=1.1.5)。
旧的示例使用 InjectedState、InjectedStore、get_runtime() 或 InjectedToolCallId。请改用 @[ToolRuntime],作为访问状态、上下文、存储和执行元数据的统一明确接口。

以前的模式

推荐的模式

有关智能体级别的迁移(例如 create_react_agent 和自定义状态),请参阅 LangChain v1 迁移指南。

工具执行

在 LangChain 中,工具由智能体使用(例如通过 @[create_agent]),工具错误处理通过中间件进行配置。 对于 LangGraph 工作流,工具执行由 @[ToolNode] 处理。有关 Graph API 的使用,包括工具如何访问当前图状态和运行作用域上下文,请参阅 ToolNode。

工具返回值

你可以为你的工具选择不同的返回值:
  • 返回 string 以提供人类可读的结果。
  • 返回 object 以提供模型应解析的结构化结果。
  • 返回带有可选消息的 Command,以便在需要写入状态时使用。

返回字符串

当工具应提供纯文本供模型读取并在其下一个响应中使用时,返回字符串。 行为:
  • 返回值被转换为 ToolMessage。
  • 模型看到该文本并决定下一步做什么。
  • 除非模型或其他工具稍后执行操作,否则不会更改智能体状态字段。
当结果是自然可读文本时使用此方法。

返回对象

当你的工具产生模型应检查的结构化数据时,返回对象(例如 dict)。 行为:
  • 对象被序列化并作为工具输出发送回来。
  • 模型可以读取特定字段并对其进行推理。
  • 与字符串返回类似,这不会直接更新图状态。
当后续推理受益于显式字段而不是自由形式文本时,使用此方法。

返回多模态内容

工具不限于纯文本。当模型支持多模态工具结果时,工具可以返回标准内容块,以便模型在一个工具结果中接收文本、图像和其他媒体。
行为:
  • 返回值被转换为具有多模态 content 的 ToolMessage。
  • 工具运行后,使用 message.content_blocks 读取规范化的块列表。
  • 模型必须支持你返回的模态。在返回图像、音频或视频之前,请检查你的模型能力。
有关块类型和提供商特定要求,请参阅多模态消息。返回图像或混合内容的 MCP 工具以相同方式转换;请参阅多模态工具内容。

返回 Command

当工具需要更新图状态(例如设置用户偏好或应用程序状态)时,返回 @[Command]。 你可以返回带有或不带有 ToolMessage 的 Command。 如果模型需要看到工具成功(例如,确认偏好已更改),请在更新中包含一个 ToolMessage,并使用 runtime.tool_call_id 作为 tool_call_id 参数。 行为:
  • 命令使用 update 更新状态。
  • 更新后的状态在同一运行的后续步骤中可用。
  • 对于可能被并行工具调用更新的字段,请使用归约器。
当工具不仅返回数据,而且还改变智能体状态时,使用此方法。

直接从工具返回

在工具上设置直接返回,以短路智能体循环:智能体立即将工具的输出返回给调用者,而无需将其发送回模型进行进一步处理。 python :::

状态注入

工具通过 @[ToolRuntime] 访问图状态。有关状态、上下文、存储和流式 API 的信息,请参阅访问上下文。
有关从工具访问状态、上下文和长期记忆的更多详细信息,请参阅访问上下文。

动态工具选择

使用动态工具,智能体可用的工具集是在运行时修改的,而不是预先全部定义好的。并非每个工具都适用于每种情况。工具过多可能会使模型不堪重负(上下文过载)并增加错误;工具过少则限制了能力。动态工具选择使得能够根据认证状态、用户权限、功能标志或对话阶段来调整可用的工具集。 根据工具是否预先已知,有两种方法:
当所有可能的工具在智能体创建时都已知,你可以预先注册它们,并根据状态、权限或上下文动态过滤哪些工具暴露给模型。
仅在达到特定对话里程碑后才启用高级工具:
这种方法在以下情况最为适用:
  • 所有可能的工具在编译/启动时都已知
  • 你想根据权限、功能标志或对话状态进行过滤
  • 工具是静态的,但其可用性是动态的
更多示例请参阅动态选择工具。

无头工具

某些工具应该在用户应用程序运行的地方(通常是浏览器)运行,而不是在服务器进程内部运行。无头工具是你在服务器上用智能体注册的工具定义,包括名称、描述和参数模式。实现仅在客户端注册,并在短暂的中断/恢复握手后执行。 这与普通工具(其函数体在服务器上运行)和服务器端工具使用(模型提供商远程执行内置工具)不同。

何时使用无头工具

当工作依赖于仅存在于客户端的环境、设备或 UI 时,使用它们。例如:
  • 浏览器 API: 地理位置、IndexedDB、剪贴板、Canvas 2D、文件选择器、电池 API 等。
  • 隐私和本地性: 数据保留在设备上(例如,IndexedDB 中的本地“内存”)。
  • 延迟: 对于纯本地操作,无需额外的服务器往返。
  • 结构化、安全的操作: 优先使用许多小型、类型化的工具(例如,每个 Canvas 图元一个工具),而不是向 eval 发送任意代码。

模式如何工作

在两种运行时中,模型看到一个它可以调用的普通工具,但实际执行发生在服务器进程之外。
  1. 定义一个无头工具,使用 langchain.tools 中的 tool(name=..., description=..., args_schema=...)。无头工具仅包含模式,没有进程内实现。
  2. 注册该工具到 create_agent 或你的 LangGraph 图,这样模型就可以正常调用它。
  3. 处理调用工具时产生的中断载荷。图不会在本地运行,而是暂停,并提供一个形如 {"type": "tool", "tool_call": {"id", "name", "args"}} 的载荷。
  4. 恢复图,在你的应用程序、其他服务或人工步骤执行了该操作之后。对于基于浏览器的流程,你可以在前端镜像该模式,并在那里附加 .implement(...)。
如果你在 Python 中仅使用 name、description 和 args_schema 调用 tool(...),LangChain 会返回一个 HeadlessTool。Python 端没有 .implement() API。
当模型为这些工具发出工具调用时,运行会中断,而不是在本地执行工具。你的应用程序可以检查载荷,在正确的环境中(例如浏览器、另一个服务或人工审查步骤)执行操作,然后用工具结果恢复图。当你使用支持的 JS SDK 钩子时,它们可以检测无头工具中断,运行匹配的客户端实现,并为你提交恢复命令。 使用可选的 onTool 回调来观察生命周期事件(start、success、error),以便为 UI 反馈(如加载指示器或提示信息)提供支持。

无头工具前端模式

查看一个使用 useStream 在客户端执行的仅包含模式工具的端到端示例。

预构建工具

LangChain 提供了大量预构建的工具和工具包,用于常见任务,如网络搜索、代码解释、数据库访问等。这些开箱即用的工具可以直接集成到你的智能体中,无需编写自定义代码。 有关按类别组织的可用工具完整列表,请参阅工具和工具包集成页面。

服务器端工具使用

一些聊天模型具有内置工具,这些工具由模型提供商在服务器端执行。这些功能包括网络搜索和代码解释器等,你无需定义或托管工具逻辑。 有关启用和使用这些内置工具的详细信息,请参阅各个聊天模型集成页面和工具调用文档。