dsh-wait-subagent:后台子代理的主动等待工具

前言

在 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 入口。

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 }

行为要点:

  1. 成员校验:通过 ctx.subagents.listChildren(parent.id)(与 list_agents 同一投影)校验 subagent_id;未知或非本 agent 的子 id 会直接报错,提示使用后台 dispatch 返回的 id(可参考 list_agents)。
  2. 事件等待:监听 subagent/end 生命周期事件(子 agent activation 被 dispose 时触发),在插件 context 上订阅,避免与 registry 更新的竞态。
  3. 可选超时:传入 timeout_ms 可在超时后得到 status: "timeout";省略则无限等待(文档建议通常省略;若设超时宜给较大值,而非用多次短等待模拟轮询)。
  4. 取消:尊重调用方的 AbortSignal,返回 status: "cancelled"。
  5. 阻塞语义:等待期间占用调用方 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
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜