Deer-Flow 的子 Agent 委派与并行执行
Deer-Flow 的子 Agent 委派与并行执行
学习目标
- 理解 Deer-Flow 子 Agent 系统的架构设计和隔离机制
- 掌握双线程池架构和并发控制策略
- 学会分析子 Agent 的 SSE 事件流和结果归集
前置知识
本章涉及子 Agent 委派模式的通用原理,建议先阅读:
下文假设你已理解上述概念,直接聚焦 Deer-Flow 的具体实现。
项目实践
子 Agent 注册表
Deer-Flow 通过 SubagentRegistry 管理可用的子 Agent 类型:
- general-purpose:拥有除
task外的所有工具,适用于通用任务 - bash:命令执行专家,仅拥有 shell 工具
每个子 Agent 通过配置文件注册,包含名称、描述、可用工具列表和系统提示。
双线程池架构
子 Agent 的执行引擎(SubagentExecutor)使用双线程池架构:
为什么需要双线程池:
- 调度池负责任务的排队、优先级和并发控制
- 执行池负责实际的子 Agent 运行(可能涉及 LangGraph 状态机、工具调用等)
- 两个池独立扩缩容,避免调度阻塞执行
并发控制
MAX_CONCURRENT_SUBAGENTS = 3 通过 SubagentLimitMiddleware 强制执行。该中间件在模型响应后运行,截断超额 task 工具调用。
15 分钟超时:每个子 Agent 有独立的超时限制,超时后标记为 task_timed_out。
事件流
子 Agent 通过 SSE 向 Lead Agent 发送事件:
| 事件类型 | 说明 |
|---|---|
task_started | 子 Agent 启动 |
task_running | 执行中(可能附带中间结果) |
task_completed | 成功完成,携带结果 |
task_failed | 执行失败,携带错误信息 |
task_timed_out | 超时终止 |
上下文隔离
每个子 Agent 运行在隔离的上下文中:
- 不可见 Lead Agent 的对话历史
- 不可见其他子 Agent 的状态
- 独立的工作目录(通过 ThreadDataMiddleware 创建的 per-thread 目录)
问题与规避
Token 归属
子 Agent 消耗的 Token 需要归因回 dispatching step。Deer-Flow 在 Token 追踪启用时,通过 tool_call_id 缓存子 Agent 的 Token 消耗,合并回 dispatching AIMessage。
过度委派
Lead Agent 可能将简单任务也委派给子 Agent。
规避:在系统提示中明确子 Agent 的适用场景,如”对于需要多步操作或专业工具的任务,使用子 Agent”。
设计取舍
为什么限制为 3 个并发
3 个并发的考虑:
- 每个子 Agent 可能消耗大量 Token,3 个并发避免 Token 爆炸
- 线程池大小为 3,正好匹配并发数
- 超过 3 个并发通常意味着任务分解过细,每个子 Agent 的任务量不足
替代方案:可配置的并发数,根据模型上下文窗口和任务复杂度动态调整。
参考来源
- Deer-Flow CLAUDE.md — Subagent System 章节
packages/harness/deerflow/subagents/— 子 Agent 源码