导语
绝大多数传统 Agent 框架存在一个共性痛点:业务逻辑、上下文处理、安全校验、记忆、工具拦截等能力高度耦合在 Agent 基类中。开发者想要新增/替换某一项能力,只能通过继承重写方法、侵入核心流程,代码臃肿、单测困难、扩展成本极高。
DeerFlow 提出一套两段式可组装中间件链架构,将 Agent 运行时所有横向切面能力拆分为独立中间件插件,通过声明式开关、精准定位装饰器、三层组装模式实现无侵入扩展。整套系统包含完整 26 个内置中间件,覆盖输入清洗、沙箱安全、上下文压缩、子代理限流、循环检测、澄清拦截全链路,同时配套 Skill 按需加载机制,做到「基础 Agent 通用、能力按需注入」。
本文完整拆解中间件链路分层、组装逻辑、五大核心设计理念与落地代码实践。
一、整体架构:26 个中间件,两段式分层链路
完整 Agent 中间件链分为共享运行时基础链 + 主 Agent 专属增强链,两段顺序拼接后传入 LangGraph 执行,子代理复用第一段基础中间件,仅不加载第二段主 Agent 独有逻辑,实现代码复用。
1. 第一段:共享运行时基础链(1--10,build_lead_runtime_middlewares)
所有会话、子代理、主 Agent 通用底层安全与运行能力,永远最先执行,负责输入、沙箱、工具异常、模型调用兜底:
| 序号 | 中间件 | 执行条件 | 核心职责 |
|---|---|---|---|
| 1 | InputSanitizationMiddleware | 永久启用 | 最外层输入清洗,所有下游中间件统一拿到干净消息 |
| 2 | ToolOutputBudgetMiddleware | 永久启用 | 截断超长工具返回内容,控制上下文膨胀 |
| 3 | UploadsMiddleware | 永久启用 | 上传文件注入对话上下文 |
| 4 | ThreadDataMiddleware | 永久启用 | 线程隔离目录创建,多用户资源隔离 |
| 5 | SandboxMiddleware | 永久启用 | 分配沙箱实例,状态存入 sandbox_id |
| 6 | DanglingToolCallMiddleware | 永久启用 | 用户中断、未响应工具调用填充占位消息,防止状态断裂 |
| 7 | LLMErrorHandlingMiddleware | 永久启用 | 统一封装大模型调用异常,转为可恢复业务错误 |
| 8 | GuardrailMiddleware | 开关控 guardrails.enabled |
工具调用前置权限校验、策略拦截 |
| 9 | SandboxAuditMiddleware | 永久启用 | Shell/文件操作安全审计日志 |
| 10 | ToolErrorHandlingMiddleware | 永久启用 | 工具执行异常封装为标准 ToolMessage,避免会话直接中断 |
2. 第二段:主 Agent 专属增强链(11--26,build_middlewares)
拼接在基础链尾部,仅主会话加载,负责上下文动态注入、记忆、视觉、子代理、循环风控、自定义扩展、兜底澄清拦截:
| 序号 | 中间件 | 执行条件 | 核心职责 |
|---|---|---|---|
| 11 | DynamicContextMiddleware | 永久启用 | 注入实时日期,静态系统提示实现前缀缓存加速 |
| 12 | SkillActivationMiddleware | 永久启用 | 解析 /skill-name 指令,按需加载技能文档 |
| 13 | SummarizationMiddleware | summarization.enabled |
上下文超长自动压缩历史对话 |
| 14 | TodoListMiddleware | 计划模式 is_plan_mode |
任务清单追踪,注入待办工具 |
| 15 | TokenUsageMiddleware | token_usage.enabled |
全链路 Token 消耗指标埋点统计 |
| 16 | TitleMiddleware | 永久启用 | 首轮对话自动生成会话标题 |
| 17 | MemoryMiddleware | 永久启用 | 对话异步写入长期记忆存储 |
| 18 | ViewImageMiddleware | 模型支持视觉 supports_vision=True |
图片 Base64 注入多模态上下文 |
| 19 | DeferredToolFilterMiddleware | tool_search.enabled |
隐藏未激活 MCP 工具,按需暴露工具 Schema |
| 20 | SystemMessageCoalescingMiddleware | 永久启用 | 合并多条系统消息为单条前置消息,兼容 vLLM/Anthropic 等严格后端 |
| 21 | SubagentLimitMiddleware | subagent_enabled |
限制并行子代理调用数量,防资源雪崩 |
| 22 | LoopDetectionMiddleware | loop_detection.enabled |
检测重复工具调用死循环,强制终止 |
| 23 | TokenBudgetMiddleware | token_budget.enabled |
单次会话全局 Token 配额限制 |
| 24 | Custom middlewares | 外部传入 | 自定义中间件统一注入点位 |
| 25 | SafetyFinishReasonMiddleware | safety_finish_reason.enabled |
内容安全拦截后清空工具调用,禁止继续执行 |
| 26 | ClarificationMiddleware | 永久启用(强制末尾) | 拦截澄清工具调用,直接中断链路,固定为链最后一环 |
3. 链路组装执行流程
#mermaid-svg-JwlQijstLQMpmgvS{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JwlQijstLQMpmgvS .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JwlQijstLQMpmgvS .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JwlQijstLQMpmgvS .error-icon{fill:#552222;}#mermaid-svg-JwlQijstLQMpmgvS .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JwlQijstLQMpmgvS .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JwlQijstLQMpmgvS .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JwlQijstLQMpmgvS .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JwlQijstLQMpmgvS .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JwlQijstLQMpmgvS .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JwlQijstLQMpmgvS .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JwlQijstLQMpmgvS .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JwlQijstLQMpmgvS .marker.cross{stroke:#333333;}#mermaid-svg-JwlQijstLQMpmgvS svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JwlQijstLQMpmgvS p{margin:0;}#mermaid-svg-JwlQijstLQMpmgvS .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JwlQijstLQMpmgvS .cluster-label text{fill:#333;}#mermaid-svg-JwlQijstLQMpmgvS .cluster-label span{color:#333;}#mermaid-svg-JwlQijstLQMpmgvS .cluster-label span p{background-color:transparent;}#mermaid-svg-JwlQijstLQMpmgvS .label text,#mermaid-svg-JwlQijstLQMpmgvS span{fill:#333;color:#333;}#mermaid-svg-JwlQijstLQMpmgvS .node rect,#mermaid-svg-JwlQijstLQMpmgvS .node circle,#mermaid-svg-JwlQijstLQMpmgvS .node ellipse,#mermaid-svg-JwlQijstLQMpmgvS .node polygon,#mermaid-svg-JwlQijstLQMpmgvS .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JwlQijstLQMpmgvS .rough-node .label text,#mermaid-svg-JwlQijstLQMpmgvS .node .label text,#mermaid-svg-JwlQijstLQMpmgvS .image-shape .label,#mermaid-svg-JwlQijstLQMpmgvS .icon-shape .label{text-anchor:middle;}#mermaid-svg-JwlQijstLQMpmgvS .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JwlQijstLQMpmgvS .rough-node .label,#mermaid-svg-JwlQijstLQMpmgvS .node .label,#mermaid-svg-JwlQijstLQMpmgvS .image-shape .label,#mermaid-svg-JwlQijstLQMpmgvS .icon-shape .label{text-align:center;}#mermaid-svg-JwlQijstLQMpmgvS .node.clickable{cursor:pointer;}#mermaid-svg-JwlQijstLQMpmgvS .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JwlQijstLQMpmgvS .arrowheadPath{fill:#333333;}#mermaid-svg-JwlQijstLQMpmgvS .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JwlQijstLQMpmgvS .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JwlQijstLQMpmgvS .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JwlQijstLQMpmgvS .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JwlQijstLQMpmgvS .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JwlQijstLQMpmgvS .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JwlQijstLQMpmgvS .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JwlQijstLQMpmgvS .cluster text{fill:#333;}#mermaid-svg-JwlQijstLQMpmgvS .cluster span{color:#333;}#mermaid-svg-JwlQijstLQMpmgvS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JwlQijstLQMpmgvS .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JwlQijstLQMpmgvS rect.text{fill:none;stroke-width:0;}#mermaid-svg-JwlQijstLQMpmgvS .icon-shape,#mermaid-svg-JwlQijstLQMpmgvS .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JwlQijstLQMpmgvS .icon-shape p,#mermaid-svg-JwlQijstLQMpmgvS .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JwlQijstLQMpmgvS .icon-shape .label rect,#mermaid-svg-JwlQijstLQMpmgvS .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JwlQijstLQMpmgvS .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JwlQijstLQMpmgvS .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JwlQijstLQMpmgvS :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} build_lead_runtime_middlewares()
中间件1--10 共享基础链
build_middlewares()
中间件11--26 主Agent增强链追加
create_agent 拼接完整链传入 LangGraph 运行图
关键约束:ClarificationMiddleware 拥有全局最高尾部优先级。即使自定义中间件通过 @Next 装饰器试图将其挤出末尾,底层组装函数 _assemble_from_features 会自动将其重新挪至数组最后一位,保证澄清拦截永远是最后一道执行逻辑。
二、五大核心设计理念:彻底解决传统 Agent 架构痛点
整套中间件体系围绕「小模块、可观测、可替换、动态组装、按需加载」五大原则落地,每一条设计均有配套代码实现支撑。
理念1:行为由插件组合,而非类继承
传统框架改造 Agent 能力依赖 BaseAgent 子类重写 run、invoke、工具回调等核心方法,所有逻辑耦合在同一类中:
- 新增记忆能力 → 修改基类执行流程
- 新增循环检测 → 侵入消息流转逻辑
- 替换安全校验 → 大面积覆写核心函数
DeerFlow 完全抛弃继承扩展模式,采用中间件切面钩子 实现所有横向能力:
每个中间件仅实现 4 组轻量钩子:before_model / after_model / before_agent / after_agent,且严格遵循「单一职责」:一个中间件只做一件事,仅修改自身声明的状态字段。
示例拆分:
SummarizationMiddleware:仅在模型调用前压缩超长历史LoopDetectionMiddleware:仅在工具调用后识别循环并截断TitleMiddleware:仅首轮对话结束后生成会话标题
优势:中间件完全解耦,可独立单元测试,新增能力无需改动任何 Agent 核心代码。
理念2:RuntimeFeatures 声明式特性开关,支持自定义替换
框架提供纯数据类 RuntimeFeatures 统一管控全量能力,每个特性字段支持三种配置形态:
True:启用框架内置默认中间件;False:直接关闭该能力;- 传入
AgentMiddleware实例:使用自定义实现替换官方中间件。
python
@dataclass
class RuntimeFeatures:
sandbox: bool | AgentMiddleware = True
memory: bool | AgentMiddleware = False
loop_detection: bool | AgentMiddleware = True
# summarization/guardrail 无内置实现,仅支持关闭或自定义中间件
summarization: Literal[False] | AgentMiddleware = False
业务侧可零侵入替换核心能力:例如自研向量记忆,仅需实现 MyMemoryMiddleware,传入 features=RuntimeFeatures(memory=MyMemoryMiddleware()),组装时会自动剔除原生 MemoryMiddleware,全程不修改底层组装逻辑。
理念3:@Next / @Prev 装饰器,精准控制自定义中间件位置
自定义中间件不需要硬编码数组下标插入,通过装饰器声明相对锚点,底层自动完成链路排序:
@Next(目标中间件类):当前插件插入锚点之后;@Prev(目标中间件类):当前插件插入锚点之前。
示例:在工具断链处理中间件后新增自定义审计插件
python
@Next(DanglingToolCallMiddleware)
class MyToolAuditMiddleware(AgentMiddleware):
pass
组装器自动识别装饰器标记,将插件精准插入指定位置,避免手动维护索引带来的链路错乱。
理念4:create_deerflow_agent 三层组装模式,适配不同扩展粒度
SDK 顶层工厂函数提供三种互斥组装模式,覆盖从快速使用到完全自定义全场景,三者不可同时使用:
- 声明式 features(推荐日常业务)
仅配置RuntimeFeatures,框架自动拼接标准 26 件中间件链,按需开关内置能力,最低接入成本。 - 扩展式 extra_middleware
在自动生成的标准链基础上,通过@Next/@Prev插入自定义插件,保留官方完整链路,仅追加业务切面。 - 完全接管 middleware
直接传入完整中间件数组,框架放弃自动组装逻辑,完全由开发者定义整条执行链,适配深度定制场景。
python
# 三种模式互斥,底层参数校验强制限制
if middleware is not None and features is not None:
raise ValueError("Cannot specify both 'middleware' and 'features'. Use one or the other.")
理念5:Skill 按需加载,不污染基础上下文
中间件解决「运行时横向切面能力」,Skill 解决「纵向业务领域能力」,二者配合实现干净的上下文隔离:
- 基础 Agent 保持极简通用系统提示,无任何领域专属指令、工具;
- 用户输入
/skill-name触发SkillActivationMiddleware,仅在当前回合注入对应 Skill 的指令、工具、最佳实践文档; - 会话切换任务后,自动卸载无关 Skill,不会持续占用上下文 Token。
核心价值:不会出现「写代码、写论文、数据分析」多领域指令堆砌在系统提示中导致模型混淆、上下文冗余膨胀的问题,新增业务领域仅需开发独立 Skill 包,无需修改 Agent 核心与中间件链。
三、落地优势总结
1. 工程侧收益
- 低耦合易维护:单中间件单一职责,故障隔离,新增/下线能力无回归风险;
- 可观测可审计:每个中间件仅修改自有状态字段,会话异常可精准定位切面;
- 灵活扩展分层:简单开关、精准插入、全链路自定义三种模式适配不同业务复杂度;
- 代码复用:基础 10 件中间件由主/子代理共用,减少重复运行时代码。
2. 推理性能收益
DynamicContextMiddleware保持静态系统提示,复用 LLM 前缀缓存,降低重复编码开销;SummarizationMiddleware+TokenBudgetMiddleware双层控制上下文长度,稳定推理速度;SystemMessageCoalescingMiddleware统一系统消息格式,兼容各大推理后端,规避接口报错。
3. 安全与稳定性收益
沙箱审计、工具输出截断、循环检测、子代理限流、安全终止拦截多层风控中间件原生内置,开箱即用,无需业务侧重复开发异常兜底逻辑。
四、适用场景
这套两段式中间件架构适合所有需要长期迭代、多业务领域、多用户会话的生产级 Agent 平台:
- 企业内部多功能智能助手(编码、数据分析、文档处理、工单);
- 多模态对话 SaaS 产品;
- 支持子代理并行任务拆解的复杂规划型 Agent;
- 需要强安全审计、资源配额管控的私有化大模型应用。
文末小结
DeerFlow 放弃传统 Agent 继承式扩展的老旧思路,以「中间件插件链」为核心骨架,分层拆解运行时所有横向能力,配套声明式开关、定位装饰器、三级组装策略,同时通过 Skill 机制隔离领域业务上下文。26 个标准化内置中间件覆盖从输入清洗到会话兜底全生命周期,兼顾开发效率、系统稳定性、推理性能与扩展性,为生产级复杂 Agent 提供一套可落地、可长期维护的标准架构范式。
需要我把这篇博客精简成适合官网短文档的版本,或者补充一份可直接运行的最小 Demo 代码吗?