前言¶
在 DeepSeek Harness(cordis)里用 subagent 并设置 run_in_background: true 时,调用会立刻返回 subagentId,子代理在后台继续跑,收尾结果通常靠异步的 settlement 通知送达。若下一步必须依赖子代理的停止原因或收尾消息,原先没有「阻塞等待」这一环:run_in_background: false 只在启动时阻塞;send_message 发完即返;list_agents 明确不是用来做轮询的。下面介绍维护者 john-walks-slow 发布的工作流类插件 dsh-wait-subagent,它注册 wait_subagent 工具,在事件驱动、零轮询的前提下,阻塞直到指定后台 continuable 子代理收尾,并在同一次调用里返回 stop_reason 与 closing_message。
这是什么¶
dsh-wait-subagent 是 DeepSeek Harness 插件,在每个 root agent 上注册一个面向模型的 Agent 工具 wait_subagent。它不改动 Web 客户端、不提供 UI、也没有额外配置项;安装后通过 bundled 的 cordis.patch.yml 自动挂载 loader 入口。
- 仓库:john-walks-slow/dsh-wait-subagent
- 社区目录:SkillHub 插件页
- 许可证:MIT(package.json 版本 1.0.0)
- 运行要求:Node ≥ 22.5;依赖
@deepseek-ai/dsh-tools0.1.2-rc.1(与 dsh 0.1.2-rc.1 锁定版本对齐)
DSH 生态强调「一切皆插件」;SkillHub 等社区目录是独立站点,与 DeepSeek / 幻方无官方从属关系。插件在当前 dsh 进程权限下运行,安装前建议自行查看源码与许可证。
核心功能¶
wait_subagent 工具¶
工具签名(来自 README):
wait_subagent(subagent_id: string, timeout_ms?: integer)
→ { status: "settled" | "timeout" | "cancelled",
subagent_id: string,
stop_reason?: "completed" | "aborted" | "error" | "max-tokens" | "refusal" | "unknown",
closing_message?: string }
行为要点:
- 成员校验:通过
ctx.subagents.listChildren(parent.id)(与list_agents同一投影)校验subagent_id;未知或非本 agent 的子 id 会直接报错,提示使用后台 dispatch 返回的 id(可参考list_agents)。 - 事件等待:监听
subagent/end生命周期事件(子 agent activation 被 dispose 时触发),在插件 context 上订阅,避免与 registry 更新的竞态。 - 可选超时:传入
timeout_ms可在超时后得到status: "timeout";省略则无限等待(文档建议通常省略;若设超时宜给较大值,而非用多次短等待模拟轮询)。 - 取消:尊重调用方的
AbortSignal,返回status: "cancelled"。 - 阻塞语义:等待期间占用调用方 agent 的 tool lane,这是设计行为;等待本身由事件驱动,阻塞时 CPU 开销可忽略。无网络、无外部服务、无文件写入等副作用。
安装与启用¶
安装后需重启 DSH 实例,cordis.patch.yml 会自动注册 loader。
从插件名安装(web profile):
dsh plugin --profile web add dsh-wait-subagent
或从 GitHub 源码安装(纯 ESM JavaScript,无构建步骤,无需 pnpm build-script 审批):
dsh plugin --profile web add github:john-walks-slow/dsh-wait-subagent
典型用法¶
先后台启动子代理,再对返回的 subagentId 调用 wait_subagent:
wait_subagent({ subagent_id: "session-9f2c47ab-83d1-4e06-b5a9-1c7f2d84e0b3" })
调用在子代理运行期间阻塞;收尾后工具返回 JSON,模型侧可见的文本类似:
Subagent session-9f2c47ab-83d1-4e06-b5a9-1c7f2d84e0b3 settled: completed
Spec written to docs/plan.md; 3 files changed, ready for review.
对应结构化结果示例:
{
"status": "settled",
"subagent_id": "session-9f2c47ab-83d1-4e06-b5a9-1c7f2d84e0b3",
"stop_reason": "completed",
"closing_message": "Spec written to docs/plan.md; 3 files changed, ready for review."
}
其他常见结果:
| 情况 | 结果 |
|---|---|
| 调用前子代理已收尾 | status: "settled",stop_reason 可能为 unknown;说明此前已收尾,closing message 可能已通过 settlement 通知单独送达 |
timeout_ms 到期 |
status: "timeout";子代理可能仍在运行 |
| 调用方 AbortSignal 触发 | status: "cancelled" |
| 未知或非本子 agent 的 id | 拒绝并报错 |
适用思路:当你下一步动作依赖子代理结果时,用 wait_subagent 主动等待,而不是猜测或轮询 list_agents。
适用场景与注意¶
适合:编排「后台跑探索 / 写 spec / 改文件 + 主对话等结果再决策」的工作流;需要同一步工具调用内拿到 stop_reason 与 closing_message 的场景。
注意:
- 不要在同一步并行
wait_subagent与interrupt_agent。wait_subagent虽并发安全,但interrupt_agent需要独占 tool lane 且排在进行中的调用之后;同一步并行时往往会先等到 wait 超时,interrupt 才生效。应先interrupt_agent,下一步再wait_subagent(已中断的子 agent 会较快收尾)。 - 无限等待会长期占用 tool lane,这是功能本身;需要上限时再设
timeout_ms。 - 社区目录页星标为 0,不代表功能未验证;以 README 与源码为准。
结尾¶
dsh-wait-subagent 补齐了 run_in_background「即发即返」与异步 settlement 通知之间的缺口:一个事件驱动的 wait_subagent,让主 agent 在依赖子代理结果时能阻塞等待并一次性读回收尾信息。
- 目录页:https://www.skillhub.cn/plugins/john-walks-slow/dsh-wait-subagent
- GitHub:https://github.com/john-walks-slow/dsh-wait-subagent