docs: address model experience review
This commit is contained in:
@@ -14,12 +14,6 @@ This package is the interface third of the capability seam, split so each concer
|
||||
|
||||
Unlike the bash seam (one executor per context, second load throws), **multiple providers coexist** here. Each registers under a unique name and a caller picks one by name — the shape mirrors the LLM adapter registry (`LlmService.registerAdapter`), not the single-service bash executor. This is the requirement that rules out the bash shape: an agent may want an in-process child for a cheap subtask and an out-of-process ACP child for an isolated one, in the same runtime.
|
||||
|
||||
## Model Experience
|
||||
|
||||
| Context surface | What the model sees | Token effect |
|
||||
|---|---|---|
|
||||
| None directly | The provider registry registers no prompt or tool. Provider lifecycle makes a bound `dsh-tool-subagent` schema appear or disappear, and `inheritsParentContext` selects truthful fresh-versus-fork wording. Run events are observe-only. | Zero direct tokens. Child prompts and final results enter model contexts only through a provider and consumer. |
|
||||
|
||||
## Service API (`ctx.subagents`)
|
||||
|
||||
| Member | Semantics |
|
||||
@@ -42,6 +36,12 @@ Beside `capabilities` sits one DESCRIPTIVE fact, not validated by the service: `
|
||||
|
||||
The service also announces provider lifecycle: `subagent/provider-added` (the frozen registry snapshot) fires after a registration and `subagent/provider-removed` (the accepted name) after an unregistration, so a consumer deriving state from a named provider (the model-facing tool wording) mirrors registry membership instead of assuming load order — the cordis Loader starts sibling plugins concurrently, so "listed earlier" does not mean "registered earlier". Run lifecycle is gated by provider readiness: `subagent/start` (payload `SubagentRunInfo`) fires only after `run.started` fulfills, and `subagent/end` (payload `SubagentRunEndInfo`) fires only for that announced run; readiness rejection emits neither. For spawn/fork, the start listener can resolve the published child via `ctx.agents.get(info.id)`; a remote provider need not have a local registry entry. Both events are **observe-only** plain emits. The service observes `result` immediately even while readiness is pending, clones its output before the caller can mutate it, and buffers that end payload until start has fired; a rejecting result cannot become an unhandled detached promise, start always precedes end, and a listener cannot corrupt the caller's result. `subagent/end` carries the cloned output as `lastAssistantMessage` on the settle path and omits it on infrastructure rejection. Any run-affecting decision is out of scope for this observe-only surface.
|
||||
|
||||
## Model Experience
|
||||
|
||||
| Context surface | What the model sees | Token effect |
|
||||
|---|---|---|
|
||||
| None directly | The provider registry registers no prompt or tool. Provider lifecycle makes a bound `dsh-tool-subagent` schema appear or disappear, and `inheritsParentContext` selects truthful fresh-versus-fork wording. Run events are observe-only. | Zero direct tokens. Child prompts and final results enter model contexts only through a provider and consumer. |
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **The consumer collects synchronously** — it starts a run and awaits `result`; steering (`sendMessage`) is part of the contract but intentionally unused, and background / poll / spill semantics are deferred to a future redesign unifying long-running-tool handling across subagents and bash ([the seam RFC](../../../docs/rfc/implemented/feature/2026-06-21-subagent-capability-seam.md)).
|
||||
|
||||
Reference in New Issue
Block a user