Tools、Agent 循环与中间件

本节目标

看清 LangChain Agent 的最小循环,学会把工具 schema、执行权限、错误与副作用写成代码契约,并理解 create_agent 和 middleware 的当前边界。

Agent 循环并不神秘

用户消息 -> 模型
            | 无工具调用 -> 最终消息
            | 工具调用   -> 参数校验 -> 执行工具 -> ToolMessage -> 模型
                                      \_________________________/ 有限循环

模型只提出动作。真正的执行器必须再次校验工具名、参数、调用者身份和资源范围。工具返回观察后,模型可能继续调用或结束。最大轮数、总耗时、成本、重复调用和人工接管条件必须由运行时限制。

LangChain v1 以 from langchain.agents import create_agent 作为标准高层 Agent 入口,取代旧的 langgraph.prebuilt.create_react_agent 首选位置。高层 Agent 建立在 LangGraph 上,但标准工具循环不要求初学者先手写 StateGraph。

从一个只读工具开始

当前官方 Python 工具入口是 from langchain.tools import tool。装饰器默认使用函数名和 docstring 构造工具描述,类型提示参与参数 schema。示意代码:

from langchain.tools import tool  # 导入将普通 Python 函数声明为 LangChain Tool 的装饰器。
 
@tool  # 根据函数名、docstring 和类型提示生成工具描述与参数 schema。
def lookup_order(order_id: str) -> dict[str, str]:  # 只读查询接口,输入是订单标识符。
    """按订单 ID 查询当前调用者有权查看的订单摘要。"""
    # 身份与资源授权必须由业务代码校验,装饰器本身不提供访问控制。
    return {"order_id": order_id, "status": "pending"}  # 返回最小订单摘要,不暴露无关字段。

工具描述要说明何时使用和边界,但它不是授权系统。模型生成的 order_id、路径、URL 或 SQL 都是不可信输入。

好工具的契约

维度要回答的问题
名称是否是单一动作,例如 lookup_order 而不是 manage_order?
输入类型、长度、枚举、资源范围和必填字段是什么?
输出模型看到什么,应用保留什么 artifact,来源如何追踪?
错误输入错误、权限拒绝、瞬时故障和永久故障如何区分?
副作用是否写数据、扣费、发消息?能否预览和审批?
幂等重试相同请求会不会重复执行?幂等键存在哪里?
预算超时、速率、调用次数和结果大小上限是什么?

只读和写入工具要分开。对发送邮件、删除文件、执行 SQL 等高风险动作,先返回预览,再通过外部审批令牌执行;审批应绑定动作、参数、状态版本和有效期。

create_agent 负责什么

高层 Agent 负责标准模型—工具循环、消息状态以及与中间件结合的扩展点。典型形状包含 model、tools、可选 system_prompt、middleware、response_format 和检查点相关配置。模型标识、提供商包和某些参数会随版本变化,代码只能在项目锁定依赖后视为已验证。

它不会自动保证:

  • 工具只访问当前用户有权访问的资源;
  • 外部动作幂等;
  • Prompt injection 无法影响动作;
  • 每个工具都有合理超时和错误分类;
  • 最终回答有事实来源。

在没有 provider 凭据前,可先运行 无密钥 create_agent 运行时合同。它以固定消息轨迹穿过真实 create_agent 与 ToolNode,验证正常、未知工具和严格参数拒绝;其 fake shim 刻意不验证提供商的 bind_tools 序列化、真实模型决策、网络或授权,因此这些仍要以独立 smoke / 集成测试覆盖。

Middleware 在哪里使用

当前官方文档把 middleware 作为 create_agent 的主要扩展面,可用于动态 Prompt、上下文裁剪、工具选择、重试、fallback、速率限制、PII 处理、guardrail、人工审批和日志。middleware hook 运行在 create_agent 编译出的 LangGraph 内;整个 Agent 也可作为更大 StateGraph 的节点。

工程上把 middleware 当“可组合策略”,不要把所有业务逻辑塞进一个 hook。权限仍要在工具执行层落实,敏感日志在产生时脱敏,middleware 失败也要有明确终态。

失败与停止策略

  • 参数不符合 schema:不执行工具,把可修复错误返回模型或直接失败。
  • 权限拒绝:不可通过重试绕过,记录审计并转人工或拒绝。
  • 网络瞬时错误:有限指数退避,受总时间预算约束。
  • 永久业务错误:立即停止,不把“找不到订单”当网络故障。
  • 重复相同调用:检查观察是否丢失;达到阈值时停止。
  • 写操作结果未知:先查幂等回执,不能盲目重放。

动手实践

为“查询政策并创建工单”设计三个工具:search_policy、preview_ticket、create_ticket。逐项写出输入 schema、输出、错误、副作用、授权、幂等键和审批要求。然后画出最多 6 次模型调用、3 次工具调用、30 秒总预算的终止图。

自测

  • 能复述模型、Agent 运行时、执行器和工具的责任边界。
  • 能解释为什么 @tool 的 schema 不能代替对象级授权。
  • 能为写工具设计预览、审批、幂等和未知结果恢复。
  • 能说明 middleware 适合横切策略,但不是安全边界的唯一实现。

下一步

进入 Retrieval 与 RAG 组件,学习如何让 Agent 使用可追踪知识。

资料基线

官方事实核对日期:2026-07-21。