第 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.x | 2.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 要额外花钱的地方。答案是**「用约束换取灵活性」**:
- 上限约束:2.0 有
subagents.max_total_per_run(每次运行最多几个子 agent)、recursion_limit(最大递归深度)这类硬上限。灵活不是无边界的,边界是显式配置的。 - 沙箱兜底:子 agent 再乱来,也被关在沙箱里,伤害可控。
- 可观测 + 可恢复:checkpoint、trace-id 让「拆错了」能被看见、能回退。
更本质地说:1.x 和 2.0 是「在不同维度上做权衡」——
- 1.x 用「固定结构」换「绝对可控」,适合「任务类型已知且稳定」的场景。
- 2.0 用「运行时灵活性」换「更广的适用面」,代价是要额外补一套约束和观测机制来把灵活性「关回笼子里」。
没有哪个更高级,只有哪个更匹配你的问题。 如果你的任务就是「深度研究」这一种,1.x 的固定流水线反而更稳;如果你要一个「什么都能干」的底座,才值得为 2.0 的灵活性和它的约束成本买单。这和第 5 章「协作式 vs 监督式」的结论一脉相承——架构选择永远是「你最不能容忍哪种失败」的映射。