多 Agent 不是多开几个 Promise
“多 Agent”常被描述成一张很漂亮的组织架构图:一个 Manager 分解任务,多个 Worker 并行,最后汇总答案。
真正困难的问题藏在图的边缘:子 Agent 是一次性函数,还是可继续会话?父子身份如何持久化?父 Agent 退出后,子 Agent 谁负责?消息按什么顺序进入?取消当前轮是否应该清空队列?进程重启后从哪里恢复?一次 fan-out 脚本的中间态是否有日志?
dsh 同时提供 Subagent seam 与 Workflow seam。它们都能启动多个 Agent,却代表两种不同的状态模型。
第一层:One-shot、Continuable 与 Workflow 是三种任务语义
One-shot Subagent 最接近函数调用。父 Agent 提供 prompt、Provider、可选 output schema、depth limit、tool filter 和 persona;Provider 执行一次子任务,返回结构化结果或错误。它适合边界清晰、调用结束后不再对话的专家任务。
Continuable Subagent 是一个持久 child Session。启动成功后,调用者拿到稳定 child id 和首条 message id;以后可以继续 followup、interrupt、list 和接收 report。它适合长期协作:例如一个代码审查专家先分析,主 Agent 修改后再让同一个专家复核。
Workflow 则是模型编写的编排脚本。当前 worker-thread engine 提供 agent()、parallel/pipeline 等能力,允许脚本 fan-out 子 Agent、收集中间值、返回 JSON。它适合一次性 map/reduce 和结构化编排,不是一个持久会话。
第二层:Continuable child 用 Session 保存身份,用 Activation 表示驻留
在 continuation 设计里,持久 Session 与进程内 Activation 被严格分开。
Session 保存 child id、parent lineage 和 descriptor,是跨进程的身份。Activation 是某段时间内被重建出来的 live AgentHandle。一个 child Session 最多一个 Activation,但可以多次冷启动。
Activation 有三个派生状态:
runningAgent 有活动准入、Turn 或正在唤醒的 inbox work; waiting本 Agent 已静止,但仍拥有未结束的 child Activation; settled本 Agent 静止且所有孩子已释放,可以 dispose handle、移除 Activation。
关键点是它没有再发明第二套消息队列。SubagentRuntime.followup() 最终仍进入该 child Agent 的 Inbox,每条 accepted message 形成 FIFO Turn。Activation 正在运行就排队,waiting 就唤醒,没有 Activation 就 cold resume。
权限来自父子关系,而不是消息里随便写一个 sender id。Continuable followup 要求直接父 Session;ancestor interrupt 要求精确 live Agent 且其 durable lineage 包含目标。消息 source 只做归因,不授予权限。
Interrupt 也有窄语义:对 live target 调用 Agent.cancel(..., {keepInbox:true}),中止当前活动,但保留未认领的 inbox 和已经发布的 descendants。它不是“删除子 Agent”。中断收敛到 idle 后,后续 waking send 可以继续队列。
父子释放遵循 child-first。父 Activation 只有在自身静止、所有 children dispose、best-effort Session flush 完成后才能 settled。这样父任务不会在子任务仍持有运行资源时提前宣告生命周期结束。
One-shot Provider 的能力发现则使用静态 flags。Output schema、depth limit、tool filter 与 persona 若不被 Provider 支持,start 前直接报 UNSUPPORTED_CAPABILITY,而不是运行后静默降级。这种 fail-loud 对异构后端非常重要。
第三层:Workflow 提高表达力,但当前不提供持久执行语义
Workflow engine 接收 meta、script、args、parent、Provider route 和 per-run agent cap。start() 在返回 run 之前同步验证脚本、meta、Provider 与限制;返回后 run.result 不 reject,执行失败以结构化 stopReason 表达。Run 由 holder 拥有,任何路径都必须 dispose。
但它当前没有 journaling 或 resume。脚本、已完成 child、intermediate value 不会形成可重启 checkpoint;进程重启后无法从中间继续。也没有 nested workflow 和跨 child 的 token budget vocabulary。它能限制并发、item 与 agent 数量,却不能回答“一次工作流最多花多少模型 Token”。
因此,选择标准不是“哪个更强”,而是状态期限:
一次性、输入输出明确:one-shot subagent; 需要跨多轮继续、可冷恢复:continuable child; 一次运行中需要 fan-out、聚合、pipeline:workflow; 关键业务既要编排又要中途恢复:当前需要额外领域 journal,不能只依赖 workflow。
对老板而言,多 Agent 的 ROI 也不应只看并发速度。它同时放大模型调用量、工具副作用、权限面和失败组合。dsh 的 agent cap、depth limit、tool filter、parent lineage 与 holder ownership 是治理基础,但 token 总预算仍是明显缺口。
多 Agent 系统的护城河,不是让更多 Agent 同时说话,而是让每个子任务的身份、权限、队列、取消、结算和恢复都可以解释。
源码核验索引
Subagent seam: packages/subagent/subagent/src/types.tsContinuation: packages/subagent/subagent/src/continuation.ts子系统文档: docs/subsystems/subagent.mdWorkflow: packages/workflow/workflow/README.mdWorker engine: packages/workflow/workflow-worker-thread/
事实边界:本文区分的是当前 shipped contract。Workflow 文档明确将 journaling/resume、nested workflow 和 token budget 列为限制,不应对外宣传为已支持。
夜雨聆风