Implement the continuable background subagents RFC: a durable child session with a series of Task-backed activations, each disposing its run before the Task settles. - dsh-subagent: rename SubagentRun.sendMessage to strict steer, drop run-level resume, add SubagentProvider.resume dispatch via SubagentService.resume, the continuation start field, and the versioned model-hidden subagent/descriptor session event. - dsh-subagent-inprocess/-spawn/-fork: publish the control-allocated child id, append the descriptor inside the initial turn, implement cold resume from the child's own transcript under the live parent scope, and strict running-only steer. - dsh-subagent-control (new): SubagentControlService owning stable child ids, descriptor snapshot/fold/authorization, Task-backed activation with settle-then-dispose ordering, the process-local active-run association, and steer-or-resume sendMessage routing. - dsh-tool-subagent: background route branches on the provider's resume capability (continuable via the control service; one-shot task for ACP), returning both child and task ids. - dsh-tool-subagent-control (new): the globally named send_message tool rendering steered/started routes. Keyless coverage spans Task ownership and disposal ordering, running delivery, cold follow-up, descriptor rejection and rollback, known-id reconstruction, kill during lookup, admission races, and a new subagent-continuable ACP snapshot scenario.
acp-agent example
English | 中文
Automation-oriented Agent Client Protocol server over JSON-RPC stdio. It is intended for parent agents, subagent providers, and other programmatic clients, not as the product UI.
pnpm run demo:acp # needs DEEPSEEK_API_KEY (repo-root .env or env)
pnpm run demo:code-mode # same protocol with the Code Mode tool transport
The leaf loads the ACP app, DeepSeek adapter, sandboxed bash and filesystem stacks, one-shot approval policy, compaction, subagents, workflows, hooks, a derived session-query index, and repeat guard. The app creates one fresh agent per session/new, persists sessions to JSONL, and keeps stdout protocol-pure. session-query.cordis.yml explicitly opts into the workspace-authorized query tools and generic timeout/spill policies for their dedicated snapshot; fs.cordis.yml adds spill storage for filesystem scenarios, code-mode.cordis.yml adds run_code and its generated TypeScript SDK, and web.cordis.yml adds the web seam, the local fetch provider, web_fetch, and a loopback HTML fixture server for the web-fetch snapshot.
Protocol channel
Stdout carries only newline-delimited ACP JSON-RPC. @deepseek-ai/dsh-acp-demo installs no stdout logger; leaf additions must use stderr for diagnostics.
The automation contract — supported methods, baseline prompt content, committed-text output, and the intentionally absent UI surfaces — lives in @deepseek-ai/dsh-acp.
Session workspaces and permissions
Each session/new supplies an absolute cwd. Sandboxed bash and filesystem mutations resolve workspace-write against that session cwd, so concurrent sessions can use separate project roots; platform temporary roots remain shared writable scratch space (sandbox contract). DSH_PERMISSION_MODE selects workspace-write or danger-full-access for deployment and tests.
Under workspace-write, a model retry requesting wider sandbox access triggers session/request_permission with allow_once and reject_once. The client decides programmatically; dismissal or an unavailable answer fails closed. The selected outcome applies only to that retry and is recorded through the normal tool-result/audit path. The server never exposes a permission picker or persists client policy.
Snapshot tests
This example owns the ACP snapshot suite. It boots the real automation server, replays committed model streams through dsh-llm-replay, and compares both normalized protocol output and re-persisted session logs. Recording uses the real model; refresh reuses committed replay input. Overrides cover throw/hang behavior, and optional workspace/ fixtures seed world-state checks.
Most scenarios pin backend behavior rather than ACP-specific behavior; the automation-only ACP decision owns why that coverage remains transport-coupled.