任务分片:上下文隔离的代价
它读了第一个的文档,做了笔记;读第二个,又做了笔记;读第三个的时候,它开始重复第一个库里的结论——不是记错了,是前面那部分已经被挤出窗口了。
任务分片:上下文隔离的代价
我让它比较三个库,选一个能用的。
它读了第一个的文档,做了笔记;读第二个,又做了笔记;读第三个的时候,它开始重复第一个库里的结论——不是记错了,是前面那部分已经被挤出窗口了。
任务本身不难,难在中间过程太长。
一、装不下的不是任务,是过程
一个人做这件事,笔记本上留三行结论就够了,中间读过的每一页都可以忘。
模型不行。它没有”笔记本”,只有一份每轮重发的对话记录。读过的每一页都在里面,而且是全文。三个库的文档读完,窗口里塞满的是过程,结论反而没地方放。
所以分片要解决的不是”任务太大”,是中间产物太占地方。真正需要的输出可能只有五百字,为了得到它,上下文里堆了几万字。
二、子 Agent 是上下文隔离,不是并行
常见的误解是把多 Agent 理解成”多叫几个 AI 一起干”。
真实机制要朴素得多:主会话调用一个工具,把任务描述交给它;子 Agent 在自己的会话里跑一个完整的循环——有自己的历史、自己的工具调用、自己的上下文预算;跑完之后,只把结果交回来。
flowchart TD
M[主会话<br/>上下文 A] -->|任务描述| S[子会话<br/>上下文 B]
S --> T1[读文档]
T1 --> T2[跑测试]
T2 --> T3[写结论]
T3 -->|只回传结论| M
T1 -.不进主线.-> X[丢弃]
T2 -.不进主线.-> X
关键在那两条虚线。子会话里读过的每一个文件、跑过的每一条命令,都不会进入主会话的上下文。主线只多了一条消息:任务完成了,结果是这个。
这不是并行计算,是内存分页。把一大块中间状态放到另一个地址空间,用完只带一个返回值回来。
三、回传什么,决定了隔离是否成立
如果子 Agent 把全过程都交回来,隔离就白做了。
所以回传的内容是被裁剪过的。以 Minis 的实现为例,一次子任务结束后保留的摘要包括:调用过哪些工具(一行一个,带标题)、跑了多少轮、进出各多少 token、以及它最新写出的一段文本。
注意最后一项的措辞:最新的一段文本,不是全部输出。子 Agent 中间写过的草稿、失败的尝试、被推翻的方案,都不回传。
这个取舍有个副作用:主模型看不到子 Agent 是怎么得出这个结论的。它只能选择信,或者再派一次任务去验证。信任成本是隔离的必然代价。
四、花名册本身也要占地方
还有一个容易忽略的成本:子 Agent 的存在本身要写进主会话的系统提示。
每个可委派的子 Agent 都要有一份说明:叫什么、能干什么。这份说明每一轮都要发给模型,否则它不知道可以委派给谁。
所以这不是”想加多少加多少”的功能。实现里给了硬上限:最多 10 个,名字 40 字符,描述 200 字符。算下来大约 800 token 的固定开销,每轮都付。
源码注释里把这个逻辑说得很清楚:这些数字不是防呆,而是因为花名册每轮都注入,数量和描述长度就是每请求的固定成本;把输入限死,就不需要在运行时再弹一个 token 超标的警告。
这条经验可以推广:任何常驻上下文的东西,都要有硬上限。工具描述、系统提示、记忆条目、子 Agent 花名册,全是同一类东西。靠”提醒用户别写太长”解决不了,只能靠结构上限。
五、代价:它不知道你知道什么
分片之后,最常出的问题不是能力不够,是信息不对称。
子 Agent 看不到主会话的历史。你跟主模型说过”我们用 Kotlin,不用 Java”,这句话不会自动传给子 Agent。它拿到的是你写的那段任务描述,仅此而已。
所以委派的质量,几乎完全取决于任务描述的质量:
| 写法 | 结果 |
|---|---|
| “看看这三个库哪个好” | 它按自己的标准选,可能完全不符合你的约束 |
| “在 Kotlin/Android 项目里比较 A、B、C,重点看启动耗时和包体积,给出结论和理由” | 大概率可用 |
这也是为什么很多 Agent 框架强调”交接文档”:不是流程需要,是上下文不共享,只能靠文字传递。
六、分叉是另一种隔离
除了委派,还有一种更轻的分片:分叉。
从当前会话的某个点分出一个新会话,它继承此前的全部历史,然后独立生长。主线不受影响,分支可以随便试。
两种隔离的区别很实在:
| 委派子 Agent | 会话分叉 | |
|---|---|---|
| 继承历史 | 不继承,只给任务描述 | 继承到分叉点 |
| 回传内容 | 只有结论 | 完整对话 |
| 适合 | 独立、边界清楚的任务 | 探索性、需要前文的工作 |
| 成本 | 一次额外上下文 | 一份完整副本 |
委派是”派一个人去办事”,分叉是”我先去另一条时间线试试”。前者省上下文,后者省解释成本。
七、什么时候不该拆
分片不是免费的。多一个 Agent,就多一次模型调用、多一份上下文、多一层信息损耗。
有三种情况不值得拆:
任务能用一段话描述清楚,但做起来只要两三步。 拆出去的开销比直接做还大。
子任务之间需要频繁交换中间结果。 隔离了就没法交换,只能来回传话,越传越失真。
结论依赖大量隐含前提。 你脑子里那些”不用说的常识”,子 Agent 一条都不知道。
反过来,判断该不该拆有个简单标准:这个子任务能不能用一段话完整描述,并且不需要看主线历史就能干。能,就适合派出去;不能,就留在主线里。
小结
多 Agent 不是架构上的炫耀,是上下文预算逼出来的分页策略。
它用”看不见过程”换”装得下任务”,用”信任成本”换”窗口空间”。这笔交易划不划算,取决于任务本身能不能被切干净。
下一篇把这套机制放到边界上:看它会以哪些方式失效。