LangChain Agent 中间件完全指南:从拦截器设计到自定义钩子实战
读懂中间件机制,让你的 Agent 从"能跑"走向"可控、可观测、可生产"。
写在前面
如果你已经用 LangChain 搭过 Agent,大概率会遇到这些痛点:
- 想给 Agent 加上日志,却不知道在哪一层埋点
- 想做调用次数限流,防止 token 成本失控
- 想在关键工具调用前让人工把关,但不想重写整个 Agent
- 想要更细粒度地控制提示词、工具选择和输出格式
这些需求,中间件(Middleware) 都能优雅地解决。它是 LangChain Agent 体系里最值得掌握的扩展机制之一,今天这篇文章就把它彻底讲清楚。
一、什么是中间件?
中间件作为核心组件,为 Agent 执行流程提供了强大的可扩展性和控制能力。
本质上,它是一种拦截器模式(Interceptor Pattern) 的实现:把 Agent 的执行管道拆成若干关键节点,在每个节点前后留出"钩子",让开发者注入自定义业务逻辑,实现对代理行为的细粒度控制和功能扩展。
Agent 执行流程总览
注意模型和工具调用之间的循环结构——这是 Agent 能"边想边做"的关键,也是中间件为什么必须存在的原因:没有拦截器,你就根本没办法在这个循环里插入逻辑。
中间件能做什么?
简单说,中间件帮你解决 Agent 走向生产时的四大难题:可观测、可控制、可约束、可降本。
二、怎么创建中间件?
中间件在 Agent 运行的每一步之前和之后,为用户暴露钩子(hooks),方便进行跟踪与控制。创建方式非常直观:把中间件实例放进 create_agent 的 middleware 参数即可。
最小可运行示例
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware, HumanInTheLoopMiddleware
from langchain.chat_models import init_chat_model
model = init_chat_model("openai:gpt-4")
agent = create_agent(
model=model,
tools=[...],
middleware=[
SummarizationMiddleware(...),
HumanInTheLoopMiddleware(...)
],
)
创建步骤
两步搞定:先建代理,再传中间件。
关于"多个中间件"的一个重要细节
middleware 参数是一个列表,可以传多个中间件。当同一位置有多个中间件时,会严格按照列表中的先后顺序触发。来看时序图:
💡 实战建议:中间件的顺序很关键。典型的最佳实践是日志/监控类放最外层,限流/熔断类放最外层靠前,业务校验类放中间——这样异常能最早被捕获。
三、中间件的两大分类
LangChain 把中间件分成了预制和自定义两类,覆盖从"开箱即用"到"深度定制"的全部需求。
整体分类结构
1. Built-in Middleware(预制中间件)
LangChain 为常见场景提供了预构建的中间件,每个都已准备好生产环境,并可根据你的具体需求配置。
| 中间件 | 功能 | 适用场景 |
|---|---|---|
| Summarization | 触发时自动总结对话列表记录 | 长对话导致上下文爆炸 |
| Human-in-the-loop | 暂停执行以供人工批准或修改工具调用 | 涉及删除/支付/发送等高风险操作 |
| To-do list | 为代理提供复杂多步骤任务的任务规划和跟踪能力 | 多步任务执行与可追溯 |
| Model call limit | 限制模型调用次数,以防止过高成本 | 成本敏感的生产环境 |
✅ 实战建议:大多数项目从
Model call limit+Summarization起步,就能解决 80% 的生产化问题。
2. Custom Middleware(自定义中间件)
LangChain 允许通过代理执行流程中特定节点的钩子来构建自定义中间件。钩子分两类:
钩子触发位置
节点型钩子(Node Hooks)
| 钩子 | 触发时机 | 典型用途 |
|---|---|---|
before_agent | Agent 开始前(每次查询一次) | 鉴权、初始化上下文 |
before_model | 每次模型调用前 | 提示词改写、敏感词过滤 |
after_model | 每次模型响应后 | 输出格式化、敏感信息脱敏 |
after_agent | 代理完成后(每次调用一次) | 清理资源、记录指标 |
环绕型钩子(Wrap Hooks)
| 钩子 | 触发时机 | 典型用途 |
|---|---|---|
wrap_model_call | 围绕每次模型调用 | 重试、降级到备用模型、缓存 |
wrap_tool_call | 围绕每次工具调用 | 工具调用审批、参数校验、结果缓存 |
💡 节点型 vs 环绕型:节点型是"在节点前后挂个钩子",环绕型是"把整个调用包起来",后者天然适合做重试 / fallback / 缓存这类需要拦截输入输出的场景。
四、总结:一张图看懂中间件
中间件是 LangChain Agent 体系中的核心扩展机制,通过拦截器模式在关键执行节点注入自定义逻辑,覆盖行为记录、格式约束、逻辑控制、资源限制四大方向。
- 想快速上手?→ 用 Built-in 中间件,5 行代码搞定生产化
- 想深度定制?→ 选 Custom 钩子,6 个位置任你组合
掌握了它,你的 Agent 才真正具备了可观测、可控制、可生产的能力。
如果觉得有帮助,欢迎点赞 / 收藏 / 评论交流~