Files
deepseek-harness/packages/subagent/tool-subagent
Dudu-0223 50f0d3a299 Merge remote-tracking branch 'origin/master' into parallel-tool-call
# Conflicts:
#	docs/architecture.md
#	docs/config-catalog.md
#	docs/cordis-catalog/services.md
#	docs/rfc/INDEX.md
#	packages/cordis/tool-cordis/src/api-catalog.ts
#	packages/core/agent-loop/README.md
#	packages/core/agent-loop/src/index.ts
#	packages/core/agent-loop/src/loop.ts
#	packages/core/tools/README.md
#	packages/core/tools/src/index.ts
#	packages/subagent/subagent/src/types.ts
#	packages/subagent/tool-subagent/README.md
#	scripts/gen-cordis-catalog.ts
#	scripts/type-equiv.manifest.json
2026-07-13 14:28:32 +08:00
..

@deepseek-ai/dsh-tool-subagent

The subagent tool lets the model delegate one self-contained task and collect the child's final output. It is a thin consumer of ctx.subagents; changing the configured provider changes the transport without changing the model-facing execution contract.

Provider selection

Each plugin instance binds to exactly one provider. The model sees { description, prompt }, not a provider selector. To expose multiple transports, load the plugin multiple times with distinct toolName values.

The description is derived from provider.inheritsParentContext: spawn and ACP tell the model to provide a standalone prompt, while fork says the child already sees completed conversation turns. The plugin follows subagent/provider-added and subagent/provider-removed, so concurrent Cordis plugin loading does not create a registration-order dependency.

Lifecycle

execute passes the tool execution's abort signal when present, otherwise supplies an inert signal to satisfy the required SubagentStartRequest.signal. It awaits ctx.subagents.start(...), then awaits run.result inside a try/finally that always calls run.dispose(). The selected signal therefore covers startup and live execution, while disposal guarantees quiescence on success, failure, and abort.

A non-completed stop reason becomes an isError tool result; partial child output is never reported as success. The current tool blocks the parent turn until collection finishes; background and polling modes are deferred.

Config

Key Meaning
provider Required ctx.subagents provider name.
toolName Model-facing tool name (default subagent). Must be unique per plugin instance.
agentOptions Default child agent options, currently including model.
persona Per-child persona; requires provider persona capability.
toolFilter Per-child global-tool restriction; requires provider toolFilter capability.
maxDepth Absolute delegation-depth cap; requires provider depthLimit capability.

Concurrency

The tool declares isConcurrencySafe: () => true: each call starts an independent child run and returns only its final answer, touching no parent-agent state, and SubagentProvider.start() is contractually concurrent-safe for independent runs (see subagent/). So the agent loop may run several subagent calls from one assistant step in parallel, and the tool description tells the model it may issue independent tasks together when their work scopes do not overlap. The subagent tool stays synchronous (one result = the child's final answer); background spawning + later collection is separate future work.

toolFilter changes the child's visible global tool layer; it is not a parent-derived authority ceiling. See the agent-scope security non-goal.