动态 Agent 执行:Map/Tree 运行时分裂
动态 Agent 执行:Map/Tree 运行时分裂
学习目标
读完本章后,你将能够:
- 理解动态 Agent 分裂模式的设计动机与适用场景
- 掌握 Map 和 Tree 两种分裂模式的区别与实现
- 设计安全的分裂策略(正则 / JSONPath)与并发控制
- 分析动态分裂与预定义并行的权衡
1. 概念定义
1.1 什么是动态分裂
动态 Agent 执行 指在图运行过程中,根据流经边的消息内容,将目标 Agent 节点在运行时分裂为多个并行实例,每个实例处理消息的一个子单元。
这与预定义并行(在 YAML 中写死多个并行节点)的本质区别在于:并行数量由运行时数据决定,而非配置时决定。
1.2 行业背景
动态并行是 2025-2026 年多 Agent 编排的核心模式之一:
| 框架 | 动态并行能力 |
|---|---|
| LangGraph | Send API 支持运行时动态扇出 |
| Mastra | .map() 控制流操作符 |
| AWS Bedrock AgentCore | 线程池 + 异步 I/O 并行调用 |
| AgentSpawn | 自适应 Agent 分裂与记忆转移 |
| Claude Code | 动态工作流可生成数百个并行子 Agent |
2. Map 模式
2.1 执行流程
2.2 分裂策略
| 策略 | 描述 | 适用场景 | 风险 |
|---|---|---|---|
| Regex Split | 正则匹配提取子串 | 自由格式文本 | 正则不匹配时行为不确定 |
| JSONPath Split | JSON 路径查询 | 结构化 JSON 输出 | 非 JSON 输入时失败 |
| Message Split | 每条消息一个单元 | 批量消息场景 | 消息粒度可能过粗 |
2.3 并发控制
dynamic: type: map split: type: regex config: pattern: "<Query>:\\s*(.*)" max_parallel: 3 # 限制并发数,防止资源耗尽max_parallel 是安全阀:
- 不设置 → 所有实例同时执行(可能数百个)
- 设置为 N → 最多 N 个实例并发,其余排队
3. Tree 模式
Tree 是 Map 的递归扩展,支持多级分裂:
与 Map 的区别:
| 维度 | Map | Tree |
|---|---|---|
| 分裂层级 | 一级 | 多级递归 |
| 结果处理 | 扁平化 | 递归归约 |
| 复杂度 | O(N) | O(N^d),d 为深度 |
| 适用场景 | 简单并行任务 | 层次化任务分解 |
4. 设计要点
4.1 执行上下文隔离
每个动态实例必须拥有独立的执行上下文:
原始上下文 ── 复制 ──> 实例 1 上下文 ──> 实例 2 上下文 ──> 实例 N 上下文隔离维度:
- 记忆状态:每个实例独立读写
- 工具调用历史:不共享 tool call 记录
- 错误处理:一个实例失败不影响其他
4.2 结果收集
Map 模式的结果收集有两种策略:
| 策略 | 行为 | 适用场景 |
|---|---|---|
| 扁平化 | 所有结果放入一个列表 | 下游节点统一处理 |
| 逐条推送 | 每个结果立即推送给下游 | 流式处理场景 |
4.3 静态输入与动态输入的混合
动态节点可以同时接收两类输入:
静态输入(来自非动态边)───┐ ├──> 节点执行动态分裂单元(来自动态边)──┘静态输入提供共享上下文(如任务指令),动态输入提供变化的数据。
5. 陷阱与对策
| 陷阱 | 表现 | 对策 |
|---|---|---|
| 分裂数量爆炸 | 正则匹配到数百个子项,资源耗尽 | max_parallel 限流 |
| 正则不匹配 | 输入格式不符,分裂结果为空 | 配置 on_no_match 策略 |
| 实例间状态泄漏 | 共享上下文导致数据污染 | 每个实例独立的 ExecutionContext |
| 错误传播 | 一个实例失败导致整个图挂起 | 实例级 try-catch + 错误结果标记 |
| 结果顺序不确定 | 并发执行导致结果顺序随机 | 使用有序收集或下游排序 |
| Token 消耗倍增 | N 个实例 × N 次 LLM 调用 | 预算控制 + 实例数告警 |
6. 设计权衡
动态分裂 vs 预定义并行
| 维度 | 动态分裂 | 预定义并行 |
|---|---|---|
| 灵活性 | 运行时决定数量 | 配置时固定 |
| 可预测性 | 低(数量不确定) | 高(固定 N 个) |
| 调试难度 | 高(实例 ID 动态生成) | 低(固定节点名) |
| YAML 复杂度 | 低(一条边配置) | 高(N 个节点定义) |
| LLM 可生成 | 是(输出 Query 即可) | 否(需修改 YAML 结构) |
适用场景判断:
- 任务数量运行时才能确定 → 动态分裂(如搜索查询、文件列表)
- 任务数量固定且已知 → 预定义并行(如 3 个评审 Agent)
Map vs Tree
- 一级分裂足够 → Map(简单、高效)
- 需要递归分解 → Tree(灵活但复杂)