Files
deepseek-harness/packages/subagent/tool-subagent-control
creatixchu b7034e4a26 feat(web): declare the remaining context forms on every shipped producer
Four values complete the vocabulary, so the opaque body is reached only by
producers that genuinely promise no shape.

`snapshot` — current state a later snapshot supersedes. system-prompt now
exposes `renderContextSections()`, the named contributions
`renderContextSnapshot()` already joins for the model, so the body attributes
each part to the subsystem that produced it instead of re-splitting joined
prose. The runtime snapshot, time-context, and tmux-context declare it.

`notice` — a one-off account of what just happened, declared by tool-tasks,
goal state changes, tool-goal wrap-up, plan-mode switches, and
repeat-tool-guard. Its `summary` rides the COLLAPSED row: these five are the
majority of shipped producers and none of them needs expanding to be read.
The task summary bounds itself because its inputs are unbounded caller text.

`relay` — a message another agent addressed to this one; both subagent
sources declare it and the body names the sender above what it said.

`recall` — material lifted from another session's log. session-reference
needed no new field: its references already record retained and omitted
counts and the truncation flag, which the body shows first, because recalled
context is bounded on the way in.

`ContextFormed` is now discriminated by `form`, so a producer cannot declare
a shape without the facts that shape is presented from — a notice without its
summary, or a snapshot without its sections, fails to compile.

Only the two hook bridges stay opaque, by design: their content is whatever
an external program printed, so no shape can be promised for it. Unknown
kinds and unreadable records land there too.
2026-08-05 17:11:48 +08:00
..

@deepseek-ai/dsh-tool-subagent-control

English | 中文

The optional, globally named send_message and list_agents tools are thin adapters over ctx.subagents. Provider-bound @deepseek-ai/dsh-tool-subagent instances register distinct delegation tools per transport; this separately loaded package registers shared control tools once, so multiple delegation tools never register duplicate global controls. The root plugin registers send_message and requires only subagents; the separately loadable ./list-agents plugin registers list_agents, declares sessionQuery as a load-time dependency, and remains inactive until that service is available. A deployment without session query keeps send_message and omits the list tool. Neither tool's presence determines whether a delegation tool starts continuable work. These tools own only the parent-to-child direction; the independently installed @deepseek-ai/dsh-tool-subagent-report owns the child-to-parent direction.

The tool performs no lifecycle routing — residency and cold resume belong to the subagent service. It passes exec.agent as the exact live parent that authorizes delivery and attributes every message as durable provenance { kind: 'coordinator', senderSessionId: parent.id }, which the service retains but never treats as authority. Every message becomes the subagent's next FIFO turn through Agent.followup(): if the child is still working, the message waits until its current turn finishes, so it cannot redirect work already underway. The tool forwards its execution signal, which owns admission only until inbox acceptance; once the child accepts the message the accepted turn cannot be cancelled through this tool. This call returns no child reply — its transcript by that id is the source of what it did — and a child with report sends content on its own initiative as a separate parent message. A delivery failure becomes an errored tool result stating the message was not delivered.

list_agents takes no arguments, derives the parent id from the calling agent, and projects ctx.subagents.listChildren() to continuable children without a cursor. The service result also contains one-shot session-backed subagents for consumers such as a UI, but those entries are omitted from this model tool because they cannot accept send_message. Diagnostics remain visible. Durable identity and mode come from each child's descriptor, while delivery-time authority and Activation ownership checks remain send_message's.

Model Experience

Tool schema

What the model sees

The generated send_message schema: subagent_id and message, describing that the message becomes the subagent's next turn, that this call returns no answer from the subagent, and that a failure means the message was not delivered.

Token effect

Fixed schema cost per parent request.

KV Cache effect

Prefix-stable; the schema does not change at runtime.

Delivery result

What the model sees

message queued as the next turn for subagent <subagent_id> on acceptance; the canonical output carries the accepted messageId. A failure — an unauthorized or unknown child, a descriptor-less child that cannot be resumed, or admission rejected — is an errored result whose message states the message was not delivered.

Token effect

One short acknowledgement per call; the child's response never returns through this call. A separately granted report may append selected content to parent history.

KV Cache effect

Append-only; newly visible content follows the reusable request prefix and does not invalidate existing KV-cache entries.

Listing result

What the model sees

One line per continuable child in the trace's stable order: <id> [<status>] — <label> (running = the logical session is live, complete = persisted only and resumable by send_message), plus <id> [diagnostic: <reason>] for a candidate that could not be read (corrupt, unsupported, or unavailable). One-shot children are intentionally absent; (no subagents) means no continuable child or diagnostic survived the projection. Diagnostics never expose descriptor contents.

Token effect

Grows linearly with the parent's direct continuable children; there is no cursor or cap, so long-lived parents with many persisted children pay the full list each call.

KV Cache effect

Append-only; each result follows the reusable request prefix.

Known Limitations and Deferred Work

  • A queued message has no independent result — acceptance returns only its inbox messageId; the child's work lands in the durable child Session and is never collected through this tool. A child granted report may send selected content back separately, but that message is not this call's result.
  • No steering of the current turn — every message opens a later FIFO turn, so a message sent while the child is working runs only after its current turn finishes and cannot redirect it.
  • Listing is a snapshot, not a delivery promise — it may race publication, disposal, or a later message, and another process may activate a child this process reports as complete; cross-process accuracy requires a shared lease.
  • No pagination or deletion — the complete stably ordered set is returned, and persisted children remain listed for as long as their sessions remain in persistence; a service-level bound or delete operation is a later product decision.