服务器端工具使用: 一些聊天模型具有内置工具(网页搜索、代码解释器),这些工具由模型提供商在服务器端执行。有关详细信息,请参阅服务器端工具使用。
访问上下文
当工具能够访问运行时信息(如对话历史、用户数据和持久化内存)时,它们最为强大。本节介绍如何从工具内部访问和更新这些信息。上下文
上下文提供在调用时传递的不可变配置数据。用于用户 ID、会话详情或应用程序特定设置等在对话过程中不应更改的信息。虽然
thread_id(通过 config={"configurable": {"thread_id": ...}} 传递)界定对话:消息历史和检查点,但 context 携带的是你的工具和中间件在调用时读取的每次运行数据。在生产环境中,你通常同时传递两者:每个对话一个稳定的 thread_id,以及每次调用时传递一个 context 对象。config 参数访问智能体的运行时上下文。将 context 与 thread_id 一起传递,以便对话在多轮次间得以持久化:
长期记忆 (存储)
@[BaseStore] 提供跨对话持久存在的存储。与状态(短期记忆)不同,保存到存储的数据在未来的会话中仍然可用。
通过 config.store 访问存储。存储使用命名空间/键模式来组织数据:
流写入器
在工具执行期间流式传输实时更新。这对于在长时间运行的操作中为用户提供进度反馈非常有用。 使用config.writer 发出自定义更新:
执行信息
通过runtime.execution_info 从工具内部访问线程 ID、运行 ID 和重试状态:
需要
deepagents>=1.9.0(或 @langchain/langgraph>=1.2.8)。服务器信息
当你的工具在 LangGraph Server 上运行时,可以通过runtime.server_info 访问助手 ID、图 ID 和已认证的用户:
serverInfo 为 null。
需要
deepagents>=1.9.0(或 @langchain/langgraph>=1.2.8)。工具执行
在 LangChain 中,工具由智能体使用(例如通过 @[create_agent]),工具错误处理通过中间件进行配置。
对于 LangGraph 工作流,工具执行由 @[ToolNode] 处理。有关 Graph API 的使用,包括工具如何访问当前图状态和运行作用域上下文,请参阅 ToolNode。
工具返回值
你可以为你的工具选择不同的返回值:- 返回
string以提供人类可读的结果。 - 返回
object以提供模型应解析的结构化结果。 - 返回带有可选消息的
Command,以便在需要写入状态时使用。
返回字符串
当工具应提供纯文本供模型读取并在其下一个响应中使用时,返回字符串。 行为:- 返回值被转换为
ToolMessage。 - 模型看到该文本并决定下一步做什么。
- 除非模型或其他工具稍后执行操作,否则不会更改智能体状态字段。
返回对象
当你的工具产生模型应检查的结构化数据时,返回对象(例如dict)。
行为:
- 对象被序列化并作为工具输出发送回来。
- 模型可以读取特定字段并对其进行推理。
- 与字符串返回类似,这不会直接更新图状态。
返回多模态内容
工具不限于纯文本。当模型支持多模态工具结果时,工具可以返回标准内容块,以便模型在一个工具结果中接收文本、图像和其他媒体。- 返回值被转换为具有多模态
content的ToolMessage。 - 工具运行后,使用
message.content_blocks读取规范化的块列表。 - 模型必须支持你返回的模态。在返回图像、音频或视频之前,请检查你的模型能力。
返回 Command
当工具需要更新图状态(例如设置用户偏好或应用程序状态)时,返回 @[Command]。
你可以返回带有或不带有 ToolMessage 的 Command。
如果模型需要看到工具成功(例如,确认偏好已更改),请在更新中包含一个 ToolMessage,并使用 runtime.tool_call_id 作为 tool_call_id 参数。
行为:
- 命令使用
update更新状态。 - 更新后的状态在同一运行的后续步骤中可用。
- 对于可能被并行工具调用更新的字段,请使用归约器。
直接从工具返回
在工具上设置直接返回,以短路智能体循环:智能体立即将工具的输出返回给调用者,而无需将其发送回模型进行进一步处理。 ::> 行为:- 工具正常执行,其输出被包装在
ToolMessage中。 - 智能体停止循环并直接返回工具的输出作为最终响应,绕过任何额外的模型调用。
- 如果模型在单一轮次中调用多个工具,只有当所有被调用的工具都设置了
return_direct=True时,return_direct才会生效。
- 工具的输出是完整、可直接展示给用户的答案(例如,返回可直接显示的结果的查找)。
- 当不需要额外推理时,你想避免额外的模型调用。
- 你需要确定性的、未修改的输出——模型无法对工具结果进行重述、总结或操作。
错误处理
使用 LangChain 智能体中间件处理工具错误,以重试失败的工具调用或返回自定义错误消息: python :::状态注入
工具通过 @[ToolRuntime] 访问图状态。有关状态、上下文、存储和流式 API 的信息,请参阅访问上下文。
有关从工具访问状态、上下文和长期记忆的更多详细信息,请参阅访问上下文。
动态工具选择
使用动态工具,智能体可用的工具集是在运行时修改的,而不是预先全部定义好的。并非每个工具都适用于每种情况。工具过多可能会使模型不堪重负(上下文过载)并增加错误;工具过少则限制了能力。动态工具选择使得能够根据认证状态、用户权限、功能标志或对话阶段来调整可用的工具集。 根据工具是否预先已知,有两种方法:- 过滤预注册的工具
- 运行时工具注册
当所有可能的工具在智能体创建时都已知,你可以预先注册它们,并根据状态、权限或上下文动态过滤哪些工具暴露给模型。这种方法在以下情况最为适用:
- 状态
- 存储
- 运行时上下文
仅在达到特定对话里程碑后才启用高级工具:
- 所有可能的工具在编译/启动时都已知
- 你想根据权限、功能标志或对话状态进行过滤
- 工具是静态的,但其可用性是动态的
无头工具
某些工具应该在用户应用程序运行的地方(通常是浏览器)运行,而不是在服务器进程内部运行。无头工具是你在服务器上用智能体注册的工具定义,包括名称、描述和参数模式。实现仅在客户端注册,并在短暂的中断/恢复握手后执行。 这与普通工具(其函数体在服务器上运行)和服务器端工具使用(模型提供商远程执行内置工具)不同。何时使用无头工具
当工作依赖于仅存在于客户端的环境、设备或 UI 时,使用它们。例如:- 浏览器 API: 地理位置、IndexedDB、剪贴板、Canvas 2D、文件选择器、电池 API 等。
- 隐私和本地性: 数据保留在设备上(例如,IndexedDB 中的本地“内存”)。
- 延迟: 对于纯本地操作,无需额外的服务器往返。
- 结构化、安全的操作: 优先使用许多小型、类型化的工具(例如,每个 Canvas 图元一个工具),而不是向
eval发送任意代码。
模式如何工作
在两种运行时中,模型看到一个它可以调用的普通工具,但实际执行发生在服务器进程之外。- 定义工具,使用
langchain中的tool({ name, description, schema }),仅包含元数据和验证,没有服务器端运行器。 - 附加真实行为,使用
.implement(async (args) => { ... }),它返回一个无头工具实现(定义 +execute函数)。 - 注册步骤 1 中的定义到
createAgent或你的图,这样模型就能在正常的工具调用循环中看到该工具。 - 传递步骤 2 中的实现到你的流式钩子的
tools选项。
将工具定义(
tool({ name, description, schema }))和实现(.implement(...))放在单独的模块中。从你的服务器智能体和前端导入共享的定义文件,这样名称和模式保持一致;将仅限客户端的执行逻辑放在实现模块中,服务器永远不会加载它们。onTool 回调来观察生命周期事件(start、success、error),以便为 UI 反馈(如加载指示器或提示信息)提供支持。
无头工具前端模式
查看一个使用
useStream 在客户端执行的仅包含模式工具的端到端示例。
