1502 字
约 5 分钟
9
子代理Spawn与Fork
2026-10-13
无标签
子代理:Spawn 与 Fork 的派遣艺术
系列:ToyAgent 智能体知识库 13/26
一句话核心:主代理不必亲自做所有事——把子任务派给带独立上下文的子代理。spawn 全新出发,fork 继承当前对话。
为什么需要
一个代理的上下文窗口装不下所有领域知识,也装不下所有任务。子代理 = 带独立上下文的分身:主代理只派任务、收结论,中间的检索、试错、长文本全部发生在子代理自己的上下文里,不污染主会话。
与流水线多智能体(12 篇)的区别要分清:12 篇是固定流水线——规划→研究→写作→审查的角色编排写死在代码里,谁来干什么是人决定的;本篇是主代理动态派遣——模型自己决定派谁、派几个、怎么派,这正是 Claude Code 的 Task 工具的实现原理。
核心机制:spawn 与 fork
派遣有两种模式,差异全在上下文:
| 维度 | spawn | fork |
|---|---|---|
| 上下文 | 全新:只有职责提示词 | 复制父会话再出发 |
| 适合 | 无状态专项任务(调研、翻译) | "接着当前话题继续做" |
| 记忆 | 什么都不知道 | 知道对话里出现过的一切 |
// dispatch_subagent:fork 模式下,子代理的 system 里拼上父会话记录
StringBuilder sys = new StringBuilder("【子代理身份】").append(spec.specialty());
if (fork) {
sys.append("\n【继承的父会话上下文】\n")
.append(String.join("\n", parentTranscript));
} else {
sys.append("\n(spawn 模式:全新实例)");
}
List<Message> childMessages = new ArrayList<>();
childMessages.add(Message.system(sys.toString()));
childMessages.add(Message.user(task));
String report = model.chat(childMessages); // 子代理独立一轮,与主会话隔离
// report 回填主会话 —— 主代理只看到结论,看不到子代理的中间过程
实现上就是三件事:拼 system(职责 + 可选的父会话继承)、独立调一轮模型、结论回填主会话。没有进程,没有线程,"独立上下文"只是另一份消息列表。
spawn 与 fork 的上下文差异对比:
graph TD
P["主代理:持有完整父会话历史"]
P -->|spawn| S["子代理 system = 仅职责提示词"]
P -->|fork| F["子代理 system = 职责 + 继承父会话记录"]
S -->|"输出:通用结论 不知对话偏好"| B["结论回填主会话"]
F -->|"输出:延续上下文 记得偏好"| B
图示:两条派遣路径的差异只在子代理 system 的初始内容——spawn 一张白纸,fork 带走父会话全部历史,但中间过程都不污染主会话。
举例
模拟对话轨迹——一个实验就能体会 spawn 与 fork 的全部差异:
用户:记住:我最喜欢紫色
主代理:(写入当前会话历史)
用户:fork 一个子代理,让它写一句贺词
主代理 → dispatch_subagent(fork=true, task="写一句贺词")
子代理 system =
【子代理身份】贺词撰写
【继承的父会话上下文】
用户:记住:我最喜欢紫色 ……
子代理输出:「祝紫气东来,前程似锦!」 ← 带紫色
用户:再 spawn 一个子代理写贺词
主代理 → dispatch_subagent(fork=false, task="写一句贺词")
子代理 system = 【子代理身份】贺词撰写(全新实例)
子代理输出:「祝一切顺利,心想事成!」 ← 通用,不知紫色
用户:对比两次贺词
差异即 spawn 与 fork 的差异:fork 记得对话,spawn 一张白纸。
选型直觉:任务里出现"它/刚才/上面说的"这类指代,或者需要沿用用户已给的偏好 → fork;任务是自包含的("调研 X 主题"、"把这段翻译成英文")→ spawn,还省掉了灌父会话的 token。
生产视角(SubAgent 编排):子代理按角色定义注册——调研员、审查员、执行者,各挂自己的工具白名单与模型档位(便宜模型跑调研,强模型跑终稿)。Claude Code 的 Task 工具、各类编排框架的 subagent 机制,同一套原理。
面试考点
- spawn 与 fork 的本质区别? 上下文的初始状态:spawn 只带职责提示词(无状态),fork 把父会话记录拼进子代理 system(有记忆)。选错的代价:该记的没记(spawn 误用于延续性任务),或该隔离的没隔离(fork 把无关历史灌进去浪费 token)。
- 子代理解决什么单代理做不了的问题? 上下文隔离与并行。子代理的海量中间过程不占主会话窗口,多个子代理可并行跑互不干扰,主代理只消费结论。
- 子代理和流水线多 Agent 的边界? 编排决策权在谁手里:写死在代码里的角色链是流水线;模型运行时通过工具调用决定派谁派几个,是子代理派遣。
生产化路径
- 深度限制:禁止/限制子代理再生子代理(派遣深度 ≤1 或 ≤2),防止递归派遣指数爆炸。
- 结构化回传:子代理结论做 Schema 校验(如必须含
summary/findings/sources字段),不合格触发一次重派,防止半截报告污染主会话。 - 工具集隔离:每个子代理角色挂白名单工具——审查型子代理只读不写,调研型子代理不接生产写接口。
- 模型档位分级:子代理默认用便宜快模型,主代理握强模型;fork 场景注意继承的长会话可能超出便宜模型的窗口,需截断策略。
- 注册表化复用:子代理角色定义进注册表(名称/职责/工具/模型档位),按名称派遣、可热更新,而不是每次硬编码 specialist prompt。
评论
0 条
还没有评论,先写一条吧。