Tools 定位:扩展模型能力 → 让 Agent “能行动”
- 创建方式:<code>@tool</code>、自定义名称描述、Pydantic/JSON schema、保留参数约束
- Server-side tool use:OpenAI/Anthropic/Gemini 等内置
- 运行时上下文:<code>ToolRuntime</code> 访问 state/context/store/stream/config/tool_call_id
- 状态更新:使用 <code>Command</code> 修改 Graph state(如清空历史)
- 存储:<code>runtime.store</code> 读写长期记忆
- Streaming:<code>runtime.stream_writer</code> 实时推送执行进度
- 关联模块:Agents(路由调用)、Messages(ToolMessage 回写)、Models(tool calling 能力)
概述
Tools 工具是 Agent 调用外部 API/数据库/文件系统的标准封装,包含函数本体 + 输入 schema,帮助模型以结构化方式触发操作。
Tools 工具通过让模型能够借助定义明确的输入和输出来与世界交互,从而扩展了模型的能力。工具封装了一个可调用的函数及其输入模式。这些可以传递给兼容的聊天模型,使模型能够决定是否调用工具以及使用哪些参数。在这些场景中,工具调用使模型能够生成符合指定输入模式的请求。
产品经理在PRD 需明确:可暴露的工具列表、输入输出字段、错误策略、运行时上下文(ToolRuntime)与合规限制。
工具定义
LangChain 既支持本地自建工具(<code>@tool</code> 装饰器/Pydantic schema)也支持部分模型自带的 server-side 工具(如搜索、代码解释器)。
创建工具最简单的方法是使用<code>@tool</code>装饰器;装饰器可自行询问大模型Python语法。默认情况下,函数的文档字符串会成为工具的描述,帮助模型了解何时使用该工具。如:
@tool
def search_database(query: str, limit: int = 10) -> str: # 类型提示:
"""Search the customer database for records matching the query."""
# - query: str → 参数 query 类型为字符串
# - limit: int = 10 → 参数 limit 类型为整数(默认值 10)
# - -> str → 函数返回值类型为字符串
return f"Found {limit} results for '{query}'"
代码中对输入进行了很详细的约定,这些类型提示是必需的,因为它们定义了工具的输入模式,又比如:
| 类型提示形式 | 作用 | |
|---|---|---|
| <code>参数名: 基础类型</code>(如 <code>str</code>、<code>int</code>) | 限定简单参数的类型 | |
| <code>-> 返回值类型</code>(如 <code>-> str</code>) | 限定函数返回值的类型 | |
| <code>Literal["a", "b"]</code> | 限定参数仅允许特定枚举值 | |
| <code>Pydantic 模型字段类型</code>(如 <code>location: str</code>) | 定义复杂结构化输入的类型 | |
| <code>ToolRuntime</code> / <code>ToolRuntime[Ctx]</code> | 标注上下文参数的类型(关联状态 / 内存) | |
| <code>dict[str, Any]</code> 等复合类型 | 限定复杂参数(如字典)的结构 |
工具当然支持自定义,包括名字、参数等。
访问上下文
工具只是简单的一来一去的调研的确很简单,但复杂的Agent中工具的使用需要与上下文进行深入的交互。当工具能够访问agent状态、运行时上下文和长期记忆时,工具就能够做出具有上下文感知的决策、个性化响应,并在对话中保持信息的连贯性。Runtime context运行时上下文提供了一种在运行时将依赖项(如数据库连接、用户ID或配置)注入工具的方法,这使得工具更易于测试和重用。
工具可以通过<code>ToolRuntime</code>参数访问运行时信息,该参数提供:
| 信息类别 | 核心作用 | 示例 |
|---|---|---|
| State(状态) | 存储工具执行过程中动态变化的临时数据,数据生命周期与当前流程绑定 | 统计当前对话中用户提问次数:从 State 读取对话消息列表,筛选用户消息计数,计数结果暂存回 State |
| Context(上下文) | 提供不可修改的基础配置,为工具提供身份识别、场景约束等固定信息 | 根据 Context 中的 “用户账户类型” 判断权限:Premium 用户可查看详细账单,Standard 用户需升级后查看 |
| Store(存储) | 跨对话持久化保存数据,实现信息在多次对话中的复用 | 用户设置 “温度单位为华氏度” 后存入 Store,下次查询天气时,工具自动从 Store 读取该偏好并应用 |
| Stream Writer(流编写器) | 工具执行中实时推送中间状态,避免用户等待时的信息空白,提升交互体验 | 查询大型数据库时,实时推送 “开始执行查询→已连接数据库→正在整理结果” 等进度反馈 |
| Config(配置) | 提供框架级执行参数,控制工具执行规则(如超时、重试),保障执行稳定性 | 调用外部 API 时,从 Config 读取 “15 秒超时设置”,若 15 秒内未响应则终止调用并提示超时 |
| Tool Call ID(工具调用 ID) | 唯一标识单次工具调用,用于区分多次调用、追踪执行链路、排查问题 | 用户一次对话中两次查询天气:通过 “tool_call_111”“tool_call_222” 两个 ID,分别关联两次调用的日志和结果 |
<img src="https://ymmcheer-1257617206.cos.ap-nanjing.myqcloud.com/typora/image-20251124225408587.png" alt="image-20251124225408587" style="zoom: 50%;" />
该部分的内容涉及Langgragh的细节,建议可先初步了解,在后续Langgragh中进行深入研究。
需求关注点
| 模块 | 关键信息 | 产品关注 |
|---|---|---|
| Tool 定义 | 使用 <code>@tool</code> 将 Python 函数暴露给模型,docstring 即说明书 | 需求需列出工具清单+用途说明,方便模型理解 |
| 自定义命名/描述 | <code>@tool("web_search", description="...")</code> | 当函数名不直观时必须自定义,保持业务语义 |
| Schema | Type hints 必填;复杂输入用 Pydantic/JSON schema | PRD 中要定义字段类型、是否必填、默认值 |
| 保留参数 | <code>config</code>、<code>runtime</code> 禁止作为 tool 形参,只能通过 <code>ToolRuntime</code> 获取 | 避免开发时撞保留字导致 runtime error |
| Server-side 工具 | 部分模型自带搜索/代码工具,在云端执行 | 需确认供应商支持度及敏感数据是否允许出站 |
| ToolRuntime | 统一入口:state(消息等)、context(用户 ID)、store(长记忆)、stream_writer、config、tool_call_id | 明确哪些上下文需要注入,如用户权限、Session |
| State/Command | 工具可返回 <code>Command(update=...)</code> 修改图状态或清空消息 | PRD 描述允许的状态操作及安全限制 |
| Store | <code>runtime.store</code> 支持跨会话记忆读写 | 指定存储范围、加密要求与淘汰策略 |
| Streaming | <code>runtime.stream_writer</code> 持续输出自定义日志 | UI 需支持实时展示工具执行进度 |
适用场景(问题 → 方案 → 价值)
- 订单查询助手
- 问题:客服 Bot 需实时查询订单状态并在多轮对话中引用结果。
- 方案:用 Pydantic schema 定义 <code>query_order</code> 工具(字段:order_id、need_history);在 ToolRuntime 中获取当前用户 ID 写入审计。
- 价值:模型调用结构化接口,避免自由文本错误,日志可追踪“谁查了哪笔订单”。
- 合规问答 + 服务器端执行
- 问题:某些数据只能在企业内网执行,不允许模型直接访问。
- 方案:封装 server-side tool,模型只发出调用请求,工具在后端执行并返回结果;若失败通过 ToolMessage 通知。
- 价值:隔离敏感数据,满足合规要求,同时保留智能问答体验。
常见问题(FAQ)
- 工具与函数调用有何区别?→ Tools 自带 schema 与描述,Agent 可根据上下文选择调用并解析结构化结果。
- docstring 真的重要吗?→ 模型依赖描述判断是否调用工具,PRD 需提供清晰易懂的用途说明。
- 可以使用复杂输入吗?→ 是,推荐用 Pydantic/JSON schema 定义嵌套字段与枚举。
- 为什么 <code>runtime</code> 不能作为参数?→ 该名称保留给 LangChain,真实上下文需通过 <code>ToolRuntime</code> 注入,否则报错。
- 如何访问当前会话消息?→ 在工具中通过 <code>runtime.state["messages"]</code> 读取,便于总结或诊断。
- 可以更新状态吗?→ 返回 <code>Command(update=...)</code> 修改 Graph state,例如清除历史或更新用户信息。
- 如何读写长期记忆?→ 使用 <code>runtime.store</code> 以键值形式存储用户配置或偏好。
- 工具执行可实时反馈吗?→ 可以,<code>runtime.stream_writer</code> 用于流式输出,如“正在调用 CRM…”。
- Server-side 工具如何接入?→ 依赖供应商(OpenAI/Anthropic 等)提供的 built-in tool 接口,需配置对应模型。
- 工具出错时如何提示模型?→ 返回标准异常或结果字符串,Agent 会生成 ToolMessage;PRD 中需描述重试与降级策略。
扩展信息
- LangChain Tools 官方指南:https://docs.langchain.com/oss/python/langchain/tools
- Provider overview(了解各模型内置工具支持):https://docs.langchain.com/oss/python/integrations/providers/overview
- LangGraph ToolRuntime 参考:https://reference.langchain.com/python/langchain/tools