
字节笔记本
2026年10月6日 · 约 6 分钟读完
DeepSeek Harness 子代理子系统设计解析
在 DeepSeek Harness 里,子代理(subagent)是主 agent 可以取用的一种可选能力:它和 bash 执行器一样不在 agent 主循环之内,而是以接缝(seam)的形式挂在外面,主 agent 把一块相对独立的工作交给子 agent 去跑,拿到结果再继续自己的推理。这个接缝在所有能力接缝里相当特别:bash 全局只允许一个执行器,子代理却允许多个提供者实现并存,spawn、fork、acp、codex、claude-code 等传输实现按名字注册,随取随用,注册表的组织方式与 LLM 适配器注册表一脉相承。

两种能力,两种发现方式
提供者支持哪些特性,分两类暴露。启动期特性写在静态能力描述符里,包括结构化输出 schema、委派深度上限、工具过滤和 persona 四个标志;服务在把请求交给提供者之前逐项核对,缺哪个就报类型化错误,绝不接受之后悄悄忽略。这种 fail loud 的取舍让模型拿到的是明确的失败反馈,而不是一次看似成功却缺斤少两的执行。可续接能力走另一套发现方式:它对应提供者上一个可选的准备方法,方法存在即能力存在,类型收窄让这条路在编译期就能查。
一次性委派:从请求到结果
一次性委派是最常用的路径。工具层把模型给出的描述和提示词,加上工具自身配置,组装成启动请求:必填的 parent 带来会话工作目录、谱系与当前委派深度;可选的输出 schema、深度上限、工具过滤和 persona,都必须有对应能力标志背书。取消只有一条通道,就是调用方传入的 signal,它在子代理发布前后语义一致。
委派返回的运行句柄刻意做薄:一个 result Promise 加一个幂等的 dispose。子代理自己失败,比如模型或传输出错、token 打满、拒绝任务,都会带着非 completed 的终止原因正常返回,由工具层映射成 isError 的工具结果;只有接缝无法表达的底层故障才会让 Promise 拒绝。终止原因是可扩展联合类型,已知值有完成、取消、错误、超长与拒绝,消费方遇到未知值一律按失败处理。结构化字段只有请求了输出 schema 并真正满足时才存在,请求本身并不保证拿到。委派深度也有明确记账:会话头里的持久深度与运行时字段取大者,子代理比父加一,冷恢复不允许把深度降回去。
可续接子代理:会话、激活与收件箱
第二条路径面向需要多轮往来的长任务。一个可续接子代理在持久层是一条普通的子会话,在进程内则至多有一个激活,也就是重建出来的子 Agent 的驻留期。激活不是请求也不是结果:它内部可以连续执行多个先进先出的轮次,只要它创建的后代还在运行,它就保持驻留。

续接消息只有 followup 一个入口,路由完全取决于激活状态:正在运行就在同一激活里排队;静默但还有孩子在跑,就唤醒同一激活;彻底结算过,就从持久会话冷恢复一个新激活。冷恢复不经过提供者:管理器直接折叠持久描述符,走通用的恢复入口重建代理,描述符里快照了提供者、模型、persona 与工具过滤,但刻意不快照可以随意扩展的选项对象,上游加字段不会破坏续接。收件箱是唯一队列,每条消息对应一个先进先出的轮次,接受顺序全局唯一可观察,跟进消息不可能改写一个已经在跑的轮次。
停止同样只有一个公开操作。中断在同步鉴权后发出取消并立即返回,不等静默:已领取进当前轮次的工作不会重新排队,未领取的消息保留在收件箱里,下次唤醒按原顺序继续。鉴权要求精确的直系父身份,地址不匹配或调用者不在其活体谱系里都会被拒绝。调用方的取消信号只在消息被收件箱接受之前有效,之后激活归管理器所有,外部既不能转向,也不能顺手销毁。
报告与清算:谁说的话算谁的
子代理可以在自己的轮次里主动向直系父报告进展:安静模式把内容注入父会话而不产生父轮次,唤醒模式则作为普通消息排队。运行时自己另有一本账:每当一个激活结算,管理器都会给孩子的直系父发一条结算通知,交代这一代怎么结束、最后说了什么。通知的消息来源类型与孩子的主动报告刻意分开,会话回放时永远不会把运行时的话记到孩子头上。所有权用集合记账:已拥有子代理集合非空,父代理自己就不允许结算;释放严格子代理优先,持久会话则在进程退出后继续存活。
不拉起 agent 的持久枚举
外围工具要回答现在有哪些孩子时,listChildren 与 listDescendants 不加载也不恢复任何 Agent:它们把 live 会话存储与可选持久层合并,用注册好的投影单元折叠每个孩子的持久描述符,得到模式、标签与活跃状态。身份解析走三级梯子:活孩子直接读注册表的水印缓存;冷孩子先查投影检查点缓存;都没有,就做一次持久层检查再折叠。描述符损坏的孩子给出 corrupt 诊断,检查失败给出可重试的 unavailable 诊断,一个坏兄弟不会把健康孩子藏起来。模型侧的 list_agents 适配器只保留可续接条目,并把状态细化为 running、idle、ready 自己的词表,ready 表示存储里还有一条可以冷恢复的孩子,而不是终态。
小结
把一次性委派做成可替换的提供者注册表,把长任务做成会话加激活的双层结构,再用收件箱把所有轮次排序收拢,这个子代理接缝展示了同一能力的两种形态如何分工:前者换来灵活接入,后者换来跨进程的可持续对话。对正在设计多 agent 系统的人来说,能力协商先行、失败必须留痕、排序只认一条队列、运行时与子代理的发言分开记账,都是可以直接搬走的经验。



