第 10 章 · 从 1.x 到 2.0:固定流水线为什么会「不够用」

一句话结论:DeerFlow 1.x 是一台「深度研究专用机」,2.0 把它重写成了「通用超级智能体编排框架(SuperAgent harness)」。这次重构的动机,浓缩成一句话就是——「固定角色流水线」太特化了,用户真正需要的是一个「通用协调底座」,让任何任务都能临时组建一支 agent 小队。


1. 1.x 的「隐性天花板」

1.x 的架构我们已经很熟了:Coordinator → Planner → Researcher/Coder → Reporter,五个角色写死,专为「深度研究」服务。

它的问题在于:角色是「预定义死的」,流程是「针对研究任务雕刻的」。

  • 你想让它「写一个爬虫脚本并部署」?没有对应的角色。
  • 你想让它「分析一份财报、生成 PPT、再录成播客」?流水线装不下这种「复合、非研究」的任务。
  • 你想加一个新角色「UI 设计师」?得改核心代码。

一句话:1.x 把「多 agent 协调」这个通用问题,硬生生做成了一个「研究专用」的答案。 协调能力是通用的,但被角色和流程的特化给锁死了。


2. 思考的分叉:怎么从「专用机」走向「通用底座」?

方向 A:继续给 1.x 加角色(加 Coder2、加 Designer……)。

  • 代价:角色列表无限膨胀,每个新角色都要改核心图,治标不治本。

方向 B:把「角色」从「写死的代码」变成「可配置的实体」,让系统根据任务动态组建小队。

  • 这就是 2.0 的路线:一个 Lead Agent(主导智能体)+ 按需 spawn 的子 agent(sub-agents)+ 沙箱 + 记忆。

为什么选 B:因为「角色」的本质,是「一个 system prompt + 一套工具 + 一份上下文」的封装(还记得第 2 章吗)。这三样完全可以做成数据/配置,而不是代码。一旦角色是数据,那么「组建一支什么小队」就从「改代码」变成了「运行时决策」——Lead Agent 看着任务,临时决定「我需要一个研究员、一个程序员、一个设计师」,然后动态拉起它们。


3. 伪代码:2.0 的 harness 抽象

2.0 提出了一个公式:Agent = Model + Harness。模型是大脑,harness 是身体。身体(协调、工具、沙箱、记忆)才是让大脑真正「能干活」的工程底座。

class Harness:                          # 通用协调底座
    def __init__(self):
        self.lead_agent = LeadAgent()   # 主导智能体:唯一的「总指挥」
        self.sandbox = Sandbox()        # 沙箱:隔离执行代码/命令
        self.memory = Memory()          # 记忆:跨会话的长短期记忆
 
    def run(self, task):
        # Lead Agent 自己判断:要不要拆?拆成几个子 agent?
        subtasks = self.lead_agent.decompose(task)
        for sub in subtasks:
            sub_agent = self.spawn_subagent(role_for(sub))  # 动态拉起一个子 agent
            sub_agent.run(sub, sandbox=self.sandbox)        # 子 agent 在沙箱里干活
        return self.lead_agent.synthesize()
 
    def spawn_subagent(self, role):
        # 角色不再是写死的类,而是「prompt + 工具 + 上下文」的封装,按需生成
        return SubAgent(prompt=role.prompt, tools=role.tools)

和 1.x 对比,变化一目了然:

维度1.x2.0
角色5 个写死的类按需动态生成
流程固定的研究状态图Lead Agent 自主编排
协调中心Supervisor 节点Lead Agent
执行环境直接跑沙箱隔离(Docker/E2B)
记忆无(或很弱)显式的长短期记忆
定位深度研究工具通用超级智能体编排

4. 但 2.0 不是「推翻」,是「去特化」

关键认知:2.0 没有否定 1.x 的协调思想,而是把它抽象成了一套通用的「协调六层」(DeerFlow 团队自己总结的六层 harness 架构,每层对应一个「agent 为什么会死」的根因):

层解决什么问题对应本教程章节
规划与编排(Planning & Orchestration)任务分解、控制流第 3、5 章
上下文工程(Context)窗口溢出第 7 章
容错(Fault Tolerance)一错全崩第 9 章
状态管理(State)检查点丢失第 4 章
工具调用(Tool Calling)不可逆的错误操作第 6 章
可观测性(Observability)不知道死在哪贯穿始终

你会发现:第 1~9 章讲的每个协调问题,都能在这张表里找到位置。 1.x 到 2.0,不是「换了个更好的框架」,而是把「研究专用流水线里那些做对了的协调思想」,提炼成了「任何 agent 系统都该有的一层通用底座」。


5. 为什么这值得一个 Go 程序员重视

你是做 Go 的,可能对 Python/LangGraph 生态有点「隔层」。但请看清这背后的语言无关的工程本质:

  • 1.x → 2.0 的演进,本质是**「从具体业务的硬编码,走向通用基础设施的抽象」——这和你在后端做的「从业务代码抽公共库」「从单体拆服务」是同一种思维**。
  • 「角色是数据不是代码」「协调靠共享状态和契约」「分层容错」——这些概念,用 Go 的 goroutine + channel、interface + 依赖注入、context + 超时,全都能落地。
  • 第 11 章我会给你一张「协调设计清单」,你可以照它用 Go 造一个自己的多 agent 框架——语言只是载体,协调的设计思想才是硬通货。

思考题

Q:2.0 让 Lead Agent「自己决定拆几个子 agent」,这看起来更灵活了,但也可能更不可控——Lead Agent 拆错了、拆多了怎么办?相比 1.x 的「固定角色 + 固定流程」,2.0 是不是用一个「可控的问题」换来了一个「不可控的问题」?

参考答案:

这个担心是对的,而且正是 2.0 要额外花钱的地方。答案是**「用约束换取灵活性」**:

  1. 上限约束:2.0 有 subagents.max_total_per_run(每次运行最多几个子 agent)、recursion_limit(最大递归深度)这类硬上限。灵活不是无边界的,边界是显式配置的。
  2. 沙箱兜底:子 agent 再乱来,也被关在沙箱里,伤害可控。
  3. 可观测 + 可恢复:checkpoint、trace-id 让「拆错了」能被看见、能回退。

更本质地说:1.x 和 2.0 是「在不同维度上做权衡」——

  • 1.x 用「固定结构」换「绝对可控」,适合「任务类型已知且稳定」的场景。
  • 2.0 用「运行时灵活性」换「更广的适用面」,代价是要额外补一套约束和观测机制来把灵活性「关回笼子里」。

没有哪个更高级,只有哪个更匹配你的问题。 如果你的任务就是「深度研究」这一种,1.x 的固定流水线反而更稳;如果你要一个「什么都能干」的底座,才值得为 2.0 的灵活性和它的约束成本买单。这和第 5 章「协作式 vs 监督式」的结论一脉相承——架构选择永远是「你最不能容忍哪种失败」的映射。