批量与并行交给代码编排
模型负责理解与判断,循环、过滤、重试、批量和并行由程序完成;同构批量任务的模型往返次数应接近 1 而不是 N。
模型负责理解、判断、规划和生成编排逻辑;循环、过滤、重试、缓存、分页和批量执行交给程序。这不是分工偏好,是算术:逐个发起 LLM 往返时,延迟、token 消耗和跑偏概率都随 N 线性放大,N 次往返应当压缩成 1 次。
把不确定性留给模型,把确定性交给程序
典型场景是搜索后读取前 N 个文件、对 N 条记录逐条执行同构工具调用。让模型发起第一步、等结果、再决定第二步,等于把同一段上下文付 N 次钱,还给了它 N 次跑偏的机会。
判据很硬:同构批量任务的模型往返次数应接近 1,而不是 N。模型产出的应该是编排逻辑——选一个编排模板,或者生成一段编排代码——真正跑循环的是你的程序:search、read、filter、batch、retry 全在代码里完成,最后一次性把结果报给模型。
什么时候可以并行
五条同时成立才并行:输入已确定、没有前后数据依赖、没有共享可变写入、输出落在独立命名空间、失败可以独立处理。任何一条不满足就串行,或者先消除依赖。
所以第一步是构建调用依赖图,把没有依赖关系的 Connector、工具、子运行和测试任务批量并行。依赖图不是可选的优化项,它是你判断「这两件事能不能同时跑」的唯一依据,也是下一步设并发上限的输入。
并发上限按资源分别设
并行不等于无限并发。模型、外部 API、浏览器、数据库、CI 各有各的容量,必须分别设上限。这类线上事故多数不是并行逻辑写错了,而是并发把下游打挂了。
还有一条容易违反:不能为了并行化重复获取相同上下文。五个并行分支各自读一遍同一个文件,省下的时间又还回去了,还多付五倍 token。共享上下文要提前取好,作为输入分发下去。
编排执行要进 Trace
编排跑在代码里,但它不能是黑箱。执行过程要进 Trace,支持回放和审计——一次批量任务改了两百个文件,事后你必须能回答「第 137 个文件是谁、依据什么改的」。
淘天塔罗平台对这个边界的处理值得照抄:文件改动、命令、Mock、截图、Diff、测试结果作为可复查事实写进执行账本;方案理由和剩余风险作为判断走 Comment 和 Handoff,并且明确 Handoff 只能当线索、不能当事实。编排层产出的是证据,模型产出的是判断,两者不能混在一个字段里。taotian-loop
模型生成编排代码时,按沙箱执行
优先提供编排模板或 SDK,让模型选模板、填参数。如果允许模型自由生成编排代码,就按沙箱执行并施加权限约束:文件系统范围、网络出口、可调用工具的白名单。模型写出来的循环和它写出来的命令一样,都可能删掉它不该删的东西。
Anthropic 在长跑 agent 上有个相关教训:用 while true 循环让 Claude 永续工作,有一次 Claude 执行了 pkill -9 bash,把自己杀了,循环直接结束。这类副作用是长跑系统的固有风险,容器隔离和权限边界只降低概率,不消除它——真正兜底的是测试和 CI 守住质量边界。anthropic-c-compiler
代价与自检
代价是编排层本身要建设和维护:依赖图、并发控制、Trace 回放、沙箱。任务异构、每一步都需要模型重新判断的场景,硬套编排反而更慢。
三个问题可以自查:你的批量任务里,模型往返次数接近 1 还是接近 N?并行的分支之间有没有共享可变写入?一次批量执行失败后,你能回放出来它是怎么失败的吗?
