背景:扇出是 2026 年 Agent 编排的默认姿势
多智能体 / sub-agent 编排已经从研究论文走进了工程基线:2026 年 Tokenomics(arxiv 2601.14470)用 30 个 ChatDev 任务实测,发现 59.4% 的 token 烧在迭代 review 阶段而非首次生成;Anthropic 工程团队也公开过「multi-agent 比 chat 多用约 15× token」。与之并行的另一面是「顺序工具调用」的延迟痛点——单步 ReAct 循环里,5 步工具串行就是 5 倍等待;多篇 2026 报告把工具串行点名为 Agent 延迟的头号瓶颈。于是工程团队普遍走向同一种妥协:把独立子任务扇出(fan-out)给 N 个子 Agent,让延迟逼近 1 拍。
但「扇出」这条捷径的代价,社区里讲得不够直白。
解剖:扇出到底复制了什么
一个 orchestrator 把任务切给 N 个子 Agent 时,每个子 Agent 都会拿到一份完整的共享上下文——system prompt、任务背景、全部工具的 JSON Schema。orchestrator 不是只把「这个子任务」递过去,而是把整本说明书复印一份再递。我把一份真实可用的共享 prompt(系统准则 + 任务背景 + 8 个工具的 JSON Schema)喂给 tiktoken 的 cl100k_base,实测 853 token。这 853 不会因为子任务变小而缩水,它是随每一次请求整包注入的。
图1:6 个子 Agent 各自带一份 853 token 的共享上下文,光这一项就多烧 5×853 = 4,265 token;N 越大,复制税线性增长。
实证一:并行把延迟砍到三成,但 N=1 时反而慢近一倍
延迟是扇出最直观的收益。我用 Node 起一个子进程当「子 Agent」(setTimeout 80ms 模拟一次 I/O 工具调用),跑了 20 次取中位,对比三种编排:
# bench_agent.js:每配置 20 次取中位(performance.now()) # serial = 一个一个 spawn 再 await # parallel = 全部 spawn 一起 await # inline = 当前进程 setTimeout,不开子进程| N | serial | parallel | inline | 并行 vs 串行 | 并行 vs 内联 |
|---|---|---|---|---|---|
| 1 | 155 ms | 171 ms | 93 ms | 0.91× | 1.83× |
| 2 | 341 ms | 202 ms | 186 ms | 1.69× | 1.09× |
| 4 | 682 ms | 279 ms | 372 ms | 2.44× | 0.75× |
| 8 | 1 255 ms | 373 ms | 743 ms | 3.37× | 0.50× |
| 16 | 2 693 ms | 760 ms | 1490 ms | 3.54× | 0.51× |
图2:并行 vs 串行子 Agent 在 N=16 达到 3.54×;但 N=1 时并行 171ms 反而比内联 93ms 慢近一倍。
两个发现值得贴墙上:第一,并行对串行子 Agent 的优势随 N 增长到 3.5× 左右收敛,N≥8 后基本吃满;第二,并行对「不开子进程、内联做完」的 baseline 有一个临界 N ≈ 3~4:N=1 时每个 Node 子进程冷启动要 ~80ms,把并行收益吃光;N=2 时并行只比内联慢 9%;N=4 之后并行才稳定反超内联(279ms vs 372ms,0.75×)。
实证二:上下文被复制 N 份,token 账单线性膨胀
延迟账算完,再看 token 账。我把上面 853 token 的共享上下文代入一个简单模型:每个子 Agent 还会带自己的私有任务上下文(这里假设 1,200 tok,可按你的真实情况替换),那么:
// token_model.cjs(节选) const shared = 853; // 共享 prompt + 工具 schema,tiktoken 实测 const work = 1200; // 每子任务私有 ctx(假设,按你的任务替换) const subTotal = N * (shared + work); // N 个子 Agent 总 token const singleTotal = shared + N * work; // 单 Agent 串行做同一件事| N | N 子 Agent 总 | 单 Agent 总 | 复制税(多烧) | 倍数 |
|---|---|---|---|---|
| 4 | 8,212 | 5,653 | +2,559 tok | 1.45× |
| 8 | 16,424 | 10,453 | +5,971 tok | 1.57× |
| 12 | 24,636 | 15,253 | +9,383 tok | 1.62× |
| 16 | 32,848 | 20,053 | +12,795 tok | 1.64× |
图3:仅「共享上下文被复制」一项,N=16 就多烧 12,795 token;账单是单 Agent 的 1.64 倍。
倍数收敛在 1.6× 附近,看上去没传说中那么夸张——但绝对值是真实的:N=16 时,光复制就多花了近 13k token 才开始干活。生产系统里 853 这个数往往偏小:把工具集扩到 30+ 个、加上 RAG 检索结果与长 system prompt,shared 跑到 3k~8k 很常见,届时 N=16 的复制税是5万–13万 token 起步。这还只是「上下文复制」一项,没算 orchestrator 复读所有子 Agent 输出的监管开销、跨轮重新注入、失败重试的级联——也就是 2026 年研究里 2.9×–15× 倍数差的主要来源。
局限:并行不是免费的,生产里还有更狠的叠加项
把这条经验搬上线前,请先校准三件事:
- 子任务真独立吗?后一步依赖前一步结果的依赖链,并行发出去也会被串行化重排。生产里更糟的是「假独立」——模型以为独立并发了 N 个调用,实际有数据依赖,结果要么白烧 token 重发,要么答案错。这也是为什么实测里「开启 parallel 后 p50 只省 18% 而不是 60%」的案例不少。
- 临界 N 别忽略。N=1~2 时,子进程的冷启动 + IPC 会把并行收益吃光——这种小任务宁愿让单 Agent 顺序做完。
- orchestrator 自己的账别忘了。监管型 orchestrator 要把所有子 Agent 输出读一遍才能往下走,它的输入随 N 增长;这部分 supervision 开销在我的静态模型里没有,但生产里是实打实的二次放大器。缓解手段:prompt cache 共享、子 Agent 只接收「自己需要的」上下文子集、给每个子 Agent 设硬性 token 上限。
结论:先算两笔账再决定要不要扇出
工程上可复用的方法论只有一句:任何想扇出的任务,先并行算「能省多少 round-trip」再除以 N 算「共享上下文被复制几份」,两者同时划算才拆。我这张双账本图(延迟 vs token)以后会直接进我们做 Agent 架构评审的 checklist——左轴决定用户体验,右轴决定账单。两个都赢才值得拆,两个只赢一个就别拆。
开源地址(结论段,指向同一组织即可,3 个):
- 矩阵门户:GitHub - wangzifan396-wzf/WB: nano-tools: 1200+ single-file, zero-dependency, local-first web utilities in one portal. Offline and private, nothing leaves your browser. Binary & protocol parsers, crypto, dev, audio, visualization, productivity. · GitHub
- 单文件工具聚合器:GitHub - wangzifan396-wzf/nano-workbench: Single-file tabbed launcher for the nano-tools matrix - one tab, 382 curated tools (of 1228), instant switching. Zero-dep. Part of nano-tools. · GitHub
- GitHub 组织主页:wangzifan396-wzf (WangZi) · GitHub