DeepSeek Harness 子代理服务整合:单一 SubagentRuntime 如何统一一次性运行、可续接子代理与后续消息投递 人工智能AI AgentAgent 框架DeepSeek【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址https://gitcode.com/gh_mirrors/de/deepseek-harness点击查看免费下载本篇文章围绕 DeepSeek Harnessdeepseek-harness仓库在packages/subagent目录下的子代理能力缝capability seam展开核心讲解此前独立的ctx.subagentControl编排服务与ctx.subagents提供者契约合并为单一公共服务SubagentRuntime的架构决策、公开 API 契约、错误体系、内部续接管理器实现以及面向模型的send_message/interrupt_agent适配器与backgroundMode配置语义。读完本文你将理解为什么子代理系统只需要一个公共服务键如何在部署中配置一次性与可续接两种后台运行策略以及续接子代理的持久化、授权、取消与销毁语义在源码中的实际落点。一、背景为什么把控制服务并回子代理服务在合并之前DeepSeek Harness 将可续接子代理continuable child的编排逻辑放在独立的ctx.subagentControl服务中它位于底层ctx.subagents提供者契约之上。这种拆分当时有三个动机让提供者分发与 Jobs、持久化解耦为模型适配器与人类适配器提供统一的编排契约把启停续接从底层提供者调用中抽象出来。但在实际使用中出现了结构性问题详见 docs/subsystems/subagent.md 中的记录两个服务描述的是同一族能力所有使用可续接子代理的调用方必须同时依赖两个服务公共 API 多了一个键暴露了调用方并不需要的架构区分提供者绑定型委托工具需要猜策略tool-subagent这类工具只能从provider.resume推断续接策略还要检查控制服务和send_message工具是否恰好被加载——同级插件的存在与否决定了执行语义可选后续面耦合了启动把启动持久化工作与是否存在一个可选的后续投递工具绑定是不必要的耦合。因此合并后的架构收敛为SubagentRuntime是唯一的公共服务deepseek-ai/dsh-subagent-control独立包和ctx.subagentControl键被移除续接实现退化为服务内部的私有管理器。二、单一公共服务SubagentRuntime的公开 API合并后的服务在packages/subagent/subagent/src/index.ts中定义export class SubagentRuntime extends TypertRemoteService { // 普通一次性运行 async start(name: string, request: SubagentStartRequest): PromiseSubagentRun // Task 支撑的可续接启动 async startContinuable(spec: ContinuableStartSpec): PromiseContinuableStart // 意图命名intent-named的后续消息投递 async followup(parent: Agent, childId: SessionId, content: ContentBlock[], options: SubagentFollowupOptions): PromiseMessageId // 中断一个存活的续接子代理的当前轮次 interrupt(targetSessionId: SessionId, authority: SubagentInterruptAuthority): void // 子代理向其直接父级报告delivery: quiet | next-step async reportFrom(child: Agent, content: ContentBlock[], options: SubagentReportOptions): PromiseMessageId // 提供者注册/查询/枚举 registerProvider(provider: SubagentProvider): () void getProvider(name: string): SubagentProvider | undefined list(): string[] }服务通过 Cordis 的declare module deepseek-ai/cordis扩展了Context挂载键为ctx.subagents。它还发布四个生命周期事件subagent/provider-added、subagent/provider-removed、subagent/start与subagent/end后者按委托父级做 scope 过滤分发。2.1start普通的一次性委托start(name, request)是经典的前台委托入口按名字解析提供者做能力校验与深度上限校验生成one-shot模式的描述符descriptor然后调用provider.start(resolved)。提供者的 promise 兑现即发布与所有权移交边界——发布前失败不会有 run 可供调用方清理也不会发出生命周期事件见index.ts中start的实现与注释。2.2startContinuable分配持久化子 id 并同步返回startContinuable与start的区别在于所有权与时机契约不同它在ChildLock临界区内预留持久化 child id、创建 Task、同步返回{ childId, messageId }而子代理的实际启动在 Task 内部继续推进只有初始提示被子代理 inbox 接受才算成功此前的任何失败都不带任何 id 拒绝并完整回滚子代理普通start则等待提供者发布并移交一个持有者所有的 run。折叠到单个start用标志位或返回联合类型会拓宽底层契约因此保留了显式的startContinuable入口——这是文档中明确记录的取舍。2.3followup按 FIFO 顺序投递下一条消息followup(parent, childId, content, options)是续接子代理的后续消息投递口常驻resident子代理直接由Agent的 inbox 接收唤醒处于waiting的 Activation不在常驻状态的子代理则从持久化 Session **冷恢复cold resume**为一个新的 ActivationAgentinbox 是唯一队列因此每条被接受的消息只有一种可观察顺序调用方取消AbortSignal只拥有inbox 接受之前这段窗口接受之后续接操作不再可取消。三、统一的错误体系SubagentError合并后服务与提供者共享一套错误类型被移除的subagentControl不再保留独立的错误类。SubagentError继承自deepseek-ai/dsh-llm的HarnessError定义在 error.tsexport class SubagentError extends HarnessError { constructor(message: string, code: string, options?: ErrorOptions) { super(message, code, options) this.name SubagentError } }从源码index.ts、continuation.ts可以归纳出稳定的错误码分类类别错误码code触发场景提供者查找NO_PROVIDER未注册该名字的提供者提供者注册DUPLICATE_PROVIDER同名提供者重复注册能力校验UNSUPPORTED_CAPABILITY请求了提供者不具备的agentOptions/outputSchema/depthLimit/toolFilter/persona能力或续接模式要求prepareContinuable而提供者没有续接可用性CONTINUATION_UNAVAILABLE未加载 agents 服务或 session-query 服务持久化PERSISTENCE_UNAVAILABLE续接操作需要 session 持久化后端而未加载授权UNAUTHORIZED调用方不是目标的精确存活直系父级/祖先、自中断、父级身份过期取消/关闭CANCELLED、DRAINING、ACTIVATION_CLOSING列表读取被取消、管理器或父级树正在排水、Activation 正在销毁续接路由NOT_RESUMABLE、DUPLICATE_CHILD目标无可用续接状态 / 持久化中已存在该 child id投递PARENT_UNAVAILABLE直接父级不在存活状态报告或通知无法投递销毁ACTIVATION_TEARDOWN_FAILEDActivation 销毁期间某一边界失败聚合上报错误码使调用方如浏览器 RPC 层与工具层可以精确区分提供者不存在能力缺失未授权与持久化缺失而不是把一切归结为内部错误。例如远程接口prompt会把UNAUTHORIZED翻译为subagent-unauthorized把NOT_RESUMABLE翻译为subagent-not-resumable。四、续接实现的内部架构管理器而非注册表扩展文档明确决策续接实现保留为内部管理器SubagentContinuationManager见 continuation.ts而不是扩展提供者注册表的核心状态。4.1 依赖注入与生命周期SubagentRuntime在构造函数中通过ctx.inject([agents], ...)创建管理器因此注入的 Cordis 子 fiber 拥有 Task 完成监听器与 teardown 效果ctx.inject([agents], (childCtx: Context) { const manager new SubagentContinuationManager(childCtx, { prepareContinuable: (name, request) this.prepareContinuable(name, request), observeActivation: (provider, childId, parent) this.observeActivation(provider, childId, parent), }, this.setupRegistry) this.continuations manager childCtx.effect(() () { /* 释放时清空槽位 */ }, subagents.continuationBinding()) })这意味着加载提供者注册表不需要 Jobs 或持久化——普通start调用方可以完全脱离续接基础设施工作管理器只在 Jobs 与 Agents 都可用时存在每个续接操作在需要持久性的那一点才解析 session 持久化销毁该 fiber 会先取消并结算所有活跃续接然后才释放它们的所有权关联drain()在释放结构作用域之前注册保证逆序 unwind 时排水先于句柄释放。4.2 Activation一次驻留期 一个存活子代理续接子代理有一个持久化 Session 和至多一个进程内 Activation。关键语义源码注释明确说明Activation 不是请求、结果、取消或 Task 边界它可以执行多个 FIFO 轮次并在其派生的后代仍在运行时保持驻留Agentinbox 是唯一的轮次队列管理器拥有驻留权Agent循环拥有轮次排序与执行权驻留状态由stateOf()从 Agent 静默度与 owned-children 集合推导running有活跃许可/轮次/待唤醒消息、waiting静默但仍有未销毁子代理、settled静默且所有子代已销毁。注意Agent.status单独不足以判断驻留在followup()接受消息与微任务真正准入之间存在idle窗口因此管理器用accepted集合记录已接受但尚未离队的消息 id防止过早判定为 settled。4.3 冷恢复cold resume与授权当对不存在 Activation 的子代理执行followup时管理器走coldResume通过 session-query 观察持久化 Session先按持久化 header 的parentSession校验授权只有持久化子代理的精确存活直系父级才能继续它再折叠fold描述符最后调用ctx.agents.resume()重建 Activation。冷恢复不会经过 subagent 提供者分发——持久化 Session 已包含初始前缀描述符就是完整重建输入。4.4 串行化、结算与销毁ChildLock每个持久化 child id 的操作投递、结算、销毁按提交顺序线性化且单个临界区失败不会拒绝无关的后续调用方结算通知子代理结算后管理器负责向持久化直接父级投递subagent-settled通知如 Background subagent … finished and will do no further work unless you send it more.。这份职责不能交给外部subagent/end监听器该负载不携带父级信息且此时子代理句柄已被销毁销毁顺序取消信号自顶向下传播cancel({ kind: parent })但句柄释放保持子优先child-first每个后代完成销毁后祖先才移除句柄最终 session flush 是尽力而为失败只记录日志结算通知的送达策略空闲父级收到一个普通轮次忙碌父级被 steering 合并到下一个 step父级自身已在 teardown 时不唤醒只注入。五、面向模型的适配器deepseek-ai/dsh-tool-subagent-control独立服务包被移除后可选的 tool-subagent-control/src/index.ts 包直接注入ctx.subagents提供两个全局命名的工具它们只是续接 API 的薄适配器不做任何生命周期路由send_message调用ctx.subagents.followup(parent, subagent_id, message, { source: { kind: coordinator, form: relay, senderSessionId: parent.id }, signal })把消息排队为子代理的下一轮。返回messageId不返回子代理的答复——失败即消息未投递interrupt_agent调用ctx.subagents.interrupt(agent_id, { kind: ancestor, agent: caller })只请求取消当前轮次。accepted: true只表示取消信号已受理目标可能继续运行到观察到信号为止已排队消息保持停放、子代理保持可用、对已完成目标是接受的无操作。send_message是独立的适配器加载与否既不启用也不禁用startContinuable。部署完全可以只通过 Task 工具启动并收集续接工作而不暴露send_message。六、委托工具配置backgroundMode是策略provider.resume只是能力deepseek-ai/dsh-tool-subagenttool-subagent/src/index.ts的每个实例通过backgroundMode选择后台语义backgroundMode?: one-shot | continuable // 默认 one-shotone-shot默认调用默认前台执行后台时持有一个普通 Taskcontinuable调用默认后台执行要求提供者具备prepareContinuable能力方法存在即能力返回持久化 child id。该配置项是部署策略而provider.resume只承担已配置续接模式的能力检查角色。因此在合并后的语义下一个支持 resume 的提供者依然可以跑一次性后台工作。启动时若提供者缺少该能力会以UNSUPPORTED_CAPABILITY在挂载阶段快速失败而缺失 Jobs、Agents 或持久化则仍推迟到第一个真正需要它们的操作才失败见文档 Consequences 一节。工具的其他配置项包括provider必填选择ctx.subagents注册名、toolName默认subagent、modelSelectionSettings、enableRunInBackground默认true、agentOptions、persona、toolFilterallow/deny至少其一与maxDepth默认30禁止委托。七、备选方案与取舍Alternatives considered文档记录了几条被否决的路径理解它们有助于把握最终设计边界保留独立服务依赖分离最强但所有生产续接路径都要组合两个服务多出的公共键暴露了调用方不需要的架构区分内部管理器以不新增服务的方式保留了可选的 Task 与持久化依赖。从provider.resume推断续接模式方法存在性正确描述冷恢复能力但不能表达部署策略会把所有可恢复提供者强制进续接后台语义并把兄弟插件缺失变成运行时错误显式工具配置把选择与能力分离。注册续接访问/检查后续工具注册表能把续接面是否存在告诉委托工具但启动持久化工作不需要任何后续适配器——这会重新把 UI 组合编码进执行策略以另一个名字重造兄弟依赖。把普通与续接启动合并为一个方法给start加标志会返回已发布的一次性 run或即时 Task 与 child 身份削弱简单的所有权边界保留startContinuable是更小的改动。八、合并后的后果与迁移要点服务拓扑少了一个公共键、少了一个包原始提供者分发在无 Jobs、无持久化时依然可用续接模式在提供者挂载时快速失败配置了续接而提供者无resume缺 Jobs/Agents/持久化则延迟到首个必需操作处失败后续投递保持可选dsh-subagent包内部对 Jobs 与持久化感知因此仍声明它们为可选 peer 依赖即便普通start调用方并不需要已有的续接竞态、授权、持久性、取消与结算后销毁settle-then-dispose语义保持不变并由迁移后的subagent测试套件如 service.spec.ts、continuation.spec.ts、control.spec.ts持续钉住。对于在 DeepSeek Harness 上开发子代理能力的开发者合并后的心智模型可以简化为一句只面向ctx.subagents一个服务编程——start做一次性委托startContinuable建立持久化续接子代理followup/interrupt/reportFrom处理续接后的交互send_message与interrupt_agent只是这些 API 的可选模型可见面而续接生命周期本身由服务内部的 Task 与持久化感知管理器负责。赞分享人工智能AI AgentAgent 框架DeepSeek【免费下载链接】deepseek-harnessDeepSeek Harness: Everything is a Plugin.项目地址https://gitcode.com/gh_mirrors/de/deepseek-harness点击查看免费下载相关推荐DeepSeek Harness 可继续子代理会话Activation 生命周期、单一 Inbox 续话与子优先销毁DeepSeek Harness 可继续子代理会话Activation 生命周期、单一 Inbox 续话与子优先销毁 本文聚焦 DeepSeek Harnes人工智能AI AgentAgent 框架DeepSeekDeepSeek Harness 子代理继续执行操作的按意图 API 设计SubagentRuntime 四大执行意图与单一持久性屏障DeepSeek Harness 子代理继续执行操作的按意图 API 设计SubagentRuntime 四大执行意图与单一持久性屏障 本篇技术指南以 Dee人工智能AI AgentAgent 框架DeepSeekDeepSeek Harness 投递语义Agent.send() 一消息一轮次的 FIFO 契约设计DeepSeek Harness 投递语义Agent.send 一消息一轮次的 FIFO 契约设计 本文讲解 DeepSeek Harness一切皆插件的人工智能AI AgentAgent 框架DeepSeek创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考