DeerFlow 深度解析:如何用多智能体架构精准答题
DeerFlow 深度解析:如何用多智能体架构精准答题
先收藏,这篇文章信息量有点大。
如果让一个 LLM 直接做 50 道中学试题,它能拿多少分?大概率不会太差。但如果要求它必须全对——错一道就要扣分——事情就完全不同了。
单个 LLM 在面对确定性任务时有几个致命弱点:幻觉编造事实、跳过难题、不会自我纠错,以及那种"明明算错了还特别自信"的迷之态度。
字节跳动最近开源的 DeerFlow(Deep Exploration and Efficient Research Flow)——一个能编排子代理、记忆系统和沙箱的超级智能体框架——提供了另一种解题思路:不让一个 Agent 做题,让两个 Agent 互相博弈。
本文会深度拆解 DeerFlow 的核心架构,然后手把手演示如何用它构建一个多 Agent 应试系统,精准解答 awesome-agent-design-comparison 项目中的 50 道考题。
本文提纲
- 认识 DeerFlow:字节跳动的超级智能体工厂
- 50 道题,8 个学科——这个 Benchmark 到底在测什么
- 核心设计:双循环多 Agent 架构
- 内循环——Resolver + Validator 的攻防博弈
- 外循环——Orchestrator 的全覆盖保障
- DeerFlow 的独门武器:记忆、技能与上下文工程
- Hands-on:用 DeerFlow 跑通这套题
- 为什么这个架构能行——从幻觉到验证的范式转变
认识 DeerFlow:字节跳动的超级智能体工厂
DeerFlow 2.0 是一个完全重写的版本(与 v1 零代码共享),2026 年 2 月上线当天就冲上 GitHub Trending #1。它的定位很清晰:编排子代理、记忆和沙箱来完成长周期复杂任务。
它不是"又一个 Agent 框架"。它的核心差异在于三个设计选择:
1. 可插拔的 Memory 系统
DeerFlow 的记忆系统是整个框架中最复杂的模块。它基于 MemoryManager 抽象基类,默认实现 DeerMem 是一个完全自包含的记忆后端:
MemoryManager (ABC)
├── DeerMem (默认后端)
│ ├── Storage (FileMemoryStorage) → ~/.deermem/
│ ├── Queue (MemoryUpdateQueue)
│ ├── Updater (独立 LLM 调用,不依赖主模型)
│ └── Message Processing
└── NoopMemoryManager (空操作后端)几个关键设计:
- LLM 独立性:记忆更新使用独立的 LLM 调用(通过
langchain init_chat_model),不占用主 Agent 的 context - 安全防护:记忆事实在注入 prompt 前做 HTML 转义,防止
</current_memory>注入攻击 - 优雅关闭:
shutdown_flush机制保证 K8s 环境下的记忆不丢失——配置terminationGracePeriodSeconds(默认 45 秒)等待排空 - 用户隔离:按用户 ID 隔离存储路径:
{storage_path}/users/{safe_user_id}/memory.json
这意味着:Agent 可以有"长期记忆",跨 session 记住之前做过什么、哪个方法有效、哪个坑踩过了。
2. 技能驱动的可扩展性
DeerFlow 使用 Skills(技能)作为 Agent 能力的核心载体。你可以给 Agent 装上各种技能:
- 图像生成(Gemini、MiniMax 等提供商)
- 视频生成(异步轮询/下载)
- 播客生成(TTS)
- 音乐生成(MiniMax)
- Claude Code 集成(一键开发环境搭建)
公共技能包位于 skills/public/,CI 中还有自动技能审查质量门控。
3. 多模型 + 沙箱 + 上下文工程
DeerFlow 支持的模型配置极其灵活:
models:
- name: gpt-4o
use: langchain_openai:ChatOpenAI
model: gpt-4o
- name: qwen3-32b-vllm
use: deerflow.models.vllm_provider:VllmChatModel
supports_thinking: true
- name: openrouter-gemini-2.5-flash
use: langchain_openai:ChatOpenAI
base_url: https://openrouter.ai/api/v1沙箱后端支持 Docker、Kubernetes(通过 Provisioner)、远程沙箱,并且是 fail-closed 安全模型——不配 API Key 时所有 /api/* 请求返回 401。
上下文工程方面,DeerFlow 包含约 26 个有序中间件:InputSanitization、TokenBudget、DynamicContext、ToolOutputBudget、SafetyFinishReason 等——在长周期任务中管理 token 消耗至关重要。
graph TB
subgraph "DeerFlow Core Services"
N[Nginx :2026]
G[Gateway :8001]
F[Frontend :3000]
P[Provisioner :8002]
end
subgraph "Agent Runtime"
SA[Sub-Agents]
SK[Skills]
MM[Memory Manager]
SB[Sandbox]
end
subgraph "Middleware Chain"
IS[InputSanitization]
DC[DynamicContext]
TB[TokenBudget]
TO[ToolOutputBudget]
SF[SafetyFinishReason]
end
N --> G
G --> F
G --> P
G --> SA
SA --> SK
SA --> MM
SA --> SB
IS --> DC --> TB --> TO --> SF
style N fill:#FF6B6B,color:#000000
style G fill:#4ECDC4,color:#000000
style F fill:#45B7D1,color:#000000
style P fill:#96CEB4,color:#000000
style SA fill:#FFEAA7,color:#000000
style SK fill:#DDA0DD,color:#000000
style MM fill:#98D8C8,color:#000000
style SB fill:#FF6B6B,color:#00000050 道题,8 个学科——这个 Benchmark 到底在测什么
awesome-agent-design-comparison 是一个专门用来比较不同 Agent 框架设计差异的 Benchmark 项目。它的数据集是 50 道翻译成英文的中学入学考试题,涵盖:
| 学科 | 选择题 | 简答题 | 总计 |
|---|---|---|---|
| 语文 | 5 | 3 | 8 |
| 数学 | 4 | 4 | 8 |
| 英语 | 5 | 3 | 8 |
| 物理 | 4 | 2 | 6 |
| 化学 | 4 | 2 | 6 |
| 生物 | 4 | 2 | 6 |
| 历史 | 3 | 1 | 4 |
| 地理 | 3 | 1 | 4 |
| 总计 | 32 | 18 | 50 |
这不是一个"看谁 LLM 更聪明"的比赛。项目的目标架构是 同一个多 Agent 设计在不同框架(OpenAI Agents SDK、Google ADK、LangGraph、CrewAI)上用各自惯用写法实现,然后统一评分比较。
评分采用混合模式:
- 确定性 rubric(默认):完全可复现,不消耗 API
- LLM-as-judge(
--judge llm):更细致,但非确定性
每个框架的分数归一化到 [0,1],按题目、学科、题型分别统计。
这里面最有趣的部分不是题目本身——大部分题目对 LLM 来说并不难。真正的挑战在于架构设计是否能让 Agent 系统稳定地、可验证地、全覆盖地答对所有题目。一道题都不会被遗漏;每道题的答案都经过独立验证;出错时有纠错机制。
核心设计:双循环多 Agent 架构
这是整个系统最精妙的部分。为什么不直接让一个 Agent 做题?
因为单一 Agent 的自我检查倾向于给自己的答案"放水"——心理学上叫 confirmation bias,技术上叫 rubber-stamping。解决办法是:让两个 Agent 互相掐架。
项目的参考架构定义了五个 Agent 角色:
| 角色 | 循环 | 职责 |
|---|---|---|
| Orchestrator(根节点) | 外循环 | 驱动整体进度,判定何时所有题目已解答 |
| Resolver(解题者) | 内循环 | 针对一道题给出答案和推理过程 |
| Validator(验证者) | 内循环 | 独立验证 Resolver 的答案;接受或要求修改 |
| Summary Report(终结节点) | 终结 | 外循环结束后生成最终结果报告 |
| Report Writer(Phase 6) | 终结 | 写入 result/results.json |
graph TB
subgraph "Outer Loop - Coverage"
O[Orchestrator Agent]
end
subgraph "Inner Loop - Per Question"
R[Resolver Agent]
V[Validator Agent]
end
subgraph "Terminal"
SR[Summary Report Agent]
end
O -->|"next question"| R
R -->|"answer + reasoning"| V
V -->|"REVISE: feedback"| R
V -->|"ACCEPT"| O
O -->|"all done"| SR
style O fill:#FF6B6B,color:#000000
style R fill:#4ECDC4,color:#000000
style V fill:#45B7D1,color:#000000
style SR fill:#96CEB4,color:#000000Agent 之间通过类型化的 Pydantic 消息通信,确保交接明确可测:
class ResolverOutput(BaseModel):
response: str # 选择题是单个字母,简答题是文本
reasoning: str # 推理过程
class ValidatorVerdict(BaseModel):
accepted: bool
feedback: str = "" # 接受时为空;拒绝时为修改理由
checked_answer: str # Validator 自己独立推导出的答案
class QuestionStatus(BaseModel):
question_id: str
final_response: str
accepted: bool
attempts: int
validator_answer: str | None内循环——Resolver + Validator 的攻防博弈
内循环是整个系统正确率的核心保障。每一道题都经历这样一个过程:
do {
answer = Resolver.solve(question, previous_feedback?)
verdict = Validator.check(question, answer)
if verdict is REVISE:
previous_feedback = verdict.reason
} while not accepted and attempts < MAX_ATTEMPTS这里有几个关键设计决策值得展开:
为什么 Validator 不能看到参考答案?
项目的默认配置是 VALIDATOR_SEES_REFERENCE = false。Validator 必须从第一性原理重新推导答案——和真人考官一样。如果 Validator 看到了参考答案,它就变成了"对答案"而非"验算",失去了独立验证的意义。
项目专门预留了一个 ablation study:VALIDATOR_SEES_REFERENCE = true 模式,用来衡量"独立性"到底贡献了多少正确率提升。
为什么 MAX_ATTEMPTS 默认是 3?
超过 3 轮 Resolver 和 Validator 还在互相争执,大概率是题目本身有问题或者两个 Agent 都理解偏了。此时强行终止,记录最后一个答案并标记 accepted=false。这比无限循环好得多——既控制了成本,又保证了结果可追溯。
内循环的通信格式
Resolver 输出的是 {response, reasoning},Validator 返回的是 {accepted, feedback, checked_answer}。注意 checked_answer 这个字段——Validator 必须自己算出一个答案,而不是仅仅说"你对"或"你错"。这迫使 Validator 真的去思考题目,而不是做表面功夫。
sequenceDiagram
participant O as Orchestrator
participant R as Resolver
participant V as Validator
O->>R: question + context
R->>R: solve question
R->>V: answer + reasoning
V->>V: independently re-derive
alt answer is correct
V->>O: ACCEPT
O->>O: mark as done
else answer needs revision
V->>R: REVISE (feedback + checked_answer)
R->>R: re-solve with feedback
R->>V: revised answer
V->>V: re-check
end外循环——Orchestrator 的全覆盖保障
外循环解决的是一个看似简单但单 Agent 经常搞砸的问题:确保每道题都被解答。
单个 LLM 在处理 50 道题时,偶尔会"遗忘"某道题。它可能觉得自己已经做完了,但实际上漏了 3 道。这在考试场景中是不可接受的。
Orchestrator 的逻辑很直接:
addressed = {}
while not all(addressed.values()):
q = next_unanswered_question()
answered = run_inner_loop(q)
addressed[q.id] = answered
run_summary_report(addressed)它会维护一个 addressed 字典(或者用 DeerFlow 的 Memory 系统持久化),每完成一道题就标记一个 QuestionStatus。只有当所有 50 道题都有状态记录时,外循环才终止。某道题就算在内循环中出错(比如 Resolver 抛了异常),也会被记录为 raw.error,不会导致整个流程卡死。
这个设计保证了完整的可审计性:最终报告中每个题目都有 accepted、attempts、validator_answer 等字段,部分失败一目了然。
DeerFlow 的独门武器:记忆、技能与上下文工程
现在我们来看看,用 DeerFlow 实现这套架构时,哪些组件正好派上用场。
1. Sub-Agents —— Resolver 和 Validator 的天然载体
DeerFlow 的子代理系统原生支持创建独立的 Agent 实例,每个有独立 context 和 tool 权限。这正是 Resolver 和 Validator 需要的隔离性——它们不能共享"思路",否则 Validator 就不是独立验证了。
DeerFlow 还支持 subagents.max_total_per_run 配置,可以精确控制内循环的资源消耗。
2. Skills —— 按学科加载领域知识
DeerFlow 的技能系统可以这样用:
- 加载
math-solver技能:包含代数运算、因式分解、三角函数等知识 - 加载
physics-solver技能:包含牛顿定律、欧姆定律、运动学公式 - 加载
language-analyzer技能:包含修辞手法识别、成语解释、被动语态转换 - 加载通用
exam-taker技能:包含选择题策略、简答题结构、评分 rubric 理解
每个 Resolver 实例在处理特定学科的题目时,可以动态加载对应的技能包。这不仅提高了准确率,还降低了每个 Agent 的 context 负担——不需要把所有学科知识一次性塞进 prompt。
3. Memory —— 跨题目的学习积累
DeerFlow 的 Memory 系统在这里有几种巧妙用法:
- Orchestrator 的状态追踪:用 Memory 持久化"已解答的题目列表",即使 session 中断也能恢复
- Resolver 的经验积累:同类题目的解题模式可以存入 Memory——比如"做因式分解题时,先检查是否有公因数"
- Validator 的常见错误模式:如果 Resolver 反复在某些题型上出错(比如总是搞混 sin 30° 和 cos 30°),Validator 可以在 feedback 中引用过往记忆
Memory 的 shutdown_flush 机制在这里也很关键——50 道题跑完可能需要较长时间,中间不能丢失状态。
4. Context Engineering —— 长周期任务的生命线
50 道题意味着很长的对话历史。DeerFlow 的 Token Budget 中间件会持续监控 token 消耗,Dynamic Context 中间件根据当前题目动态注入最相关的上下文(而非整个学科的教科书)。
Manual Context Compaction(手动上下文压缩)可以让 Orchestrator 在必要时主动清理无关历史,腾出 token 空间。
5. Sandbox —— 数学题的终极验证
对于数学题,最好的验证不是让 Validator 的 LLM 再算一遍——而是让代码跑一遍:
# Resolver 声称 x²-5x+6 的因式分解是 (x-2)(x-3)
# Validator 让沙箱验证:
from sympy import expand, symbols
x = symbols('x')
assert expand((x-2)*(x-3)) == x**2 - 5*x + 6 # TrueDeerFlow 的 Docker/K8s 沙箱让这种验证成为可能——Resolver 给出符号答案,Validator 在沙箱中运行验证代码,ACCEPT 或 REVISE 完全基于实际计算结果。
6. 各框架如何实现同一架构的对比
项目的精妙之处在于:同一个五角色设计,在不同的 Agent 框架中有截然不同的实现方式:
| 框架 | Orchestrator | 内循环 | Summary | 核心优势 |
|---|---|---|---|---|
| OpenAI Agents SDK | Runner loop |
handoff chain + output_type |
Agent 渲染报告 | 类型化输出最简洁 |
| Google ADK | SequentialAgent |
LoopAgent 包装 Resolver+Validator |
LlmAgent |
原生支持循环 Agent |
| LangGraph | StateGraph "route-next" 节点 | "resolve" → "validate" 节点 + conditional edge | "summarize" 节点 | 显式状态流最灵活 |
| CrewAI | Crew 遍历所有题目 | Agent 角色 "Examiner" + "Verifier" + Task 委托 | Agent "Reporter" | 角色分工最直观 |
Hands-on:用 DeerFlow 跑通这套题
下面给出一个基于 DeerFlow 的概念实现框架。这不是完整的可运行代码,而是展示核心组件的装配方式:
步骤 1:定义 Skills
# skills/public/exam-solver/SKILL.md
---
name: exam-resolver
description: Solve exam questions with step-by-step reasoning
---
You are an exam solver. For each question:
1. Identify the subject and question type
2. Show your step-by-step reasoning
3. For multiple choice: return the letter only
4. For short answer: return the complete answer text
5. Output as: { "response": "...", "reasoning": "..." }# skills/public/exam-validator/SKILL.md
---
name: exam-validator
description: Independently verify exam answers
---
You are an exam validator. Your job is to CHECK answers, not produce them.
1. Re-derive the answer independently — do NOT trust the Resolver's reasoning
2. Compare your answer with the Resolver's
3. If they match: return ACCEPT
4. If they differ: return REVISE with specific, actionable feedback
5. Always include your own derived answer as checked_answer步骤 2:装配 Agent 流水线
# 伪代码——展示组装逻辑
from deerflow import Agent, SubAgent, Memory, Skill, SessionGoal
# 建立会话目标
goal = SessionGoal(
description="Answer all 50 exam questions from the benchmark dataset"
)
# 创建 Orchestrator
orchestrator = Agent(
name="orchestrator",
model="gpt-4o",
goal=goal,
memory=Memory(storage="deermem"),
sub_agents=[],
)
# 为每道题创建 Resolver + Validator 对
for question in dataset:
resolver = SubAgent(
name=f"resolver-{question.id}",
skills=[Skill("exam-resolver")],
tools=["calculator", "sandbox-python"],
max_attempts=1,
)
validator = SubAgent(
name=f"validator-{question.id}",
skills=[Skill("exam-validator")],
tools=["calculator", "sandbox-python"],
max_attempts=1,
)
# 内循环:Resolver → Validator → (revise?) → Resolver → ...
result = inner_loop(question, resolver, validator, max_attempts=3)
memory.store(question.id, result)
# 生成最终报告
summary_agent = Agent(name="summary", model="gpt-4o")
report = summary_agent.run(
prompt="Generate results.json from memory",
memory=memory,
)步骤 3:启动服务
# 克隆 DeerFlow
git clone https://github.com/bytedance/deer-flow.git
cd deer-flow
# 一键设置
make setup
# Docker 部署
docker compose up -d
# 或者本地开发
make dev步骤 4:运行 Benchmark 并评分
# 每个框架的 run.sh 会生成 result/results.json
cd frameworks/deerflow/
./run.sh
# 用共享 Grader 评分
python -m grader.grade \
--result frameworks/deerflow/result/results.json \
--dataset dataset/questions.json
# 对比所有框架
python -m grader.grade_all --report-dir reports/为什么这个架构能行——从幻觉到验证的范式转变
回到开头的问题:为什么一个 LLM 直接做题不够好,但两个 LLM 互相博弈就能大幅提升正确率?
答案在于改变了验证的性质。
单个 LLM 自检的问题在于,它使用的是和生成答案时同一个推理路径。如果推理路径一开始就歪了,自检只是在错误的方向上确认自己没错。这就像让学生自己批改自己的卷子——有良心的学生会认真检查,但大多数人做不到完全客观。
Resolver + Validator 模型的关键是 independence:
- 独立上下文:Validator 不知道 Resolver 是怎么想的,它只能看到答案和推理过程
- 独立推导:Validator 必须从零开始推导,不能偷懒复述 Resolver 的思路
- 对抗立场:Validator 的角色设计就是"找茬"。Resolved 对了就 ACCEPT,错了就给精确的 REVISE feedback
- 可审计性:每道题都有
attempts、validator_answer、accepted字段,评审者可以追溯每一次判定
这种模式不只是适用于考试题。任何要求高准确率 + 可验证性的场景——代码审查、财务审计、医疗诊断辅助、法律文书审核——都可以从 Resolver + Validator 架构中受益。
DeerFlow 真正的价值也不在于它跑得比谁快,而在于它提供了一套生产级的可插拔基础设施:Memory 让你有长期记忆,Skills 让你按需加载能力,Sandbox 让你安全执行代码,Middleware 让你精细控制上下文——这些加在一起,才让 Resolver + Validator 模式从概念验证变成可部署的系统。
参考文档与链接
- GitHub: bytedance/deer-flow — 字节跳动开源的 SuperAgent 框架,2,631 commits,MIT 许可证
- GitHub: itech001/awesome-agent-design-comparison — Agent 框架设计对比 Benchmark 项目
- Dataset: questions.json — 50 道考试题数据集
- Agents Design Document — 多 Agent 架构参考设计文档
- DeerFlow Docs: Memory System — DeerMem 可插拔记忆后端设计
- DeerFlow Docs: Skills — 技能系统和公共技能包
- DeerFlow Docs: Sandbox — Docker/K8s/Remote 沙箱后端
- LangGraph Documentation — StateGraph + conditional edge 参考
- OpenAI Agents SDK — Agent + output_type 实现参考
- Google ADK — LoopAgent + SequentialAgent 参考
- CrewAI Documentation — Role-based Agent 协作参考
- awesome-agent-design-comparison Grader — 共享评分器(确定性 rubric + LLM-as-judge)
你觉得 Resolver + Validator 这招在你的场景里能用吗?评论区聊聊你的 Agent 架构,踩过坑的尤其欢迎。觉得有启发就点个赞,让更多人看到这个思路。
作者: itech001 来源: 公众号:AI人工智能时代 网站: https://www.theaiera.cn/ 每日分享最前沿的AI新闻资讯和技术研究。
本文首发于 AI人工智能时代,转载请注明出处。