Two findings on the ACP backend: Blocking: cancel() only sent session/cancel, so a child that ignores the notify or wedges the prompt left result hung forever — the model-facing tool awaits result before its finally disposes, so the parent cancellation hung and the child stayed alive, violating the SubagentRun.cancel() contract (result settles aborted). The result path now races the ACP drive against a cancelSettled promise that requestCancel resolves, so result settles aborted the instant a cancel is requested, regardless of the child. dispose() still kills+reaps the process. New MOCK_IGNORE_CANCEL mock mode (receives cancel, never resolves the prompt, never exits) drives a regression proven to hang without the race. Nit: the drive-path catch was an empty broad catch that discarded the error (AGENTS.md forbids). Because cancellation is now handled by the race arm, a rejection reaching the catch is always a genuine child-level error — bind it, flatten to error, and surface the original via a new AcpRunSpec.onError sink that the provider wires to ctx.logger.warn, so a real fault is preserved.
subagent/ — subagent capability family
The subagent seam: an agent delegating work to a child agent. Like the bash and llm families this is a capability seam (see capability seams) — but with one defining difference: multiple provider implementations coexist in one context, registered by name, rather than the single-implementation bash shape. The registry mirrors the LLM adapter registry.
| Package | Role | ctx key |
|---|---|---|
subagent/ |
Abstract subagent seam: named-provider registry + vocabulary | ctx.subagents |
subagent-inprocess/ |
Shared in-process run driver (pure lib; registers nothing) | — |
subagent-spawn/ |
In-process backend: a fresh child agent | (registers on ctx.subagents) |
subagent-fork/ |
In-process backend: a child seeded with the parent's completed-turn prefix | (registers on ctx.subagents) |
subagent-acp/ |
Out-of-process backend: a child agent in a spawned subprocess, driven over ACP | (registers on ctx.subagents) |
tool-subagent/ |
Model-facing subagent delegation tool over ctx.subagents |
(registers on ctx.tools) |
The interface lives at subagent/subagent/. The in-process subagent-spawn / subagent-fork backends share the subagent-inprocess driver (a pure library — both depend on it, neither on the other), and the out-of-process subagent-acp backend ships alongside them here; the test-only dsh-subagent-mock (in support) is separate. All product packages except the mock.
The proposal and design rationale: docs/rfc/implemented/feature/2026-06-21-subagent-capability-seam.md.