ACP is a client protocol, not a control plane
What the Agent Client Protocol standardizes, what it leaves to the host, and how Coding Agent Control Plane composes project, environment, provider, model, and harness before any handshake.
| Resource | Link |
|---|---|
| Protocol | ACP architecture |
| Overview | ACP protocol overview |
| Version boundary | ACP v1 to v2 migration |
| Implementation | coding-agent-control-plane |
| Runtime design | ACP runtime architecture |
| Environment model | Environment domain model |
An ACP connection can be healthy while the coding product around it is unusable.
The agent may accept initialize, create a session, stream updates, and answer a prompt. The editor can still lose the session after a reload, leave a child process running after the window closes, expose the wrong workspace, or have no way to explain why a tool call was denied.
That is not a protocol failure. It is a control-plane failure.
The Agent Client Protocol standardizes communication between a client application and a coding agent. It does not start the executable, choose the repository, resolve a credential, apply an environment policy, or prove that the work is complete. A launcher that pretends otherwise becomes a pile of harness-specific conditionals.
The goal is not to pretend that every coding agent is identical. The goal is one reliable control plane with agent-specific behavior at explicit adapter boundaries.
The protocol boundary
ACP defines two participants. The agent uses generative AI to modify code. The client provides the interface, manages access to resources, and handles user interaction. They communicate through JSON-RPC methods, requests, responses, and notifications.
That boundary is useful because editors and agents can evolve independently. An editor can connect to several agents. An agent can work inside several editors. The protocol carries the interaction contract without forcing either side to adopt the other’s internal architecture.
The protocol is not the same thing as the process that carries it.
| Boundary | Owns | Does not own |
|---|---|---|
| Protocol | Initialization, capabilities, sessions, prompts, updates, cancellation, and permission requests | Process supervision, persistence, retries, or product policy |
| Client | User interface, environment access, resource permissions, and client-side requests | The agent’s model loop or the meaning of its internal plans |
| Runtime host | Process launch, identity, working directory, credentials, restart, shutdown, and logs | Durable product decisions that belong to the application |
| Product control plane | Projects, environments, worlds, audit records, recovery policy, and completion evidence | Agent-specific wire details that belong in an adapter |
The exact names vary by product. The separation does not.
What ACP gives — and what it does not
The protocol gives a client a standard conversation surface. A typical connection negotiates capabilities, creates or loads a session, sends a prompt, receives progress notifications, handles permission requests, and cancels the active turn when needed.
The client can use those messages to build an editor, terminal, desktop application, or browser interface. It can render text, file changes, tool activity, permission prompts, and session progress without knowing how the agent implements its model loop.
The client also remains an active participant. ACP is not a one-way stream from an agent to a display. In ACP v1, an agent can ask the client to read or write a file and create or use a terminal. ACP v2 removes those client methods in favor of client-provided MCP servers. Permission requests remain part of the interaction. Every version still crosses a trust boundary that needs a policy decision on the client side.
An ACP implementation still needs answers the wire contract cannot give:
| Question | Why the protocol alone cannot answer it |
|---|---|
| Which executable should start? | A protocol describes messages, not installation discovery or executable selection. |
| Which repository is exposed? | The client must resolve and validate the working directory before launch. |
| Where do credentials come from? | Authentication and secret storage depend on the host environment and provider. |
| Who owns the child process? | A connection can close while a subprocess continues running. |
| What survives a reload? | Session loading is only useful if the product stores an identity and can find the agent again. |
| Which tools are allowed? | Capabilities do not replace sandboxing, approval rules, or resource policy. |
| When is the task complete? | A final protocol response is not proof that tests passed or the requested artifact exists. |
Treating ACP as the runtime creates predictable bugs. A connection object becomes a session database. A subprocess becomes a workspace manager. A stream of updates becomes an audit log. None of those substitutions are safe.
Compose the session before the handshake
Coding Agent Control Plane is the desktop product that owns that composition. A coding session is not “start Claude.” It is an explicit combination assembled before any ACP message is sent:
Coding session
= project
+ environment
+ LLM provider
+ model
+ coding-agent harness
The user selects the combination. The application resolves the working directory, provider route, model policy, agent command, permissions, tools, and credential references needed to start. Claude Code, Codex, Grok Build, and OpenCode remain interchangeable harnesses, not the product’s domain model.

An environment is the primary runtime context: where the work happens and which working directories apply. A project groups the work. A world is separate — an operator-authored catalog of approved providers and harnesses. Exactly one world is active. World descriptors never contain raw secrets.
| Portable core | Agent adapter |
|---|---|
| Project, environment, and world identity | CLI flags, argv, and configuration files |
| Session lifecycle | Agent-specific session creation and resume calls |
| Prompt turn and cancellation | Wire messages on the ACP byte pipe |
| Permission request | Agent-specific permission schema and tool names |
| Event timeline | Stream parsing and dialect normalization |
| Completion evidence | Agent result fields and host-side verification |
| Agent capabilities | Version-specific feature negotiation |
The core answers “what is happening?” The adapter answers “how does this agent express it?”
Separate launch from connection
Launching an agent and connecting to an agent are different phases.
The control plane first resolves the harness descriptor, validates the workspace, prepares credentials, creates a child process, and records the process identity. Only then does the protocol client negotiate a connection and create a session.
| Phase | Success means | A failure usually means |
|---|---|---|
| Discover | The executable and adapter are known | Installation or registry problem |
| Validate | Workspace, credentials, and policy are acceptable | Configuration or authorization problem |
| Launch | The child process started with the expected identity | Spawn, path, or environment problem |
| Handshake | The agent and client negotiated capabilities | Protocol or version problem |
| Create session | A durable conversation can begin | Agent-side session problem |
| Run turn | Progress and requests are flowing | Provider, tool, or permission problem |
| Verify | The requested outcome has evidence | Task or validation problem |
Without these phases, every failure becomes “the agent did not work.” That message is operationally useless.
Agents resolve from PATH and are never bundled into the signed application. An approved harness that is not installed stays visible with an explanation. A descriptor in the world catalog is not a license to hide the gap: resume: false must remain visible. A host-managed login flow must not be represented as an environment variable just because another agent uses one.
Keep the host a byte pipe
A useful architecture keeps the ACP client next to the UI and the process supervisor next to the operating system.
| Layer | Responsibility | Why it stays separate |
|---|---|---|
| React WebView | ACP sessions, streaming messages, plans, permissions, cancellation, and product UI | Protocol state stays next to the interface that presents and controls it |
| Native host | Agent discovery, process lifecycle, Keychain access, security checks, and lossless byte transport | The host supervises the executable without becoming a second ACP peer |
| World and environment model | Approved providers, models, harnesses, permissions, plugins, Skills, and MCP connections | Launch policy remains explicit and reproducible across projects |
| Services | Provider routing, plugin catalogs, MCP aggregation, updates, and harness evaluation | Supporting infrastructure evolves without expanding the protocol adapter |
In the repository, apps/native-host/src/acp.zig starts an agent and moves bytes. It does not interpret JSON-RPC. apps/web-ui/src/lib/acp owns the conversation protocol, including a dual-stack client that prefers ACP v2 and still accepts v1. Raw credentials remain in the macOS Keychain and are resolved only for an approved launch path.
The native host never implements ACP fs or terminal execution APIs. The WebView negotiates the protocol dialect, while file and terminal execution stay outside the native byte pipe. That separation also matches ACP v2, which replaces the v1 client methods with client-provided MCP servers.
Where failures actually appear
The most confusing failures happen when a healthy protocol connection is mistaken for a healthy product.
The agent connects but the UI is empty
The connection may be streaming updates into a handler that is not attached to the active session. The protocol works; the product lost event ownership.
The session disappears after reload
The client kept an in-memory connection but never persisted the session identity, workspace, or harness descriptor. ACP may support loading a session, but the application still has to know what to load and where.
The window closes but the agent keeps running
The UI lifecycle and process lifecycle are detached. A runtime supervisor needs explicit ownership, shutdown, and orphan cleanup.
The agent finishes but the task is not done
The protocol returned a stop reason. The product still needs verification: tests, artifact checks, repository state, or an evaluation result.
The right abstraction boundary
The control plane should make these decisions once:
- how a user selects a project and environment
- which world of providers and harnesses is active
- how credentials and permissions are governed
- how sessions are identified and recovered
- how processes are supervised and cleaned up
- how failures become actionable states
The adapter should make these decisions locally:
- how to invoke the agent
- how to negotiate its protocol dialect
- how to translate prompts and events
- how to map its capabilities
- how to close its connection safely
ACP makes the protocol seam portable. The control plane makes the product dependable.
Takeaways
ACP standardizes communication
It gives clients and coding agents a shared interaction contract. It does not define launch, workspace, credentials, or completion evidence.
Compose before handshake
Project, environment, provider, model, and harness are product decisions. The protocol starts after those are resolved.
Keep the host a byte pipe
Discover, spawn, and transport without becoming a second ACP peer. Protocol state belongs next to the UI that presents it.
Agent-agnostic does not mean agent-identical
A control plane should expose capability differences instead of hiding them behind the lowest common denominator.