跳转到内容

动态 Agent 执行:Map/Tree 运行时分裂

动态 Agent 执行:Map/Tree 运行时分裂

学习目标

读完本章后,你将能够:

  • 理解动态 Agent 分裂模式的设计动机与适用场景
  • 掌握 Map 和 Tree 两种分裂模式的区别与实现
  • 设计安全的分裂策略(正则 / JSONPath)与并发控制
  • 分析动态分裂与预定义并行的权衡

1. 概念定义

1.1 什么是动态分裂

动态 Agent 执行 指在图运行过程中,根据流经边的消息内容,将目标 Agent 节点在运行时分裂为多个并行实例,每个实例处理消息的一个子单元。

这与预定义并行(在 YAML 中写死多个并行节点)的本质区别在于:并行数量由运行时数据决定,而非配置时决定

1.2 行业背景

动态并行是 2025-2026 年多 Agent 编排的核心模式之一:

框架动态并行能力
LangGraphSend API 支持运行时动态扇出
Mastra.map() 控制流操作符
AWS Bedrock AgentCore线程池 + 异步 I/O 并行调用
AgentSpawn自适应 Agent 分裂与记忆转移
Claude Code动态工作流可生成数百个并行子 Agent

2. Map 模式

2.1 执行流程

2.2 分裂策略

策略描述适用场景风险
Regex Split正则匹配提取子串自由格式文本正则不匹配时行为不确定
JSONPath SplitJSON 路径查询结构化 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 的区别

维度MapTree
分裂层级一级多级递归
结果处理扁平化递归归约
复杂度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(灵活但复杂)

7. 参考来源