第 6 章 编排与子智能体¶
单个循环能处理的任务长度有限:上下文会满、步骤会纠缠、并行无从谈起。编排把一个大任务拆成若干可独立执行与验收的子任务,交给子智能体或工作流阶段处理,再回收结果。拆得好是并行与隔离,拆得不好只是把一次失败变成多次失败。本章给出分解、委派、并行、回收与终止的判据。
1. 分解的判据¶
拆分不是越细越好。可拆的子任务要同时满足三条:能独立验收(有明确判据)、上下文可隔离(不需要全史)、执行可独立(不依赖其他子任务的实时状态)。三条缺一,拆分只会增加协调成本。
粒度用两个量约束:子任务的步数不超过单轮步数上限的三分之一,子任务单独执行时的上下文占用不超过窗口的一半。低于这个粒度,委派信封、上下文重建与结果汇总的开销会超过并行收益;高于这个粒度,子任务本身又会遇到父级同样的上下文压力。拆完后的总 token 消耗应当下降而不是上升——上升说明拆的是“活”,不是“上下文”。
反模式是"按工具包一层智能体":每个工具配一个子智能体,看似模块化,实际每个子智能体都要重新理解任务,协调成本高于收益。判据仍是控制流:子任务内部的步骤是否需要模型临场决定;不需要的,用工作流阶段即可。
2. 委派与上下文隔离¶
子智能体不应继承父级的全部历史。全史委派会把父级的噪声、已否掉的路径、无关的观测一起带过去,既占额度又误导判断。可行做法是给一个结构化信封:目标、约束、输入位置、验收标准、返回格式。
def envelope(goal, constraints, inputs, accept, fmt="结论 + 证据引用"):
return {
"goal": goal, # 这一个子任务要达成什么
"constraints": constraints, # 权限、范围、不得触碰的资源
"inputs": inputs, # 文件路径或查询,不复制大段内容
"accept": accept, # 什么算完成,由谁判定
"return": fmt, # 回传形状,便于父级汇总
}
inputs 给引用而非内容,是隔离的关键:子智能体按需读取,读多少由它自己按任务决定。accept 必须写在信封里,否则子智能体会以"自己觉得做完了"为完成标准。
信封是协议而不是建议:缺 goal 或 accept 的委派直接拒收;constraints 里必须显式列出禁止项(可写路径、可用工具、不得读取的凭据),未列出的按禁止处理。return 还要带上限——行数、字节数或 token 预算,超出时子智能体先截断并附获取完整结果的引用,否则一次子任务就能把父级上下文灌满。子智能体不得反向读取父级会话历史,需要的信息必须经信封下发;这条限制保证委派可重放,也让父级的历史压缩不会影响已派出的任务。
3. 并行与依赖图¶
并行收益来自无依赖的子任务。依赖关系要显式成图:谁读谁写、谁必须先完成、哪些资源互斥。无依赖的读操作可并行;写同一资源的操作必须串行或加锁;有数据依赖的操作按拓扑序执行。
图上的边分两类:数据边(B 要读 A 的产出)与资源边(两者写同一路径或占同一设备)。资源边容易被漏掉——两个子任务写不同文件但共享同一个构建目录、同一个串口,仍会互相破坏。调度按拓扑分层,同层内并行,层数就是关键路径长度;关键路径上的子任务优先分配预算。取消与超时要沿边传播:一个阶段失败,下游节点直接标记为阻断,不再启动。
部分失败策略要预先确定:全有或全无(任一失败则回滚或放弃)适合一致性要求高的任务;尽力而为(保留成功部分,汇总失败)适合可分解的收集类任务。两种策略不能混用在同一批并行任务里,否则汇总时无法判断整体状态。
4. 共享状态与隔离副本¶
并行执行的最大风险是共享状态冲突:两个子智能体改同一个文件、抢同一个设备、写同一张表。三种对策按成本排列:资源锁(简单但降低并行度)、乐观并发(版本号检测冲突后重试)、隔离副本(各自在独立工作树或容器里改,最后合并)。
锁要带租约与获取顺序:租约到期自动释放,避免崩溃后永久占用;所有参与者按同一全局顺序申请多把锁,否则两个子任务各持一把、互相等待就成死锁。乐观并发适合读多写少:提交时比对版本号,冲突则重放该子任务——前提是子任务的副作用可重做。
隔离副本的代价在合并:文本冲突可三方合并,二进制与结构文件往往只能人工裁决。判据是冲突概率与合并成本:冲突少且可自动合并时用副本,冲突多时串行更省事。
副本合并要有基线:每个副本记录分叉时的 commit 或文件哈希,合并时以基线做三方比较,而不是拿两份终稿硬拼。按所有权分区比逐行合并更稳:给每个子任务划分互不重叠的文件或目录,合并退化为拷贝,冲突概率归零。二进制资产(模型、图片、日志)不进自动合并,只允许"整体采用某一副本"。
5. 结果回收与二次验证¶
子智能体的结论是"主张",不是"事实"。回收时要区分三类返回:结论(做了什么、结论是什么)、证据(命令、输出、文件位置)、未决(没做完、不确定、需要什么)。只回结论不回证据,父级无法验证;只回证据不回结论,父级要重新推理一遍。
证据按强度分档:可重放的命令与其退出码最强,其次是产物哈希与测试报告,最弱是子智能体的自述。回收时父级只接受前两档作为验收依据;自述只能用于定位下一步。二次验证的代价要与任务价值匹配——低风险子任务抽检,高风险与不可逆子任务全检。
二次验证按任务类型选:代码类跑测试或类型检查,数据类做 schema 与守恒校验,机器人任务回仿真或读回状态。验证失败时,把失败证据回给子智能体重做,而不是父级直接改——父级缺少子任务的上下文,直接改容易引入新错误。
6. 编排形态¶
三种常见形态:主管(supervisor)负责分解、委派与汇总;流水线(pipeline)按阶段串行,每阶段有独立验收;群(swarm)是同质执行者并行处理分片,再由聚合器汇总。形态选择取决于任务结构,而不是流行度。
主管的瓶颈在汇总:子结果回到父级时要先压成摘要再进上下文,否则并行省下的时间会被父级重新阅读结果抵消。流水线要有阶段契约:每阶段的输入输出形状固定,下游不读上游的原始轨迹。群的聚合规则必须可执行——按 key 去重、按优先级取优、或两两比较,聚合本身不应再调一次模型做"综合判断",否则分片的并行收益在最后一步归零。
判据:协调开销必须小于并行或隔离带来的收益。主管适合子任务异构、需要动态调整;流水线适合阶段边界清晰、每阶段可单独验收;群适合同质分片、聚合规则简单。混合形态常见:外层流水线,某一阶段内部用主管。
7. 终止:递归、死循环与预算¶
编排会引入三类新的不终止方式:递归委派(子智能体再委派,深度失控)、重复动作(同一调用反复出现,没有进展)、预算分摊失败(每个子任务都"还差一点",总预算被耗尽)。
对应三条约束:委派深度上限、重复动作检测(同一工具同一参数连续出现即判定无进展)、预算按子任务预分且父级保留兜底额度。子任务的预算不应由子任务自己申请,否则每个子任务都有动机多要。深度上限按层数计(常用两层,最多三层),超过即拒绝再委派;重复检测看窗口内的调用指纹,连续三次相同即中止;父级兜底额度按总预算的两成预留,只用于收尾与验证,不再发新委派。
8. 检查点与断点续跑¶
长任务的恢复能力取决于状态是否外置。检查点至少要存四样:已完成子任务及其证据、待执行子任务、当前资源状态(改了哪些文件、占了哪些设备)、预算余额。恢复时按检查点重建上下文,而不是重放全部历史。
检查点写在子任务边界,不写在子任务内部——边界外的状态才可原子提交。恢复时先核对资源状态:工作树是否仍在该 commit、设备是否仍被占用、临时文件是否还在;不一致的项要么重做、要么标记为人工处理。已完成子任务的重放必须幂等,靠 task_id 去重,否则续跑会把已生效的写入再做一遍。
检查点要带版本:任务结构变化后,旧检查点可能不再适用。恢复前校验版本与资源状态,不匹配时选择重做受影响部分,而不是盲目续跑。写入也要可原子替换:先写临时文件再重命名,否则中断落在写中途就会得到一个半截状态的检查点。
9. 要点¶
- 可拆的子任务要能独立验收、上下文可隔离、执行可独立,三条缺一不拆。
- 委派用结构化信封:目标、约束、输入引用、验收标准、返回格式。
- 依赖显式成图;无依赖读并行,同资源写串行;部分失败策略预先定死。
- 共享状态用锁、乐观并发或隔离副本;副本的代价在合并。
- 子结果是主张不是事实;回收要带证据,并按任务类型二次验证。
- 编排形态按任务结构选,协调开销必须小于收益。
- 递归深度、重复动作、预算分摊三处设硬约束。
- 检查点存已完成、待执行、资源状态与预算余额,并带版本校验。