description: "Global send_message, interrupt_agent, and list_agents tools for users and maintainers composing or debugging continuable-child control."
English | 中文
dsh-tool-subagent-control adds the global control tools for continuable children: send_message steers between a direct parent and child, interrupt_agent stops a child's current turn while keeping its inbox and descendants intact, and list_agents (from the separately loadable list-agents plugin) lists continuable children by durable id and label. Parents and continuable children inherit the same send_message definition and ordering, so model communication adds no child-only tool schema. No tool's presence decides whether a delegation tool starts continuable work.
Mount this package in any composition with continuable children the model should message, interrupt, or list. The root plugin needs only the subagent service; the list tool is a separate plugin a deployment can omit.
Load the subagent service, a backend, the delegation tool, and this package. Adding the separate list plugin exposes all three tools:
- name: '@deepseek-ai/dsh-subagent'
- name: '@deepseek-ai/dsh-subagent-spawn-in-process'
- name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: spawn
backgroundMode: continuable
- name: '@deepseek-ai/dsh-tool-subagent-control'
- name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
This package takes no configuration: the root plugin provides send_message and interrupt_agent, and the list plugin provides list_agents.
Sends a message to an Agent named by agent_id: any exact live Agent may target its direct continuable child, while a resident continuable child may also target its direct parent. A working target receives the message at its nearest step boundary through Steer; an idle target starts a turn, and a cold direct child resumes through the continuation lifecycle. The call returns only acceptance (the accepted message's stable messageId), never a reply. A failure — an unsupported target, unavailable parent, unknown child, descriptor-less child that cannot be resumed, or rejected admission — states the message was not delivered.
Stops only the target's current turn: queued messages stay parked until a later send_message, descendants keep running, and the child stays available for follow-ups. The call returns when the stop request is accepted, not when the target is quiet; interrupting an already-finished agent is an accepted no-op, and self, sibling, stale, and non-ancestor callers get errored results.
Lists the continuable children below the calling agent: children (default) shows direct children, descendants walks the whole tree in stable pre-order, annotating each entry with its durable direct-parent session id and depth. Status comes from the live Agent registry — running, idle, or ready. One-shot children are intentionally absent because they cannot accept send_message, and unreadable candidates appear as diagnostics.
Read these pages when the package-level contract is not enough; they move from the tool schemas to the continuation service behind them.
The generated schemas: send_message takes agent_id and message; interrupt_agent takes agent_id; list_agents takes the optional scope enum.
Fixed schema cost per parent request.
Prefix-stable; the schema does not change at runtime.
interrupt requested for agent <agent_id> on acceptance. An unauthorized caller — self, sibling, stale, or non-ancestor — is an errored result naming the rejection; an absent or settled target still renders the acceptance line.
One short acknowledgement per call; the interrupted turn's abort is visible only in the child's own transcript.
Append-only; each result follows the reusable request prefix.
message delivered to agent <agent_id> on acceptance; the canonical output carries the accepted messageId. A failure — a non-adjacent target, unavailable parent, unknown child, descriptor-less child that cannot be resumed, or admission rejected — is an errored result whose message states the message was not delivered.
One short acknowledgement per call; the target's response never returns through this call. A child uses the same tool with its initial task's parent id to append selected content to parent history.
Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.
One line per continuable child in stable catalog order: <id> [<status>] — <label> (running = active driver, idle = resident between turns, ready = storage only, resumable rather than terminal), plus <id> [diagnostic: <reason>] for a candidate that could not be read. The descendants scope inserts parent=<id> depth=<n> before the label dash on every line, in pre-order. One-shot children are intentionally absent; (no subagents) means no continuable child or diagnostic survived the projection.
Grows linearly with the listed continuable children — the whole tree under the descendants scope; there is no cursor or cap, so long-lived parents with many persisted children pay the full list each call.
Append-only; each result follows the reusable request prefix.
These limits define what the control tools cannot observe or steer; they are current package constraints.
messageId; later target work lands in that target's durable Session and is never collected through this tool. A reply is another explicitly addressed send_message, not this call's result.ready; cross-process accuracy requires a shared lease. interrupt_agent performs the authoritative live-lineage check itself, so discovery staleness cannot grant authority.