DeerFlow Agent 中间件架构:用插件化链彻底告别 Agent 继承式开发

导语

绝大多数传统 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 子类重写 runinvoke、工具回调等核心方法,所有逻辑耦合在同一类中:

  • 新增记忆能力 → 修改基类执行流程
  • 新增循环检测 → 侵入消息流转逻辑
  • 替换安全校验 → 大面积覆写核心函数

DeerFlow 完全抛弃继承扩展模式,采用中间件切面钩子 实现所有横向能力:

每个中间件仅实现 4 组轻量钩子:before_model / after_model / before_agent / after_agent,且严格遵循「单一职责」:一个中间件只做一件事,仅修改自身声明的状态字段。

示例拆分:

  • SummarizationMiddleware:仅在模型调用前压缩超长历史
  • LoopDetectionMiddleware:仅在工具调用后识别循环并截断
  • TitleMiddleware:仅首轮对话结束后生成会话标题

优势:中间件完全解耦,可独立单元测试,新增能力无需改动任何 Agent 核心代码。

理念2:RuntimeFeatures 声明式特性开关,支持自定义替换

框架提供纯数据类 RuntimeFeatures 统一管控全量能力,每个特性字段支持三种配置形态:

  1. True:启用框架内置默认中间件;
  2. False:直接关闭该能力;
  3. 传入 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 顶层工厂函数提供三种互斥组装模式,覆盖从快速使用到完全自定义全场景,三者不可同时使用:

  1. 声明式 features(推荐日常业务)
    仅配置 RuntimeFeatures,框架自动拼接标准 26 件中间件链,按需开关内置能力,最低接入成本。
  2. 扩展式 extra_middleware
    在自动生成的标准链基础上,通过 @Next/@Prev 插入自定义插件,保留官方完整链路,仅追加业务切面。
  3. 完全接管 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. 工程侧收益

  1. 低耦合易维护:单中间件单一职责,故障隔离,新增/下线能力无回归风险;
  2. 可观测可审计:每个中间件仅修改自有状态字段,会话异常可精准定位切面;
  3. 灵活扩展分层:简单开关、精准插入、全链路自定义三种模式适配不同业务复杂度;
  4. 代码复用:基础 10 件中间件由主/子代理共用,减少重复运行时代码。

2. 推理性能收益

  1. DynamicContextMiddleware 保持静态系统提示,复用 LLM 前缀缓存,降低重复编码开销;
  2. SummarizationMiddleware + TokenBudgetMiddleware 双层控制上下文长度,稳定推理速度;
  3. SystemMessageCoalescingMiddleware 统一系统消息格式,兼容各大推理后端,规避接口报错。

3. 安全与稳定性收益

沙箱审计、工具输出截断、循环检测、子代理限流、安全终止拦截多层风控中间件原生内置,开箱即用,无需业务侧重复开发异常兜底逻辑。

四、适用场景

这套两段式中间件架构适合所有需要长期迭代、多业务领域、多用户会话的生产级 Agent 平台:

  1. 企业内部多功能智能助手(编码、数据分析、文档处理、工单);
  2. 多模态对话 SaaS 产品;
  3. 支持子代理并行任务拆解的复杂规划型 Agent;
  4. 需要强安全审计、资源配额管控的私有化大模型应用。

文末小结

DeerFlow 放弃传统 Agent 继承式扩展的老旧思路,以「中间件插件链」为核心骨架,分层拆解运行时所有横向能力,配套声明式开关、定位装饰器、三级组装策略,同时通过 Skill 机制隔离领域业务上下文。26 个标准化内置中间件覆盖从输入清洗到会话兜底全生命周期,兼顾开发效率、系统稳定性、推理性能与扩展性,为生产级复杂 Agent 提供一套可落地、可长期维护的标准架构范式。

需要我把这篇博客精简成适合官网短文档的版本,或者补充一份可直接运行的最小 Demo 代码吗?

相关推荐
terryso1 小时前
BMAD Loop:把开发循环的控制权,交还给确定性代码
架构
2601_954526753 小时前
【工控底层架构】进口阀门和国产阀门哪个性价比高?从TCO模型到边缘诊断源码的全栈解析
人工智能·架构·硬件工程
an317424 小时前
弹窗数据流设计的两种高阶架构实践
前端·vue.js·架构
熊猫钓鱼>_>4 小时前
智能革命的巨浪——AI时代的社会重构与生存之道
大数据·人工智能·重构·架构·llm·agent·ai-native
doiito(Do It Together)4 小时前
我用 Rust 写了个 AI 媒体管家:Gliding Horse 赋能 media_agent,目标是让 ComfyUI 工作流彻底自动化
人工智能·架构·rust·媒体
Xiaoda115 小时前
vLLM Scheduler:为什么 Continuous Batching 是 LLM Serving 的核心?
架构
江畔柳前堤5 小时前
第07章:Docker 网络模型
运维·网络·git·elasticsearch·docker·容器·架构
AI-好学者6 小时前
RAG知识点_3_高级实践
人工智能·ai·架构·langchain·ai编程
禅思院7 小时前
AI对话前端从入门到崩溃:一个长对话引发的五层优化战争【引子】
前端·面试·架构