Skip to content

Agent Client Protocol (ACP) is a JSON-RPC-based protocol for talking to agent runtimes. dsh ships an automation-only ACP server (packages/acp/acp) over JSON-RPC stdio: programmatic clients create fresh harness agents, send text/image prompts, collect committed assistant text/images, resolve one-shot permission requests by policy, and cancel work. The primary in-repository client is dsh-subagent-acp (see Subagents).

PackageRole
@deepseek-ai/dsh-acpACP server plugin over JSON-RPC stdio
@deepseek-ai/dsh-subagent-acpACP-backed subagent transport

What this package is (and is not) ​

From packages/acp/acp/README.md: this package is a transport adapter, not a UI integration or a capability seam. It does not expose editor navigation, transcript replay, commands, modes, configuration pickers, elicitation, reasoning, plans, titles, or tool presentation — interactive rendering and human questions belong to the Web host and client modules. The server's surface is deliberately small: the automation contract only.

Plugin and configuration ​

apply(ctx, config) opens an AgentSideConnection on stdin/stdout and drives ctx.agents. Stdout is reserved for protocol frames.

ConfigDefaultMeaning
provider—Initial provider route for every created agent
model—Initial model for every created agent

Both fields are optional so another agent/request listener may supply the target; the runnable ACP composition requires both.

Protocol contract ​

MethodBehavior
initializeNegotiates the supported version. Advertises mcpCapabilities: { http: true }, sessionCapabilities: { close, list, resume }, and image prompts only when a durable attachment store is mounted and the configured exact provider/model resolves with explicit image input; audio and embedded context stay false. No editor, terminal, or filesystem capability is advertised.
authenticateNo-op, because the server advertises no authentication methods.
(task methods)Fresh agents per task, ordered text/image prompts in, committed assistant text/image chunks out, one-shot permission requests resolved by policy, cancellation supported.

Image prompts are durable end-to-end: the bridge admits only raster formats (PNG, JPEG, WebP, GIF), validates the whole image batch and rechecks the session's latest exact route before saving anything, commits every image before the user event, and discards the inline base64 so the durable message holds only verified attachment references. Committed assistant images are re-read and integrity-verified before inline base64 delivery. Admission failures (unsupported mime, non-canonical base64, a model without image input) reject as invalid params; store or route-verification failures report an internal error. Audio and embedded-context input are always rejected.

The implementation lives in packages/acp/acp/src/ — index.ts (the plugin, connection loop, method dispatch), codec.ts (JSON-RPC frame codec over stdio), and invariant.ts (its invariant companion, per the repo's per-package invariant convention).

The consumer: dsh-subagent-acp ​

The ACP server is not a standalone product surface; inside dsh it is the backend of the acp subagent transport. When an agent spawns a subagent through ctx.subagents with the ACP transport, dsh-subagent-acp launches the ACP server (a fresh harness agent inside a child process speaking ACP over stdio) and proxies the delegation through it — giving the subagent an isolated process boundary while keeping the uniform subagent API (see Subagents for the transport matrix: spawn, fork, acp, codex/claude-code/dsh-sdk).

The runnable application ​

The top-level examples/acp-agent and packages/examples/acp-demo were retired when upstream removed the top-level examples/ tree (commit 4125514a08). The ACP application is now a shipped bundle, packages/bundle/acp-app — run it with dsh --profile acp:

PathRole
packages/bundle/acp-appThe automation-only ACP stdio application over dsh-base; mounts the ACP bridge
apps/cli/tests/profiles/acp/The profile-level ACP tests (the former examples/acp-agent test suite)

Session controls, model options, and MCP mounts ​

Beyond the task methods, the server surface has grown since the demo era. The implementation is split across packages/acp/acp/src/:

FileWhat it owns
index.tsPlugin, AgentSideConnection, method dispatch
codec.tsJSON-RPC frame codec over stdio
model-control.tssetSessionConfigOption — per-session model route/options control (methods.agent.session.setConfigOption)
mcp.tsMCP mounts advertised through mcpCapabilities: { http: true }
session.tssession/close, session/list, session/resume implementations
updates.tsLive updates pushed to the client
invariant.tsThe per-package invariant companion

Key source files ​

Repo-relative pathWhat it provides
packages/acp/acp/src/index.tsPlugin, AgentSideConnection, method dispatch
packages/acp/acp/src/{model-control,mcp,session,updates}.tsSession options, MCP mounts, session lifecycle, live updates
packages/acp/acp/src/codec.tsJSON-RPC frame codec
packages/subagent/subagent-acp/src/The ACP subagent transport
packages/bundle/acp-app/The runnable ACP application (dsh --profile acp)

Further reading ​

  • Subagents — the transport matrix and dsh-subagent-acp
  • SDK Protocol — dsh's other JSON-RPC wire, for comparison
  • Examples & Demos — how to run acp-app via dsh --profile acp
  • Repo: packages/acp/acp/README.md, packages/subagent/subagent-acp/README.md