
DeerFlow 2.0 发布之后社区里讨论最多的一个词从“Deep Research”变成了“Super Agent Harness”。说白了这个版本想解决的核心问题只有一件事把“深度研究”这种重流程能力从演示级的项目变成一个能嵌进业务系统、能被二次开发、能被监控和审计的工程底座。如果你看过 DeerFlow 早期版本应该对它基于 LangGraph 的多智能体编排、规划-研究-反思-报告四段式流程有印象而 2.0 的重点是把这些能力解耦成一个个可替换、可观测、可对外暴露接口的模块。这篇文章会以我们团队实际改造 DeerFlow 2.0 的经历为例从架构拆解、源码读法到 SSE 流式接口封装、可观测性接入把基于 DeerFlow 做 Super Agent Harness 落地的关键细节一次讲清楚。内容更适合准备做二次开发的开发者也适合正在选型深度研究方案的架构师。1. 从 Deep Research 到 Super Agent HarnessDeerFlow 2.0 的定位变化1.1 旧版 DeerFlow为“一次深度研究”而生的重流程早期 DeerFlow 给我的感觉更像一个“重流程的研究机器”。你给它一个问题它按顺序完成规划、执行搜索、反思、生成报告最后输出一份长文。这种模式对“Deep Research”这个单点场景非常合适因为它把所有可能的变数都收进了一个固定的流程图里先规划再研究反思不满意就继续研究满意了就写报告。但这套东西一旦要接入真实业务问题就暴露了。我们最早接 DeerFlow 时面临的第一件事是“流程太死”。有的场景只需要“用户给个关键词系统自动搜索并输出摘要”不需要多轮反思有的场景又要求在写报告之前必须人工审阅研究素材还有的场景希望把研究结果直接塞进下游的企业知识库而不是生成一篇好看的 Markdown。旧版 DeerFlow 的架构虽然清晰但它的边界是写死在 LangGraph 图里的改起来要么动源码要么把整个流程复制一份再改维护成本很高。1.2 2.0 的转型把“研究流程”变成“智能体底座”DeerFlow 2.0 提出的 Super Agent Harness本质上是一种“载体升级”的写法。它不再强调自己是“深度研究框架”而是强调自己是一套能跑复杂 Agent 工作流的底座输入、状态流转、工具调用、流式输出、人工介入、可观测性全部做成了可插拔、可替换的接口。用一句大白话总结1.0 你是在“用 DeerFlow 做研究”2.0 你是“用 DeerFlow 这个壳子围绕你自己的业务定义 Agent 的行为”。这个壳子保留了深度研究最强的部分——规划、研究、反思、报告四个核心节点的能力沉淀但节点的实现不再绑定某个大模型或某个搜索工具用户完全可以替换自己的搜索源、自己的记忆模块、自己的审批流程。这种转型想解决的问题很明确让一个人或一个小团队不需要从零搭建多智能体编排的底层就能在两天内拼出一个能处理复杂任务的“超级智能体”服务。1.3 为什么我建议用“行为工厂”而不是“框架”来理解它很多刚接触 DeerFlow 2.0 的开发者会问它和 LangGraph、AutoGen、CrewAI 到底有什么区别。我的观点是DeerFlow 2.0 更像一个“行为工厂”它给常见 Agent 行为预置好了成熟的生产流水线同时把流水线的“模具”开放给你。你可以在里面定制行为让 Planner 换成你自己的任务分解器让 Researcher 换成对接内部 API 的查询器让 Reflection 换成带评分规则的审查器甚至把 Report 节点整个替换成“写入数据库”的动作。这和 LangGraph 的原始能力并不冲突——LangGraph 是提供状态机和图执行能力的“底层框架”DeerFlow 2.0 是在其上构建的一层“领域模板”。理解这层关系后二次开发时你就不会纠结“要不要自己用 LangGraph 重写一套”因为直接把 DeerFlow 的图结构拎出来改比从零写省太多事。2. 架构拆解一张图看懂 DeerFlow 2.0 的骨架在进入源码之前最好先对整个图的结构有一个全局认知。DeerFlow 2.0 的核心流程依然是四个阶段的循环只是每个阶段都被抽象成了可独立替换的模块。2.1 Planner把用户问题拆成研究计划Planner 负责接收用户输入把它拆解成一系列研究子问题或者任务清单。如果你处理的是“比较三款开源向量数据库的运维成本”这类问题Planner 会拆出“业务背景”“硬件要求”“运维复杂度”“社区活跃度”等子问题再为每个子问题指定研究策略。这部分在旧版中比较机械通常是一轮 prompt 输出 JSON。2.0 里把 Planner 的结果设计成了结构化状态也就是说你可以在计划阶段介入和修正人工改掉某些子问题或者直接从外部系统注入一个计划。我实际测试下来把一个复杂问题从单轮 prompt 拆解改成“分类细化”两段式研究效率会有明显提升。2.2 Researcher真正干脏活累活的节点Researcher 是深度研究里最累的节点。它拿到 Planner 的子任务后会调用搜索 API、抓取网页内容、读取 PDF、汇总信息。DeerFlow 老版本已经内置了一些常用工具2.0 最大的变化是工具接口统一每个工具都是一个可接收上下文并返回结构化结果的函数不再和节点强耦合。这样带来的直接好处是你可以把内置的“通用网页抓取工具”替换成“公司内网检索工具”而不用动 Researcher 的决策逻辑。我们后来就把内网 Confluence 搜索封装成了一个工具节点和公网搜索并列Researcher 会自动根据任务类型选择走哪个工具。这一点是“Super Agent Harness”最实的体现——工具的多少决定了智能体能力的边界而工具的可插拔性决定了智能体能否长在业务里。2.3 Reflection让智能体学会“不满意就重来”Reflection 节点是 DeerFlow 区别于普通“搜索摘要器”的核心。它会把 Researcher 收集到的信息重新审视一遍判断这些材料够不够回答规划阶段提出的问题有没有明显矛盾是否需要补充检索。这个节点在 2.0 里被做成了“可配置的评判器”既可以用一个大模型对材料打分也可以接入规则引擎比如“必须至少包含三个来源”“时效性必须在半年内”。打分结果会决定图的走向如果评审通过进入 Report 节点不通过则带着反思意见回到 Researcher 继续补充研究。这里我想提醒一点反思节点是一把双刃剑它的判断能力直接取决于模型能力和 prompt 设计稍后我会在踩坑部分专门展开。2.4 Report从研究素材到结构化输出Report 节点负责把反思通过后的材料组织成最终输出。DeerFlow 2.0 的 Report 不仅支持生成 Markdown还可以配置输出为 JSON、XML或者直接把结果写入数据库。这意味着它不再是一个“写文章”的节点而是一个“交付物工厂”。我们团队在这个节点上做过一次改造把默认的长文生成 prompt 换成按公司模板生成“问题背景—核心结论—证据引用—待确认事项”的四段式输出会被自动解析成结构化对象对接下游工单系统。效果非常好因为报告生成规则是业务里最常变化的部分而 2.0 的节点边界让替换成本降到了最低。2.5 状态图LangGraph StateGraph 如何把节点串起来DeerFlow 2.0 的图装配基于 LangGraph核心代码结构大致是这样的from langgraph.graph import StateGraph, END # 全局状态 schema所有节点的输入输出都写在这上面 class DeerFlowState(TypedDict): query: str plans: list[dict] research_log: list[dict] reflection_score: float report: str max_iterations: int iteration: int graph StateGraph(DeerFlowState) # 注册核心节点 graph.add_node(planner, plan_node) graph.add_node(researcher, research_node) graph.add_node(reflection, reflection_node) graph.add_node(report, report_node) # 定义起点和主链路 graph.set_entry_point(planner) graph.add_edge(planner, researcher) graph.add_edge(researcher, reflection) # 反思循环分数太低则回到 researcher最多迭代 max_iterations 次 graph.add_conditional_edges( reflection, route_after_reflection, { revise: researcher, complete: report, }, ) graph.add_edge(report, END) app graph.compile()如果你读过老版本的代码会发现结构变化不大但 2.0 的关键差异在节点内部的实现方式上所有节点都通过接口函数和状态交互不再直接调用其他节点。这一点让整个图变成了可插拔的流水线。改动某个节点时只要输入输出契约不变其他节点完全不需要感知。3. 源码拆解从状态定义到反思循环一份 DeerFlow 2.0 代码详解这一节我们直接进入代码细节讲一讲我在阅读 DeerFlow 2.0 源码时认为最值得注意的几个地方。源码给出的实现思路也是二次开发时绕不开的几条主线。3.1 状态数据结构的定义一切调试的起点DeerFlow 的节点之间靠全局状态传递数据因此状态 schema 是整个框架的“数据库表结构”。如果状态定义不合理后面追踪问题和扩展功能都会非常痛苦。一个典型的 2.0 状态定义会把“过程数据”和“交付数据”分开过程数据包括 plans、research_log、reflection_score这些主要用于控制流程图走向和调试交付数据包括 report、structured_output这些是最终要落到业务系统的内容。我建议你在做二次开发时保留这种区分的习惯不要把临时检索结果和最终交付物混在一起否则流量一多状态数据会快速膨胀流式传输时也会带来不少序列化开销。class DeerFlowState(TypedDict): # 输入用户原始问题 query: str # 上下文会话标识、历史摘要、外部注入的约束条件 conversation_id: str constraints: list[str] # 过程数据 plans: list[dict] research_log: list[dict] reflection_score: float iteration: int # 输出数据 report: str structured_result: dict有一个细节值得注意iteration 和 max_iterations 一定要放进状态里不要用全局变量或外部配置来控制循环次数。因为 LangGraph 图在并发执行时每个会话都有自己的状态实例如果把迭代计数放在全局多用户并发时就会出现互相干扰结果就是明明只让用户 A 最多迭代 5 次用户 B 却可能因为共享变量提前结束。3.2 工具封装可插拔的 Fetch 与数据清洗DeerFlow 2.0 的工具层是我看源码时觉得最有学习价值的部分。以网页抓取为例框架不会把“请求网页”和“解析正文”耦合在同一个函数里而是拆成两层fetch 负责获取原始内容parser 负责从 HTML 中提取有效正文。这种拆法在二次开发中极其有用。比如我们接一个内部文档系统只需要替换 fetch 层的实现改成带鉴权的 HTTP 请求parser 层完全复用。数据清洗逻辑里也藏了不少细节抓下来的文本要做字符编码归一化有些站点返回 GBK 或者带 BOM要去除导航栏、广告、脚本标签最好还要把长文本按段落切块方便后续大模型处理。class BaseTool: def run(self, params: dict, context: dict) - list[dict]: raise NotImplementedError class HttpFetchTool(BaseTool): def run(self, params: dict, context: dict) - list[dict]: # 这部分是一个带超时、重试、编码归一化的抓取实现 # 真实项目里还要考虑 robots、频率限制、UA 伪装等问题 return [{type: content, source: params[url], text: cleaned_text}]我强烈建议在封装工具时把每次工具调用的入参、出参、耗时、是否命中缓存都记录到 research_log 里。这些数据不仅在反思节点可以用到后续做可观测性分析时更是宝贵的原始素材。3.3 反思循环的退出条件避免无限空转的关键反思循环是 DeerFlow 最容易被忽视的风险点。如果你不限制迭代次数也没有分数阈值模型对某些冷门问题会反复进入“检索→反思→觉得不够→再检索”的循环既烧 token 又拖慢响应。我在源码里看到的通用做法是组合使用两类条件第一是硬性条件即最大迭代次数通常 3 到 5 次封顶第二是软性条件即反思评分可以是一个 0 到 1 的分数也可以是一组布尔判断。节点的退出逻辑大概是这样的def route_after_reflection(state: DeerFlowState) - str: if state[iteration] state[max_iterations]: # 已经达到硬性上限不管质量如何都直接收尾 return complete if state[reflection_score] 0.8: return complete return revise一个很实用的经验反思评分不要只让大模型给一个笼统分数建议让 Reflection 节点输出几个维度的评分例如“覆盖度”“一致性”“时效性”然后按业务权重算加权分。这样调节行为时你只需要改权重不需要反复改 prompt。我们实际项目里就遇到过“覆盖度足够但时效性很差”的研究结果加权评分比单一分数直观得多。4. 给智能体装上监控可观测性与人机协同的落地4.1 为什么 Deep Research 类的智能体特别难调试如果你的智能体只是单轮“输入输出”那挂个日志基本够用。但 Deep Research 是多节点、多工具、多轮反思的长时间任务一个问题可能产生几十次工具调用。排查问题的时候你不仅要看“模型输出了什么”还要看“每个节点依赖了哪些中间状态”“哪个工具调用了多少次”“反思为什么反复不通过”。这就是可观测性要解决的根本问题。DeerFlow 2.0 把节点间的状态流转做成显式数据后天然适合接追踪系统。这里我的建议是从第一天就接入可观测性平台不要等项目上线再加。我见过太多团队上线后才开始追问题结果因为缺少中间状态日志排查一个简单 Bug 花了整整两天。4.2 接入 LangSmith / Langfuse 追踪LangGraph 生态里最成熟的可观测性方案是 LangSmith也可以用 Langfuse 做开源替代。接入方式不复杂核心是配好环境变量# LangSmith 接入示例 export LANGCHAIN_TRACING_V2true export LANGCHAIN_API_KEYyour_langsmith_api_key export LANGCHAIN_PROJECTdeerflow-production如果用的是 Langfuse通过langfuseSDK 的CallbackHandler直接挂到 LangGraph 的编译结果上from langfuse.callback import CallbackHandler handler CallbackHandler( public_keypk-..., secret_keysk-..., hosthttps://cloud.langfuse.com ) app graph.compile(checkpointercheckpointer) # 在每次 invoke 时传入回调 result await app.ainvoke(initial_state, {callbacks: [handler]})接入之后你要看的核心指标是每个节点的耗时分布、工具调用成功率、反思循环的平均轮数、模型 token 消耗。特别是工具调用的成功率如果某个搜索源频繁超时你会看到 Researcher 节点耗时会异常飙升。这类问题只靠应用日志很难发现但追踪图上会一目了然。4.3 Human-in-the-loop把人工审批嵌入图流程DeerFlow 2.0 作为 Super Agent Harness另一个被频繁提到的能力就是人机协同。研究型任务天然存在风险模型可能抓到一个有误导性的来源或者给出的结论敏感。此时不能让它全自动跑完得在关键节点上停下来等人工确认。LangGraph 提供interrupt机制可以在节点之间插入暂停点。以我们的改造为例在“研究完成、反思通过”之后、进入 Report 之前我们会暂停流程把研究素材和反思结论推送给前端等待人工点击“通过”或“打回”。3分钟没有响应就自动挂起而不是盲目继续。from langgraph.types import interrupt def human_review_node(state: DeerFlowState) - DeerFlowState: review_result interrupt({ type: human_review, payload: { research_log: state[research_log], reflection_score: state[reflection_score], }, }) # 人工返回 approve 或 reject if review_result.get(action) reject: state[constraints].append(review_result.get(reason, )) # 打回后进入反思节点带上人工意见 return state这个设计解决了以前那个很尴尬的问题要么全程无人审核出错了才后悔要么盲目相信人工每一步都打断用户体验非常差。正确做法是抓大放小只在“影响结果质量”的关键节点上设置审批其余环节保持自动。主动设置审批而不是频繁打断才是人机协同的正确姿势。5. 二次开发实战把 DeerFlow 2.0 封装成自己的智能体服务5.1 确定封装边界是“流程服务”还是“对话服务”在开始写代码之前先想清楚你的服务形态。如果你的用户只是偶尔发一个研究任务、等结果那你直接做一个同步请求接口就够了但如果用户希望看到“正在规划”“正在搜索”“反思未通过正在补充材料”这样的过程反馈那就必须上流式接口。DeerFlow 2.0 本身调用耗时通常从几十秒到几分钟不等同步请求很容易触发网关超时。所以我们的推荐方案是服务端始终采用流式响应即通过 SSE 持续推送事件客户端拿到全部事件后自行组装结果。这样既解决了超时问题也天然支持了过程可视化。下面我会重点讲我们封装 SSE 流式接口的整套方案。5.2 用 FastAPI 封装 SSE 流式接口我们选择 FastAPI 作为 HTTP 服务框架原因很简单异步支持好、SSE 实现成本低、OpenAPI 文档自动生成。核心思路是把 DeerFlow 的图编译结果包装成异步生成器每一轮的节点输出被转成 SSE 事件推送出去。import json from fastapi import FastAPI from fastapi.responses import StreamingResponse from deerflow import build_harness app FastAPI() harness build_harness() async def deerflow_events(payload: dict): query payload[query] conversation_id payload.get(conversation_id, ) state { query: query, conversation_id: conversation_id, plans: [], research_log: [], constraints: [], } async for chunk in harness.astream(state): # chunk 是当前节点的输出片段 if plans in chunk: yield sse_event(plan, chunk[plans]) if research_log in chunk: yield sse_event(tool_call, chunk[research_log]) if reflection_score in chunk: yield sse_event(reflection, {score: chunk[reflection_score]}) if report in chunk: yield sse_event(result, {report: chunk[report]}) yield sse_event(done, {}) def sse_event(event_type: str, data) - str: payload json.dumps({type: event_type, data: data}, ensure_asciiFalse) return fdata: {payload}\n\n app.post(/api/research/stream) async def research_stream(payload: dict): return StreamingResponse( deerflow_events(payload), media_typetext/event-stream, headers{ Cache-Control: no-cache, X-Accel-Buffering: no, }, )这里有几个很容易踩的坑我直接说出来第一X-Accel-Buffering: no很关键如果服务前面挂着 Nginx默认会缓冲响应导致客户端等服务端全部算完才收到“data:”流式就名存实亡了第二media_type必须是text/event-stream否则前端 EventSource 解析会异常第三SSE 的每个事件块必须以空行结尾即两个\n。5.3 流式消息协议status / tool_call / reflection / result 四类事件前后端之间的通信协议一定要在第一时间定清楚不然前端会很痛苦。我们最终采用的是一个包裹型的消息协议每条 SSE 消息都是一个带type和data的 JSON便于前端按事件类型分发处理。// 前端解析 SSE 的标准流程 async function parseSSE(response) { const reader response.body.getReader(); const decoder new TextDecoder(); let buffer ; while (true) { const { done, value } await reader.read(); if (done) break; buffer decoder.decode(value, { stream: true }); const blocks buffer.split(\n\n); buffer blocks.pop(); for (const block of blocks) { const line block.trim(); if (!line.startsWith(data:)) continue; const raw line.slice(5).trim(); if (!raw) continue; const event JSON.parse(raw); handleEvent(event); } } } function handleEvent(event) { switch (event.type) { case plan: renderPlan(event.data); break; case tool_call: appendToolRecord(event.data); break; case reflection: showReflectionScore(event.data); break; case result: renderReport(event.data.report); break; case done: finalizeUI(); break; default: break; } }这个协议的关键点是状态机语义清晰前端只处理 5 种事件后端也只发这 5 种事件。如果你将来还要支持人工审批可以在此基础上增加human_review_request事件前端拿到后展示一个审批弹窗再把人工操作通过另一个 POST 接口回传。协议演进时尽量只增加新事件类型不要随意改旧事件的字段结构。5.4 多用户并发与会话管理DeerFlow 图本身并不保存跨会话数据所以多用户并发时你必须自己管理会话状态。我们采用的方案是为每个conversation_id建立一个独立的图执行任务任务的进度保存在内存或 Redis 中SSE 连接只做单向推送用户断开连接不会中断后台任务。这里有几个经验可以分享。第一后台任务的取消机制很重要。用户在浏览器端关闭页面后SSE 连接断开但后台任务可能还在跑。我们会在任务启动时绑定一个自动取消标记如果用户 5 分钟内没有重新订阅就终止任务。第二要控制单任务并发度。DeerFlow 在 Researcher 阶段会并发发起多个搜索请求如果不限流一个人工任务可能瞬间打满你部署的搜索服务额度。第三建议在服务层加一个简单的队列而不是让每个请求都直接去抢模型额度。我们曾经遇到过 20 个并发研究任务同时涌入直接把模型服务限流打爆的情况。6. 踩坑实录DeerFlow 改造中我遇到的 6 个常见问题6.1 模型特定 Prompt 不匹配换模型后效果大跌DeerFlow 的默认 prompt 是在特定模型族上调试出来的。我们最初用默认配置接入某国产开源模型研究质量明显下降尤其是反思节点出现了反复“不通过”的问题。后来我们把 Reflection 节点的评分标准从“通用表述”改成了“带明确 checklist 的量化打分”并调低了模型能力不足时的收敛阈值才恢复正常。提示任何从开源项目里拿到的 prompt 都不是魔法必须先在小样本集上做评测再上线。6.2 网页抓取超时与编码异常Researcher 节点耗时飙升抓取第三方网页时超时、反爬、编码问题是最常见的坑。我们有个阶段经常出现 Researcher 节点跑到 90 秒以上最后发现是某个国外站点 HSTS 握手非常慢默认的超时时间不够。解决办法是给 HTTP 客户端分别设置“连接超时”和“读取超时”对重点域名单独调参。另外从网页中提取正文时一定要处理 UTF-8 之外的编码比如 GB18030不做编码归一化的话进入大模型的文本会出现大量乱码反思节点也会把乱码误判成“材料质量差”。6.3 反思循环次数过多Token 消耗直接翻倍反思节点虽然保证质量但也是最贵的节点。一旦模型打分逻辑不稳很容易让流程陷入“检索→反思→检索”的循环token 消耗成倍增长。我们的经验是最大迭代次数默认设为 3并为每个迭代轮次设计了递减的评分阈值第一轮 0.8第二轮 0.75第三轮 0.7。也就是说越到后面越“放水”避免无限空转。6.4 人工审批事件被流式通道吞掉在做 Human-in-the-loop 时我们遇到过前端已经收到human_review_request事件但用户提交审批回传后后端流程没有恢复的问题。排查后发现是因为我们把审批回传做成了另一个独立的 HTTP 接口但该接口没有绑定到原来的图执行实例上相当于给一个不存在的任务发了指令。解决方法是统一维护一个任务注册表把所有conversation_id和graph_instance的对应关系存在里面回传时先查注册表确保操作的是同一个内存对象。6.5 部署时 Nginx 缓冲把 SSE 变成了“假流式”这个问题前面已经提过但值得再强调一次。我们第一次部署后前端表现完全是“等了 1 分钟突然把所有内容一次性吐出来”。原因就是 Nginx 默认开启了缓冲。解决方式是在 Nginx 配置里对 SSE 路径添加proxy_buffering off;同时服务端返回响应时带上X-Accel-Buffering: no头。在云厂商的 Kubernetes 环境里还要检查 Ingress Controller 是否也有类似缓冲配置比如 Nginx Ingress 的nginx.ingress.kubernetes.io/proxy-buffering: off注解。6.6 日志量在并发场景下迅速膨胀智能体任务的日志量远大于传统业务接口因为每个工具调用、每次模型返回都要记录。没有做采样和分级之前我们一天跑下来日志量达到几个 GB。后来把日志分成两级全量写入追踪平台LangSmith/Langfuse应用日志只保留关键节点事件启动、节点切换、完成、报错。同时给日志加上 conversation_id 字段方便在日志系统里按链路追踪。这样既保证了排查问题需要的上下文也不会把日志成本打爆。7. 关于二次开发我的几点实在建议7.1 先跑通最小闭环再追求扩展基于 DeerFlow 2.0 做二次开发时最大的诱惑是一上来就想把架构改得多完美。我的建议是第一周先原样跑通一个最小闭环一个查询进来经过四个节点输出一份报告。期间把追踪系统、日志规范、SSE 接口全部搭好。只有在闭环跑通之后再去替换 Planner 或 Researcher 的实现。因为如果你一边加业务逻辑一边改框架出了问题你根本分不清是框架的 bug 还是你业务代码的 bug。7.2 把状态 schema 当成 API 契约来管理DeerFlow 的节点之间通过状态通信因此状态字段的增删改就是一次 API 变更。我们团队现在规定任何改动状态 schema 的操作都必须同步更新文档和字段说明并标注兼容性影响。有一个阶段我们随意往 research_log 里塞了一个字段导致旧流程的序列化报错排查花了不少时间。状态 schema 是二次开发里最容易失控的地方一定要用契约管理。7.3 留足人工干预的接口即便你的目标场景没有明确的人工审批需求我也建议在架构上预留 Human-in-the-loop 接口。原因很简单大模型研究类应用上线后你一定会遇到“计划外”的坏案例。届时如果没有人工干预接口你只能靠修改 prompt 或加工具来修复而这两者都可能引入新问题。预留一个简单的审批节点成本很低但能显著提升系统的容错能力。7.4 后续可以扩展的方向如果你问我 DeerFlow 2.0 接下来还能往哪走我认为有几个方向很值得探索一是把长期记忆模块接入状态机让智能体记住用户的研究偏好二是把工具调用从“单次 Fetch”升级成“多步任务链”比如先检索、再根据结果决定是否需要下载附件三是把反思结果做成可回放的数据集用于定期评估和回归测试。这些方向本质上都在从“能用”走向“好用”而 DeerFlow 2.0 给出的底座让这些扩展不再需要推到重来。我个人在实际改造中的体会是DeerFlow 2.0 最有价值的不是它现成的几个节点而是它展示了一个经过验证的 Agent 工作流应该长什么样。照着它的方式组织状态、工具、节点和可观测性即便你最后没有直接使用这个框架也能把一套稳定的多智能体系统搭起来。如果你正准备基于它做自己的 Super Agent Harness先从最小闭环开始把观测和人工干预接口留好后面你会发现扩展比想象中顺利得多。