This note documents the preferred integration shape for a new Open Design agent runtime.
New agent runtimes should expose an ACP over stdio CLI mode.
In practice, Open Design expects to spawn a local executable and speak JSON-RPC over the child process streams:
Open Design daemon
ββ spawn your-agent acp
ββ stdin <- ACP JSON-RPC requests/responses
ββ stdout -> ACP JSON-RPC responses/notifications
ββ stderr -> logs and diagnostics only
If the runtime's real implementation is a local or remote server, keep that detail behind a thin CLI wrapper:
your-agent acp
ββ connects to your runtime server / SDK / model backend
That wrapper keeps Open Design on the standard ACP subprocess transport and avoids requiring a daemon-side network transport adapter.
The ACP protocol uses JSON-RPC, but transport matters.
The ACP transport documentation defines stdio as communication over standard input and standard output. In that transport, the client launches the agent as a subprocess, the agent reads from stdin, writes protocol messages to stdout, and writes logs to stderr.
ACP's remote HTTP/WebSocket transport is still described as a draft/proposal rather than the established compatibility path. Open Design's implemented ACP adapters therefore use stdio subprocesses today.
For streamFormat: 'acp-json-rpc', Open Design currently drives a session with these JSON-RPC methods:
initialize- Sent first.
- Includes Open Design client metadata and
clientCapabilities.
session/neworsession/load- Creates a working session, or resumes the durable upstream session from a prior turn when Open Design has a saved session handle.
- Includes the project working directory.
session/newmay include MCP server descriptors when the runtime is allowed to use Open Design-provided tools.
session/set_config_optionorsession/set_model(optional)- Sent when the user selected a non-default model.
- Open Design prefers
session/set_config_optionwhensession/newreports a model config option; otherwise it falls back tosession/set_model.
session/prompt- Sends the composed user/system prompt as a text block, followed by
resource_linkblocks for staged image attachments when present. - A successful response marks the prompt as complete.
- Sends the composed user/system prompt as a text block, followed by
session/cancel- Sent on user cancellation when a session exists and stdin is still writable.
The runtime should support the corresponding JSON-RPC responses and notifications:
- Response to
initialize. - Response to
session/neworsession/load.- Must include a usable
sessionId. - A new session may also return the durable upstream session handle that Open Design records for the next turn.
- Should report the current model if available.
- Should report model config options if model selection is supported through config options.
- Must include a usable
- Notifications using
session/update.- Open Design currently maps:
agent_thought_chunkto thinking output.agent_message_chunkto assistant text output.tool_callandtool_call_updateto tool-use/result events, including artifact-write accounting when the update carries a real file path.- Other update kinds to bounded status/diagnostic events.
- Open Design currently maps:
- Optional
session/request_permissionrequests.- Open Design auto-selects an approve/allow-style option when available.
- If no acceptable option is present, the turn fails fast.
- Response to
session/prompt.- Should include usage metadata when available.
- This response tells Open Design the turn is finished.
- Keep protocol messages on
stdoutparseable as JSON-RPC lines. - Write human-readable logs and diagnostics to
stderr. - Return clear JSON-RPC errors for protocol failures.
- After
session/promptcompletes, either exit cleanly when stdin closes or tolerate Open Design sendingSIGTERMafter a short grace period. - Implement
session/cancelif possible. Open Design falls back to process termination when the transport is no longer usable. - Avoid interactive terminal prompts. If permission is required, use ACP permission requests instead.
An ACP runtime definition in Open Design is intentionally small:
export const myAgentDef = {
id: 'my-agent',
name: 'My Agent',
bin: 'my-agent',
versionArgs: ['--version'],
fallbackModels: [{ id: 'default', label: 'default' }],
buildArgs: () => ['acp'],
streamFormat: 'acp-json-rpc',
} satisfies RuntimeAgentDef;Current examples include AMR, Devin, Hermes, Kimi, Kiro, Kilo, Reasonix, Trae CLI,
and Vibe runtime definitions under apps/daemon/src/runtimes/defs/.
- ACP transport documentation: https://agentclientprotocol.com/protocol/transports
- ACP uses JSON-RPC.
- The stdio transport uses standard input and standard output.
- In stdio mode, the client launches the agent as a subprocess.
- The agent reads from
stdin, writes protocol messages tostdout, and usesstderrfor logs.
- ACP remote transport RFD: https://agentclientprotocol.com/rfds/streamable-http-websocket-transport
- Describes Streamable HTTP / WebSocket as the proposed remote transport direction.
- Notes that ACP's standard transport has historically been stdio and that a standard remote transport is still being defined.
- Open Design implementation:
apps/daemon/src/agent-protocol/acp/session.tsimplements the ACP JSON-RPC session lifecycle and is exposed throughapps/daemon/src/agent-protocol/index.ts.apps/daemon/src/server.tsspawns ACP runtimes as child processes with piped stdio.apps/daemon/src/runtimes/defs/*.tscontains existing ACP runtime definitions usingstreamFormat: 'acp-json-rpc'.