@xneog/dsh-tool-subagent 0.1.0 → 0.1.3-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/subagent/tool-subagent/README.md
5
- README.md: 9d7ed2e364f6a9dff26a1c9006535f898bdaabcc
6
- README.zh.md: 8650ee35588c2615e4d6c016cb672030ee2e8194
5
+ README.md: 18e391739a504c653933199f3213b6fed2729fed
6
+ README.zh.md: 07c9e75cc115995747c91c2acbcf6afd29c89b94
package/README.md CHANGED
@@ -1,57 +1,184 @@
1
+ ---
2
+ description: "Model-facing subagent delegation tool for users and maintainers configuring, composing, or debugging delegation over a subagent provider."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @xneog/dsh-tool-subagent
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- The model-facing delegation tool over one configured `ctx.subagents` provider. Changing the provider changes transport without changing the execution contract.
10
+ ## Summary
11
+
12
+ `dsh-tool-subagent` is the model-facing delegation tool: it turns one configured `ctx.subagents` provider into a tool the agent can call to start a child agent. Changing the provider changes the transport without changing the execution contract, so one composition can expose several delegation tools, each bound to a different backend. Calls wait for the child by default under `one-shot` policy, or start work in the background by default under `continuable` policy, which returns a durable child id the model can message later. An eligible instance can also let the model discover and select the child's LLM provider, model, and reasoning effort. The tool's descriptions adapt to whether the child inherits the parent's completed turns, and failed runs surface as errored tool results rather than partial success.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ Mount one instance per delegation target, each with a distinct `toolName`. The tool exists exactly while its provider does, so sibling load order and provider reloads never strand it.
29
+
30
+ ### Minimal configuration
31
+
32
+ Load the subagent service, an in-process or remote backend, and this tool; then name the provider. This composition exposes a `subagent` tool that delegates to the `spawn` backend:
33
+
34
+ ```yaml
35
+ - name: '@xneog/dsh-subagent'
36
+ - name: '@xneog/dsh-subagent-spawn-in-process'
37
+ - name: '@xneog/dsh-tool-subagent'
38
+ config:
39
+ provider: spawn
40
+ toolName: subagent
41
+ ```
42
+
43
+ | Field | Default | Meaning |
44
+ |---|---|---|
45
+ | `provider` | required | Provider name on `ctx.subagents` (e.g. `spawn`, `fork`, `acp`) |
46
+ | `toolName` | `subagent` | Model-facing tool name; distinct for every loaded instance |
47
+ | `modelSelectionSettings` | `false` | Sample the Host's exact-route authorization preference for each new top-level Session; valid only in Agent scope and requires provider `agentOptions` support |
48
+ | `enableRunInBackground` | `true` | Expose `run_in_background`; disabling also rejects forced background calls |
49
+ | `backgroundMode` | `one-shot` | Background policy: `one-shot` defaults calls to foreground; `continuable` defaults them to background and requires the provider's `prepareContinuable` capability |
50
+ | `agentOptions` | — | Configured child `provider`, `model`, adapter-owned `reasoningEffort`, and positive `maxTokens` defaults; requires provider `agentOptions` support and overlays any provider-owned route defaults |
51
+ | `persona` | — | Per-child persona; requires the provider's `persona` capability |
52
+ | `toolFilter` | — | Per-child global-tool restriction; requires the `toolFilter` capability |
53
+ | `maxDepth` | `3` | Absolute delegation-depth cap (`0` forbids delegation); `'provider-managed'` sends no cap to an out-of-process provider |
54
+
55
+ The generated [configuration catalog](../../../docs/config-catalog.md#xneogdsh-tool-subagent) is the exhaustive source for every accepted field and its JSDoc.
56
+
57
+ ### Foreground and background modes
58
+
59
+ Under `one-shot` policy, an omitted `run_in_background` waits in the foreground and returns the child's final text; `run_in_background: true` starts a plain parent-owned background job and returns `started background subagent job <id>`, collected with `job_output` and stopped with `job_kill`.
60
+
61
+ Under `continuable` policy, an omitted or `true` `run_in_background` starts a durable child and returns `started subagent <childId>` without waiting for a result; the runtime delivers one settlement notice when the child's Activation ends, and the optional `send_message` tool sends it more work. Set `run_in_background: false` to wait for the result in the foreground.
6
62
 
7
- ## Provider selection and lifecycle
63
+ `maxDepth` caps recursion (default `3`; `0` forbids delegation) and requires a provider with the `depthLimit` capability; `'provider-managed'` leaves the budget to an out-of-process provider. `persona` and `toolFilter` configure every child when the provider supports them, and the tool stays visible at the cap — each attempted start checks the calling agent's current depth and rejects with an errored result.
8
64
 
9
- Each plugin instance binds one `provider` to one `toolName`; the model receives no provider selector. Load another distinctly named instance to expose another transport. The tool registers only while its provider exists, avoiding sibling load-order and provider-reload dependencies. Its description follows `provider.inheritsParentContext`: fresh children require standalone prompts, while forked children already see completed parent turns.
65
+ ### Selecting a child LLM
10
66
 
11
- A foreground call passes the execution signal through startup and execution, awaits `run.result`, and always awaits `run.dispose()` before returning. Only `completed` returns the canonical `{ kind: 'foreground', runId, output: JsonValue[] }`, rendered as the same final text; abort, refusal, token limit, and other failures become errored tool results whose message appends the child's preserved partial text (the `SubagentResult.output` selection) after the stop-reason headline, so a truncated answer is never reported as success yet never silently lost. If result collection and disposal both reject, the errored result preserves both diagnostics.
67
+ Set `modelSelectionSettings: true` to sample the Host's `subagent-model-selection` preference when each fresh top-level Session is composed. A restored Session without a recorded policy remains disabled, including an explicitly empty restore. When enabled, the non-empty exact provider/model route list is recorded in the Session, inherited by child Sessions, and unchanged by later settings edits. The tool then exposes optional `provider`, `model`, and `reasoning_effort` fields and registers the shared `list_subagent_models` tool. This mode requires a backend that advertises `agentOptions`; both in-process backends and DSH SDK support it, while ACP, Codex, and Claude Code reject it rather than ignore it.
12
68
 
13
- `backgroundMode` selects both the background route and the omitted `run_in_background` default. `one-shot` waits in the foreground by default; an explicit `true` registers a plain parent-owned Task and returns canonical `{ kind: 'background', jobId }`, rendered as `started background subagent job <id>`, even when the provider supports continuable children. Generic task tools own its later status, collection, cancellation, and notices. `continuable` runs in the background when the argument is omitted or `true`; an explicit `false` waits for the result in the foreground. Its background route requires a provider with the `prepareContinuable` capability, calls `ctx.subagents.startContinuable()`, and returns `{ kind: 'continuable', subagentId }`, rendered as `started subagent <childId>`. The route resolves at inbox acceptance: the child owns its own turns from there, so this call neither waits for nor collects a result. The child's transcript by that id remains the source of its detailed output, and the optional global `send_message` tool sends it more work. The continuation service delivers one settlement notice whenever the child's Activation ends, containing its outcome and any final assistant message independently of `report`. Starting continuable work does not require `send_message` to be loaded. See the [background subagent Agent Note](../../../.agents/notes/implemented/feature/2026-07-08-background-subagent-tasks.md), the [continuable subagents Agent Note](../../../.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.md), and the [background-first delegation Agent Note](../../../.agents/notes/implemented/feature/2026-08-11-background-first-continuable-delegation.md).
69
+ A call supplies `provider` and `model` together, or supplies only an effort when configured, parent, or provider-owned defaults provide the route. Static `provider.agentRouteDefaults`, when present, form the provider/model baseline; tool configuration and model fields overlay it before route-aware effort merging and exact-route preflight. Providers without these defaults use compatible values from the parent's latest logged request, then the parent's creation options before its first request, while retaining the configured `maxTokens`. Changing the route without an explicit effort clears the inherited route-owned effort, so the selected model resolves its default. The live LLM adapter validates the effective route before child creation. Catalog membership remains advisory, so a model can use an unlisted id when its adapter accepts it.
14
70
 
15
- `toolFilter` changes the child's global tool layer but is not a parent-derived authority ceiling. See the [agent-scope security non-goal](../../../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md#security-and-authority-are-non-goals).
71
+ -----
16
72
 
17
- ## Config
73
+ <a id="understand-the-implementation"></a>
74
+ ## Understand the implementation
18
75
 
19
- | Key | Meaning |
76
+ <details>
77
+ <summary>Implementation internals — click to expand</summary>
78
+
79
+ This section explains how the tool mirrors provider lifecycle and settles runs; the observable behavior is covered in [Use this package](#use-this-package).
80
+
81
+ ### Design concept
82
+
83
+ One instance is one provider plus one tool name. The plugin mirrors provider lifecycle: it registers the tool when the named provider appears and disposes it when the provider leaves, so sibling load order and HMR replacement cannot strand a dangling tool. A numeric `maxDepth` or configured LLM selection the provider cannot enforce fails the mount instead of the first delegation. At most one instance in a tool scope may own model selection because `list_subagent_models` has a global name.
84
+
85
+ ### Foreground settlement
86
+
87
+ A foreground call awaits `run.result`, maps every non-completed stop reason to an error headline, appends the provider diagnostic and any preserved partial assistant text, and always awaits `run.dispose()` before returning; when result collection and disposal both reject, the errored result preserves both failures.
88
+
89
+ ### Background routes
90
+
91
+ One-shot background registers a plain parent-owned Task whose done channel settles the start and keeps the stop reason and optional provider diagnostic in its detail. Continuable background calls `ctx.subagents.startContinuable()`, which resolves at inbox acceptance: the child owns its own turns from there, so the call neither waits for nor collects a result.
92
+
93
+ ### Context-sensitive wording
94
+
95
+ The tool's description derives from `provider.inheritsParentContext`: a fresh child gets "it does not see this conversation" wording, a forked child gets "it does not see the current in-flight turn" wording, so the model never restates or omits context that does not exist.
96
+
97
+ ### Source map
98
+
99
+ | File | Role |
20
100
  |---|---|
21
- | `provider` (required) | Provider name (`spawn`, `fork`, `acp`, ...). |
22
- | `toolName` | Model-facing name, default `subagent`; distinct for every loaded instance. |
23
- | `enableRunInBackground` | Exposes background mode, default `true`; disabling also rejects forced background calls. |
24
- | `backgroundMode` | Background lifecycle policy, default `one-shot`. `one-shot` defaults calls to foreground; `continuable` defaults them to background, requires the provider's `prepareContinuable` capability, and returns a durable child id without requiring the follow-up tool. |
25
- | `agentOptions` | Provider-specific child `provider`, `model`, and positive `maxTokens`; the in-process provider treats explicit values as overrides of inherited parent options. |
26
- | `persona` | Per-child persona; requires provider `persona` capability. |
27
- | `toolFilter` | Per-child global-tool restriction; requires `toolFilter` capability. |
28
- | `maxDepth` | Absolute delegation-depth cap, default `3` (`0` forbids delegation); a numeric cap requires the `depthLimit` capability and fails the mount without it. `'provider-managed'` sends no cap for an out-of-process provider whose budget belongs to the child harness. The tool stays visible at the cap; each attempted start checks the calling agent's current depth and returns an errored tool result when rejected. |
101
+ | [`src/index.ts`](src/index.ts) | Tool registration, lifecycle mirroring, mode resolution, result settlement |
102
+ | [`src/model-selection.ts`](src/model-selection.ts) | Request/config merge and live LLM route preflight |
103
+ | [`src/model-selection-settings.ts`](src/model-selection-settings.ts) | Host-owned opt-in setting sampled for new Sessions |
104
+ | [`src/model-selection-state.ts`](src/model-selection-state.ts) | Session event that records and inherits the sampled decision |
105
+ | [`src/list-models.ts`](src/list-models.ts) | `list_subagent_models` runtime discovery tool |
106
+
107
+ </details>
108
+
109
+ -----
110
+
111
+ <a id="further-exploration"></a>
112
+ ## Further Exploration
113
+
114
+ Read these pages when the package-level contract is not enough; they move from the tool's runtime behavior to the seam it delegates over and the adjacent child tools.
29
115
 
30
- ## Concurrency
116
+ - [Subagent subsystem](../../../docs/subsystems/subagent.md) — providers, one-shot start requests, continuable children and activations.
117
+ - [dsh-tool-subagent-control](../tool-subagent-control/README.md) — messaging, interrupt, and listing tools for continuable children.
118
+ - [Generated tool catalog](../../../docs/tool-catalog.md#xneogdsh-tool-subagent) — the default schema and per-mode wording.
119
+ - [Generated configuration catalog](../../../docs/config-catalog.md#xneogdsh-tool-subagent) — every accepted config field.
120
+ - [Background subagent tasks](../../../.agents/notes/implemented/feature/2026-07-08-background-subagent-tasks.md) — the one-shot background route.
121
+ - [Background-first continuable delegation](../../../.agents/notes/implemented/feature/2026-08-11-background-first-continuable-delegation.md) — why continuable work defaults to background.
122
+ - [Model-selected subagent routes](../../../.agents/notes/implemented/feature/2026-08-18-model-selected-subagent-routes.md) — selection policy, inheritance, discovery, and the fork restriction.
31
123
 
32
- Foreground and background calls are concurrency-safe: sibling delegations in one assistant message overlap under the loop's rolling pool (`maxParallelToolCalls`), and results still commit in model order. Children work in their own sessions and a run never mutates the parent session; the one-shot background form's one parent-owned write — registering a Task — is a synchronous, commutative insertion that tolerates concurrent dispatch, so overlapping background calls acquire their job ids in dispatch-race order. Coordinating sibling workspace effects belongs to the model, exactly as it already does for background and continuable children. See the [parallel subagent Agent Note](../../../.agents/notes/implemented/feature/2026-08-09-parallel-subagent-delegations.md) and the [parallel tool-call Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-parallel-tool-call-execution.md).
124
+ -----
33
125
 
126
+ <a id="model-experience"></a>
34
127
  ## Model Experience
35
128
 
36
129
  ### Tool schema
37
130
 
38
131
  #### What the model sees
39
132
 
40
- The generated default [`subagent` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tool-subagent) under this instance's configured name while its provider exists. Provider context inheritance changes the tool and prompt descriptions. Enabled background mode adds `run_in_background`: continuable mode documents its `true` default, runtime settlement notice, and explicit foreground override, while one-shot mode documents its `false` default and the job id collected with `job_output` or stopped with `job_kill`. While the tool is visible in an assembly's scope, a `tool:<toolName>` system-prompt section tells the model to start independent continuable delegations together, keep working while they run, and choose foreground only when its next action depends on the result; a tool restriction removes both its schema and this guidance.
133
+ The generated default [`subagent` schema](../../../docs/tool-catalog.md#xneogdsh-tool-subagent) under this instance's configured name while its provider exists. An enabled Session policy adds `provider`, `model`, and `reasoning_effort` plus inheritance and selection guidance; the provider must support `agentOptions`. Provider context inheritance changes the tool and prompt descriptions. Enabled background mode adds `run_in_background`: continuable mode documents its `true` default, runtime settlement notice, and explicit foreground override, while one-shot mode documents its `false` default and the job id collected with `job_output` or stopped with `job_kill`. While the tool is visible in an assembly's scope, a `tool:<toolName>` system-prompt section tells the model to start independent continuable delegations together, keep working while they run, and choose foreground only when its next action depends on the result; a tool restriction removes both its schema and this guidance.
41
134
 
42
135
  #### Token effect
43
136
 
44
- Fixed schema cost per parent request; each provider instance adds one schema, and each continuable instance adds one short system-prompt section.
137
+ Fixed schema cost per parent request; model selection adds three parameters. Each provider instance adds one schema, and each continuable instance adds one short system-prompt section.
45
138
 
46
139
  #### KV Cache effect
47
140
 
48
- Prefix-stable while provider instances, names, descriptions, and schemas are unchanged. Provider registration lifecycle may invalidate parent reuse from the first changed tool definition.
141
+ Prefix-stable while provider instances and their configuration are unchanged. Adapter catalog changes do not alter the definition; a child route override may prevent a fork child from reusing the inherited parent prefix.
142
+
143
+ ### Model selection and discovery
144
+
145
+ #### What the model sees
146
+
147
+ A settings-controlled instance whose Session carries a policy exposes the child LLM selection fields and `list_subagent_models`. Calls reject while the optional `ctx.llm` service is unavailable. Discovery returns only registered providers and advertised models in the exact route policy; an unauthorized provider is rejected before its adapter catalog is called, and an exact lookup must be allowed before it resolves the model's reasoning efforts and default. Execution independently enforces the same policy.
148
+
149
+ #### Token effect
150
+
151
+ One fixed discovery schema is present in enabled compositions. Directory contents enter the transcript only when the model calls the tool.
152
+
153
+ #### KV Cache effect
154
+
155
+ The schema is prefix-stable across adapter registration and catalog changes. Each discovery result is appended after the reusable prefix.
156
+
157
+ ### System prompt
158
+
159
+ #### What the model sees
160
+
161
+ When `enableRunInBackground` and `backgroundMode: continuable` are both set, the model additionally reads a `tool:<toolName>` system-prompt section telling it to start independent continuable delegations together and keep working while they run. With the default tool name `subagent`, the section text is:
162
+
163
+ ##### Tool-guidance section
164
+
165
+ ```markdown
166
+ Use subagent in the background by default. Start independent delegations together in one assistant message and continue useful work while they run. Set `run_in_background: false` only when your next action depends on that subagent's result. When a background run settles, the runtime sends you a notice containing its outcome and any final assistant message.
167
+ ```
168
+
169
+ #### Token effect
170
+
171
+ One short fixed section per continuable instance, paid on every parent request while the tool is in scope.
172
+
173
+ #### KV Cache effect
174
+
175
+ Prefix-stable while the section text and tool presence are unchanged; removing the tool or changing the section establishes a different parent prefix.
49
176
 
50
177
  ### Foreground result
51
178
 
52
179
  #### What the model sees
53
180
 
54
- The call retains the description and prompt. Success contains only the child's final text; other outcomes become `Error: <message>`. Intermediate child steps stay out of the parent.
181
+ The call retains the description and prompt. Success contains only the child's final text; other outcomes become `Error: <stop reason>`, followed by a safe provider diagnostic when present and then any partial assistant text. Intermediate child steps stay out of the parent.
55
182
 
56
183
  #### Token effect
57
184
 
@@ -65,7 +192,7 @@ Append-only; newly visible content follows the reusable request prefix and does
65
192
 
66
193
  #### What the model sees
67
194
 
68
- Start returns exactly `started subagent <childId>` in configured continuable mode, or `started background subagent job <id>` in configured one-shot mode. In one-shot mode the generic task surface provides later status, final output, cancellation responses, and notices. In continuable mode this tool returns no result of its own; the child's settlement reaches the parent as a [service-owned notice](../subagent/README.md#settlement-notice), an independently loaded `send_message` tool delivers follow-ups, and the child's transcript by its id is the source of its detailed output.
195
+ Start returns exactly `started subagent <childId>` in configured continuable mode, or `started background subagent job <id>` in configured one-shot mode. In one-shot mode the generic task surface provides later status, final output, cancellation responses, and notices; failed status detail includes the provider diagnostic when the result supplied one. In continuable mode this tool returns no result of its own: the child's settlement reaches the parent as a service-owned notice, an independently loaded `send_message` tool delivers follow-ups, and the child's transcript by its id is the source of its detailed output.
69
196
 
70
197
  #### Token effect
71
198
 
@@ -77,6 +204,22 @@ Append-only; newly visible content follows the reusable request prefix and does
77
204
 
78
205
  ## Known Limitations and Deferred Work
79
206
 
207
+ <a id="known-limitations-and-deferred-work"></a>
208
+
209
+
210
+ These limits define what this tool does not return or enforce; they are current package constraints.
211
+
80
212
  - **Background runs expose no result through this tool** — a one-shot task's final output is collected through the generic task surface, and a continuable child's output stays in its own session, read by its subagent id. The settlement notice states how that child ended and carries any final assistant message, but it is not this call's return value and cannot be awaited here.
81
213
  - **Duplicate names across waiting one-shot instances are detected late** (`TODO(subagent-dup-toolname)`) — continuable instances reserve their prompt-section name during plugin application, but preventing provider-registration rollback for waiting one-shot instances requires a registry of intended names.
82
- - **Child policy is fixed per instance** — another model, persona, tool filter, or depth cap requires another distinctly named tool.
214
+ - **Shipped fork tools cannot select a child LLM route** — they inherit the parent's provider and model to keep the copied conversation prefix eligible for KV Cache reuse. Re-enable selection only when route changes preserve reuse or expose a bounded recomputation cost.
215
+ - **Non-routing child policy is fixed per instance** — another persona, tool filter, or depth cap requires another distinctly named tool. LLM selection requires an enabled per-Session preference and a provider that advertises `agentOptions`; both in-process providers and DSH SDK advertise it, while ACP, Codex, and Claude Code reject it rather than ignore it.
216
+
217
+ <a id="dev-note"></a>
218
+ ### Dev Note
219
+
220
+ <details>
221
+ <summary>Working context for maintainers — click to expand</summary>
222
+
223
+ None.
224
+
225
+ </details>
package/README.zh.md CHANGED
@@ -1,61 +1,188 @@
1
+ ---
2
+ description: "面向模型的 subagent 委派工具,供用户与维护者配置、组合或排查基于 subagent 提供方的委派。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @xneog/dsh-tool-subagent
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- 基于一个已配置 `ctx.subagents` 提供方、面向模型的委派工具。更换提供方只会改变传输,不会改变执行约定。
10
+ ## 概述
11
+
12
+ `dsh-tool-subagent` 是面向模型的委派工具:它把一个已配置的 `ctx.subagents` 提供方变成 agent 可以调用来启动子 agent(智能体)的工具。更换提供方只会改变传输,不会改变执行约定,因此一个组合可以暴露多个委派工具,各自绑定不同的后端。`one-shot` 策略下,调用默认在前台等待子 agent;`continuable` 策略下,调用默认在后台启动工作,并返回模型之后可以发消息的持久化子 agent id。合适的实例还可让模型发现并选择子 agent 的 LLM 提供方、模型与推理等级。工具的描述会随子 agent 是否继承父级已完成轮次而调整,失败的运行以出错的工具结果呈现,而非部分成功。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
27
+
28
+ 每个委派目标挂载一个实例,且每个实例的 `toolName` 必须不同。工具与其提供方同时存在、同时消失,因此同级加载顺序与提供方重新加载都不会让工具悬空。
29
+
30
+ ### 最小配置
31
+
32
+ 先加载 subagent 服务、一个进程内或远程后端与本工具,然后指定提供方名称。此组合暴露一个委派给 `spawn` 后端的 `subagent` 工具:
33
+
34
+ ```yaml
35
+ - name: '@xneog/dsh-subagent'
36
+ - name: '@xneog/dsh-subagent-spawn-in-process'
37
+ - name: '@xneog/dsh-tool-subagent'
38
+ config:
39
+ provider: spawn
40
+ toolName: subagent
41
+ ```
42
+
43
+ | 字段 | 默认值 | 含义 |
44
+ |---|---|---|
45
+ | `provider` | 必填 | `ctx.subagents` 上的提供方名称(如 `spawn`、`fork`、`acp`) |
46
+ | `toolName` | `subagent` | 面向模型的工具名称;每个已加载实例必须不同 |
47
+ | `modelSelectionSettings` | `false` | 为每个新顶层 Session 读取宿主的精确路由授权偏好;只在 Agent 作用域内有效,并要求提供方支持 `agentOptions` |
48
+ | `enableRunInBackground` | `true` | 公开 `run_in_background`;禁用时也会拒绝强制后台调用 |
49
+ | `backgroundMode` | `one-shot` | 后台策略:`one-shot` 默认前台调用;`continuable` 默认后台调用,并要求提供方具备 `prepareContinuable` 能力 |
50
+ | `agentOptions` | — | 配置的子级 `provider`、`model`、适配器所有的 `reasoningEffort` 与正整数 `maxTokens` 默认值;要求提供方支持 `agentOptions`,并会覆盖提供方持有的路由默认值 |
51
+ | `persona` | — | 每个子 agent 独立的 persona;要求提供方具备 `persona` 能力 |
52
+ | `toolFilter` | — | 每个子 agent 独立的全局工具限制;要求提供方具备 `toolFilter` 能力 |
53
+ | `maxDepth` | `3` | 绝对委派深度上限(`0` 禁止委派);`'provider-managed'` 不向进程外提供方发送上限 |
54
+
55
+ 生成的[配置目录](../../../docs/config-catalog.zh.md#xneogdsh-tool-subagent)是每个受支持字段及其 JSDoc 的穷尽式真源。
56
+
57
+ ### 前台与后台模式
58
+
59
+ `one-shot` 策略下,省略 `run_in_background` 会在前台等待并返回子 agent 的最终文本;`run_in_background: true` 会启动一个归父级所有的普通后台任务,并返回 `started background subagent job <id>`,可用 `job_output` 收集、用 `job_kill` 停止。
60
+
61
+ `continuable` 策略下,省略或为 `true` 的 `run_in_background` 会启动一个持久化子 agent,并返回 `started subagent <childId>`,不等待结果;子 agent 的 Activation 结束时,运行时投递一条结算通知,可选的 `send_message` 工具会向它发送更多工作。把 `run_in_background` 设为 `false` 可在前台等待结果。
6
62
 
7
- ## 提供方选择与生命周期
63
+ `maxDepth` 限制递归深度(默认 `3`;`0` 禁止委派),并要求提供方具备 `depthLimit` 能力;`'provider-managed'` 把预算留给进程外提供方。当提供方支持时,`persona` 与 `toolFilter` 会配置每个子 agent;工具在达到上限时仍然可见——每次尝试启动都会检查调用 agent 的当前深度,被拒绝时返回出错的工具结果。
8
64
 
9
- 每个插件实例把一个 `provider` 绑定到一个 `toolName`;模型不会收到提供方选择器。如需公开另一种传输,请加载另一个名称不同的实例。工具只在其提供方存在时注册,从而避免对同级加载顺序和提供方重新加载的依赖。工具描述遵循 `provider.inheritsParentContext`:新建子 agent(智能体)需要独立提示词,而 fork 子 agent 已能看到父级已完成轮次。
65
+ ### 选择子级 LLM
10
66
 
11
- 前台调用会让执行信号贯穿启动和执行,等待 `run.result`,并且在返回前总会等待 `run.dispose()`。只有 `completed` 会返回规范值 `{ kind: 'foreground', runId, output: JsonValue[] }`,并渲染为相同的最终文本;中止、拒绝、token 上限和其他失败都会变成出错的工具结果,其消息在终止原因标题之后附带子 agent 保留下来的部分文本(即 `SubagentResult.output` 的选取结果)——被截断的回答不会被报告为成功,也绝不会被悄悄丢弃。如果结果收集与 dispose(资源释放)都 reject,出错的结果会保留两项诊断信息。
67
+ 设置 `modelSelectionSettings: true`,即可在组合每个全新顶层 Session 时读取宿主的 `subagent-model-selection` 偏好。没有已记录策略的恢复 Session 会保持禁用,包括显式为空的恢复。启用后,非空的精确 provider/model 路由列表会记录进 Session、由子 Session 继承,后续设置编辑不会改变它。工具随后公开可选的 `provider`、`model` `reasoning_effort` 字段,并注册共享的 `list_subagent_models` 工具。此模式要求后端声明 `agentOptions`;两个进程内后端和 DSH SDK 支持该能力,而 ACP、Codex 与 Claude Code 会拒绝它,而不是忽略它。
12
68
 
13
- `backgroundMode` 同时选择后台路由与省略 `run_in_background` 时的默认行为。`one-shot` 默认在前台等待;显式传入 `true` 时,它会注册一个归父级所有的普通 Task,并返回规范值 `{ kind: 'background', jobId }`,渲染为 `started background subagent job <id>`,即使提供方支持可继续子 agent 也不例外。通用 Task 工具负责其后续状态、收集、取消和通知。`continuable` 在参数省略或为 `true` 时于后台运行;显式传入 `false` 时则在前台等待结果。其后台路由要求提供方具备 `prepareContinuable` 能力,调用 `ctx.subagents.startContinuable()`,并返回 `{ kind: 'continuable', subagentId }`,渲染为 `started subagent <childId>`。该路由在 inbox 接受时结算:子 agent 自此拥有自己的轮次,因此该调用既不等待也不收集结果。通过该 id 查看其 transcript(文本记录)仍是其详细输出的来源,可选的全局 `send_message` 工具则向其发送更多工作。每当子 agent 的 Activation 结束,继续执行服务都会投递一条结算通知,其中包含结束结果及可能存在的最终 assistant 消息,且这项投递不依赖 `report`。启动可继续工作不要求加载 `send_message`。见[后台 subagent Agent Note](../../../.agents/notes/implemented/feature/2026-07-08-background-subagent-tasks.md)、[可继续的 subagent Agent Note](../../../.agents/notes/implemented/feature/2026-07-28-continuable-subagent-conversations.md)和[后台优先委派 Agent Note](../../../.agents/notes/implemented/feature/2026-08-11-background-first-continuable-delegation.md)
69
+ 一次调用需同时提供 `provider` `model`;当配置值、父 agent 值或提供方持有的默认值能提供路由时,也可只提供推理等级。静态的 `provider.agentRouteDefaults` 在存在时构成提供方/模型基线;工具配置与模型字段会在路由相关强度合并和确切路由预检前覆盖它。没有这些默认值的提供方会使用父 agent 最新已记录请求中的兼容值,再使用父级首次请求前的创建选项,并保留配置的 `maxTokens`。更改路由但未显式提供推理等级时,会清除继承的路由自有等级,使所选模型解析自己的默认值。实时 LLM 适配器在创建子 agent 前校验有效路由。目录成员资格只提供建议,因此适配器接受时,模型可以使用未列出的 id。
14
70
 
15
- `toolFilter` 会改变子 agent 的全局工具层,但不是从父级派生的权限上限。见 [agent 作用域的安全非目标](../../../.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md#security-and-authority-are-non-goals)。
71
+ -----
16
72
 
17
- ## 配置
73
+ <a id="understand-the-implementation"></a>
74
+ ## 理解实现
18
75
 
19
- | 键 | 含义 |
76
+ <details>
77
+ <summary>实现细节——点击展开</summary>
78
+
79
+ 本节解释工具如何镜像提供方生命周期并结算运行;可观察行为已在[使用本包](#use-this-package)中说明。
80
+
81
+ ### 设计理念
82
+
83
+ 一个实例就是一个提供方加一个工具名称。插件镜像提供方生命周期:具名提供方出现时注册工具,提供方离开时释放工具,因此同级加载顺序与 HMR 替换不会让工具悬空。提供方无法执行的数值型 `maxDepth` 或已配置 LLM 选择会在挂载时失败,而不是在首次委派时失败。每个工具作用域内最多一个实例可以拥有模型选择,因为 `list_subagent_models` 使用全局名称。
84
+
85
+ ### 前台结算
86
+
87
+ 前台调用会等待 `run.result`,把每个非完成终止原因映射为错误标题,追加提供方诊断与任何保留下来的部分 assistant 文本,并在返回前始终等待 `run.dispose()`;当结果收集与 dispose(资源释放)都 reject 时,出错结果会保留两项失败。
88
+
89
+ ### 后台路由
90
+
91
+ 一次性后台模式会注册一个归父级所有的普通 Task,其 done 通道结算启动,并在 detail 中保留终止原因与可选提供方诊断。可继续后台模式调用 `ctx.subagents.startContinuable()`,该调用在 inbox 接受时结算:子 agent 自此拥有自己的轮次,因此该调用既不等待也不收集结果。
92
+
93
+ ### 随上下文变化的措辞
94
+
95
+ 工具描述源自 `provider.inheritsParentContext`:全新子 agent 得到「it does not see this conversation」措辞,fork 子 agent 得到「it does not see the current in-flight turn」措辞,因此模型既不会复述、也不会省略并不存在的上下文。
96
+
97
+ ### 源码地图
98
+
99
+ | 文件 | 职责 |
20
100
  |---|---|
21
- | `provider`(必填) | 提供方名称(`spawn`、`fork`、`acp` 等)。 |
22
- | `toolName` | 面向模型的名称,默认 `subagent`;每个已加载实例必须不同。 |
23
- | `enableRunInBackground` | 公开后台模式,默认 `true`;禁用时也会拒绝强制后台调用。 |
24
- | `backgroundMode` | 后台生命周期策略,默认 `one-shot`。`one-shot` 默认前台调用;`continuable` 默认后台调用,要求提供方具备 `prepareContinuable` 能力,并返回持久化子 agent ID,且不要求加载后续消息工具。 |
25
- | `agentOptions` | 传给具体提供方的子 agent `provider`、`model` 和正整数 `maxTokens`;进程内提供方会用显式值覆盖继承的父级选项。 |
26
- | `persona` | 每个子 agent 独立的 persona;要求提供方具备 `persona` 能力。 |
27
- | `toolFilter` | 每个子 agent 独立的全局工具限制;要求提供方具备 `toolFilter` 能力。 |
28
- | `maxDepth` | 绝对委派深度上限,默认 `3`(`0` 禁止委派);数值上限要求 `depthLimit` 能力,缺失时挂载失败。对于预算由子 harness 拥有的进程外提供方,`'provider-managed'` 不发送上限。工具在达到上限时仍然可见;每次尝试启动都会检查调用 agent 的当前深度,被拒绝时返回出错的工具结果。 |
101
+ | [`src/index.ts`](src/index.ts) | 工具注册、生命周期镜像、模式解析、结果结算 |
102
+ | [`src/model-selection.ts`](src/model-selection.ts) | 请求/配置合并与实时 LLM 路由预检 |
103
+ | [`src/model-selection-settings.ts`](src/model-selection-settings.ts) | 为新 Session 读取的宿主所有 opt-in 设置 |
104
+ | [`src/model-selection-state.ts`](src/model-selection-state.ts) | 记录并继承已读取决定的 Session 事件 |
105
+ | [`src/list-models.ts`](src/list-models.ts) | `list_subagent_models` 运行时发现工具 |
106
+
107
+ </details>
108
+
109
+ -----
110
+
111
+ <a id="further-exploration"></a>
112
+ ## 进一步探索
29
113
 
30
- ## 并发
114
+ 当包级约定不够用时阅读以下页面;它们从工具运行时行为进入它所委派其上的 seam,以及相邻的子 agent 工具。
31
115
 
32
- 前台调用和后台调用均并发安全:同一条 assistant 消息中的同级委派会在循环的滚动池(`maxParallelToolCalls`)下重叠执行,结果仍按模型顺序提交。子 agent 在各自的会话中工作,一次运行绝不变更父会话;一次性后台形态对父级拥有状态的唯一写入是注册一个 Task——这是一次同步、可交换、能容忍并发分发的插入,因此重叠的后台调用按分发竞态顺序获得各自的 job id。协调同级工作区效果由模型负责,正如模型已经对后台和可继续子 agent 所承担的那样。见 [并行 subagent Agent Note](../../../.agents/notes/implemented/feature/2026-08-09-parallel-subagent-delegations.md) [并行工具调用 Agent Note](../../../.agents/notes/implemented/feature/2026-07-10-parallel-tool-call-execution.md)
116
+ - [Subagent 子系统](../../../docs/subsystems/subagent.zh.md)——提供方、一次性启动请求、可继续子 agent Activation
117
+ - [dsh-tool-subagent-control](../tool-subagent-control/README.zh.md)——可继续子 agent 的消息、中断与列表工具。
118
+ - [生成工具目录](../../../docs/tool-catalog.zh.md#xneogdsh-tool-subagent)——默认 schema 与各模式的措辞。
119
+ - [生成配置目录](../../../docs/config-catalog.zh.md#xneogdsh-tool-subagent)——每个受支持配置字段。
120
+ - [后台 subagent 任务](../../../.agents/notes/implemented/feature/2026-07-08-background-subagent-tasks.zh.md)——一次性后台路由。
121
+ - [后台优先的可继续委派](../../../.agents/notes/implemented/feature/2026-08-11-background-first-continuable-delegation.zh.md)——可继续工作为何默认在后台运行。
122
+ - [模型选择 subagent 路由](../../../.agents/notes/implemented/feature/2026-08-18-model-selected-subagent-routes.zh.md)——选择策略、继承、发现与 fork 限制。
33
123
 
124
+ -----
125
+
126
+ <a id="model-experience"></a>
34
127
  ## 模型体验
35
128
 
36
129
  ### 工具 schema
37
130
 
38
- #### 模型看到的内容
131
+ #### 模型看到什么
132
+
133
+ 当提供方存在时,以当前实例配置的名称公开已生成的默认 [`subagent` schema](../../../docs/tool-catalog.zh.md#xneogdsh-tool-subagent)。启用的 Session 策略会添加 `provider`、`model` 与 `reasoning_effort`,以及继承和选择指引;提供方必须支持 `agentOptions`。提供方是否继承上下文会改变工具描述和提示词描述。启用后台模式会添加 `run_in_background`:可继续模式会记录其默认值为 `true`、运行时结算通知与显式前台覆盖;一次性模式会记录其默认值为 `false`,以及用 `job_output` 收集或用 `job_kill` 停止的 job id。当工具在本次组装的作用域中可见时,一个 `tool:<toolName>` 系统提示词 section 会指示模型同时启动相互独立的可继续委派、在它们运行时继续工作,并且仅当下一步动作依赖结果时选择前台;工具限制会同时移除其 schema 和这段指引。
134
+
135
+ #### Token 影响
136
+
137
+ 每个父级请求支付固定的 schema 成本;模型选择会增加三个参数。每个提供方实例增加一个 schema,每个可继续实例还增加一个简短的系统提示词 section。
138
+
139
+ #### KV Cache 影响
140
+
141
+ 只要提供方实例及其配置不变,前缀就保持稳定。适配器目录变化不会改变定义;子级路由覆盖可能使 fork 子 agent 无法复用继承的父级前缀。
142
+
143
+ ### 模型选择与发现
144
+
145
+ #### 模型看到什么
146
+
147
+ Session 携带策略的 settings 控制实例会公开子级 LLM 选择字段与 `list_subagent_models`。可选 `ctx.llm` 服务不可用时,调用会失败。发现只返回精确路由策略中的已注册提供方与已公布模型;未授权提供方会在调用其适配器目录前被拒绝,精确查询也必须先获准,才会解析模型的推理强度与默认值。执行阶段会独立强制同一策略。
148
+
149
+ #### Token 影响
150
+
151
+ 启用的组合中存在一个固定发现 schema。只有模型调用工具时,目录内容才进入 transcript。
39
152
 
40
- 当提供方存在时,以当前实例配置的名称公开已生成的默认 [`subagent` schema](../../../docs/tool-catalog.md#deepseek-aidsh-tool-subagent)。提供方是否继承上下文会改变工具描述和提示词描述。启用后台模式会添加 `run_in_background`:可继续模式会记录其默认值为 `true`、运行时结算通知与显式前台覆盖;一次性模式会记录其默认值为 `false`,以及用 `job_output` 收集或用 `job_kill` 停止的 job id。当工具在本次组装的作用域中可见时,一个 `tool:<toolName>` 系统提示词 section 会指示模型同时启动相互独立的可继续委派、在它们运行时继续工作,并且仅当下一步动作依赖结果时选择前台;工具限制会同时移除其 schema 和这段指引。
153
+ #### KV Cache 影响
154
+
155
+ 适配器注册与目录变化不会改变 schema 前缀。每个发现结果都追加在可复用前缀之后。
156
+
157
+ ### 系统提示词
158
+
159
+ #### 模型看到什么
160
+
161
+ 当 `enableRunInBackground` 与 `backgroundMode: continuable` 同时设置时,模型还会读到 `tool:<toolName>` 系统提示词 section,指示它把相互独立的可继续委派一起启动,并在它们运行时继续工作。使用默认工具名 `subagent` 时,section 文本为:
162
+
163
+ ##### 工具指导 section
164
+
165
+ ```markdown
166
+ Use subagent in the background by default. Start independent delegations together in one assistant message and continue useful work while they run. Set `run_in_background: false` only when your next action depends on that subagent's result. When a background run settles, the runtime sends you a notice containing its outcome and any final assistant message.
167
+ ```
41
168
 
42
169
  #### Token 影响
43
170
 
44
- 每个父级请求都会产生固定的 schema token 开销;每个提供方实例增加一个 schema,每个可继续实例还会增加一个简短的系统提示词 section
171
+ 每个可继续实例一个简短固定 section,只要工具在作用域内,就由每个父级请求支付。
45
172
 
46
173
  #### KV Cache 影响
47
174
 
48
- 只要提供方实例、名称、描述和 schema 不变,前缀就保持稳定。提供方注册生命周期可能从首个变化的工具定义开始,使父级复用失效。
175
+ 只要 section 文本与工具存在性不变,前缀就保持稳定;移除工具或更改 section 会建立不同的父级前缀。
49
176
 
50
177
  ### 前台结果
51
178
 
52
- #### 模型看到的内容
179
+ #### 模型看到什么
53
180
 
54
- 调用会保留描述和提示词。成功时只包含子 agent 的最终文本;其他结果变为 `Error: <message>`。子 agent 中间步骤不会进入父级。
181
+ 调用会保留描述与提示词。成功时只包含子 agent 的最终文本;其他结果变为 `Error: <终止原因>`,随后在存在时附上安全的提供方诊断,再附上任何部分 assistant 文本。子 agent 中间步骤不会进入父级。
55
182
 
56
183
  #### Token 影响
57
184
 
58
- 提示词和结果会留在父级历史中,直到上下文压缩(context compaction);子 agent 工作上下文留在子 agent 中。
185
+ 提示词与结果保留在父级历史中,直到上下文压缩(context compaction);子 agent 工作上下文留在子 agent 中。
59
186
 
60
187
  #### KV Cache 影响
61
188
 
@@ -63,9 +190,9 @@
63
190
 
64
191
  ### 后台结果
65
192
 
66
- #### 模型看到的内容
193
+ #### 模型看到什么
67
194
 
68
- 在配置的可继续模式下,启动时返回内容恰为 `started subagent <childId>`;在配置的一次性模式下,则返回 `started background subagent job <id>`。一次性模式下,通用 Task 接口提供后续状态、最终输出、取消响应和通知。可继续模式下,本工具不返回自己的结果;子 agent 的结算会以[服务负责的通知](../subagent/README.md#settlement-notice)到达父级,独立加载的 `send_message` 工具会投递后续消息,而通过其 id 查看子 agent 的 transcript 即是其详细输出来源。
195
+ 在配置的可继续模式下,启动时返回内容恰为 `started subagent <childId>`;在配置的一次性模式下,则返回 `started background subagent job <id>`。一次性模式下,通用 Task 接口提供后续状态、最终输出、取消响应与通知;若结果携带提供方诊断,失败状态的 detail 会包含它。可继续模式下,本工具不返回自己的结果:子 agent 的结算以服务负责的通知到达父级,独立加载的 `send_message` 工具投递后续消息,而通过其 id 查看子 agent 的 transcript(文本记录)即是其详细输出来源。
69
196
 
70
197
  #### Token 影响
71
198
 
@@ -75,8 +202,24 @@
75
202
 
76
203
  仅追加;新增可见内容位于可复用请求前缀之后,不会使现有 KV Cache 条目失效。
77
204
 
78
- ## 已知限制与暂缓事项
205
+ ## 已知限制与延期工作
206
+
207
+ <a id="known-limitations-and-deferred-work"></a>
208
+
209
+
210
+ 这些限制说明本工具不返回或不强制执行什么;它们是当前包约束。
211
+
212
+ - **后台运行不通过本工具公开结果**——一次性任务的最终输出通过通用 Task 接口收集,可继续子 agent 的输出留在其自身会话中,按其 subagent id 读取。结算通知会说明该子 agent 如何结束,并携带可能存在的最终 assistant 消息,但它不是本次调用的返回值,也无法在此等待。
213
+ - **等待中的一次性实例较晚才发现重复名称**(`TODO(subagent-dup-toolname)`)——可继续实例会在插件应用期间预留提示词 section 名称,但若要阻止等待中的一次性实例回滚提供方注册,仍需要一份预期名称注册表。
214
+ - **随附 fork 工具不能选择子级 LLM 路由**——它们继承父级提供方与模型,使复制的对话前缀仍有资格复用 KV Cache。仅当路由变更能保留复用或公开有界重算成本时,才重新启用选择。
215
+ - **非路由子 agent 策略按实例固定**——另一个 persona、工具过滤器或深度上限需要另一个名称不同的工具。LLM 选择要求启用逐 Session 偏好,且提供方必须声明 `agentOptions`;两个进程内提供方和 DSH SDK 会声明该能力,而 ACP、Codex 与 Claude Code 会拒绝它,而不是忽略它。
216
+
217
+ <a id="dev-note"></a>
218
+ ### 开发备注
219
+
220
+ <details>
221
+ <summary>维护者的工作上下文——点击展开</summary>
222
+
223
+ 无。
79
224
 
80
- - **后台运行不通过本工具公开结果**:一次性任务的最终输出通过通用 Task 接口收集,可继续子 agent 的输出留在其自身会话中,按其 subagent id 读取。结算通知会说明该子 agent 如何结束,并携带可能存在的最终 assistant 消息,但它不是本次调用的返回值,也无法在此等待。
81
- - **等待中的一次性实例较晚才发现重复名称**(`TODO(subagent-dup-toolname)`):可继续实例会在插件应用期间预留提示词 section 名称,但若要阻止等待中的一次性实例回滚提供方注册,仍需要一份预期名称注册表。
82
- - **每个实例的子 agent 策略固定**:其他模型、persona、工具过滤器或深度上限都需要另一个名称不同的工具。
225
+ </details>