# What Is the Agent Client Protocol (ACP) and How OpenCode Implements It

> Learn about the Agent Client Protocol ACP and how OpenCode uses this standardized JSON-RPC protocol to connect AI language models to editors like VS Code.

- Repository: [Anomaly/opencode](https://github.com/anomalyco/opencode)
- Tags: deep-dive
- Published: 2026-02-16

---

**The Agent Client Protocol (ACP) is a standardized JSON-RPC protocol that enables any IDE or editor to act as a client to an AI agent, and OpenCode implements this protocol in `packages/opencode/src/acp/` to expose its language model capabilities to external editors like Zed and VS Code.**

The **Agent Client Protocol (ACP)** defines a common language for editor-agent communication. OpenCode, the open-source AI coding assistant from AnomalyCo, adopts ACP to decouple its core AI capabilities from the user interface, allowing any ACP-compatible editor to drive code generation, tool execution, and session management through a well-defined JSON-RPC contract.

## What Is the Agent Client Protocol (ACP)?

ACP is a **JSON-RPC-based protocol** that standardizes how an editor (client) interacts with an AI agent (server). It specifies requests such as `initialize`, `session/new`, and `session/prompt`, alongside notifications like `session/update`, `tool_call`, and `permission.asked`.

The protocol remains **editor-agnostic**, meaning OpenCode can serve AI assistance to Zed, VS Code, or any future editor implementing the ACP client specification without code changes. According to the source documentation in [`packages/opencode/src/acp/README.md`](https://github.com/anomalyco/opencode/blob/main/packages/opencode/src/acp/README.md), ACP supports streaming responses, tool execution, and granular permission handling while maintaining a strict type contract.

## How OpenCode Implements the Agent Client Protocol

OpenCode’s ACP implementation lives under `packages/opencode/src/acp/` and exposes the project’s internal AI session system through a protocol-compliant server. The architecture separates concerns into focused modules that handle agent logic, session bridging, and transport.

### The ACP Server Architecture

The implementation splits responsibilities across four core components:

- **[`agent.ts`](https://github.com/anomalyco/opencode/blob/main/agent.ts)** – Implements the `Agent` interface from `@agentclientprotocol/sdk`. It handles `initialize` requests, session lifecycle management (`session/new`, `session/load`), and translates between ACP protocol messages and OpenCode’s internal session system. It also manages tool call notifications and permission forwarding.

- **[`session.ts`](https://github.com/anomalyco/opencode/blob/main/session.ts)** – Manages the mapping between ACP session IDs and OpenCode’s native `Session` objects. It preserves working directory context, MCP server configurations, model/variant selection, and mode state across the protocol boundary.

- **[`types.ts`](https://github.com/anomalyco/opencode/blob/main/types.ts)** – Defines TypeScript interfaces for internal session state and configuration objects passed between the ACP layer and OpenCode’s core SDK.

- **[`server.ts`](https://github.com/anomalyco/opencode/blob/main/server.ts)** – Boots the JSON-RPC server using the official ACP SDK’s stdio transport helper, wires the `Agent` implementation, and handles graceful shutdown sequences.

### Starting the ACP Server

OpenCode provides a dedicated CLI command to launch the ACP server, making it available for editor integration:

```bash

# Start ACP server in current project

opencode acp

# Start for a specific directory

opencode acp --cwd /path/to/project

```

The CLI entry point resides in [`packages/opencode/src/cli/cmd/acp.ts`](https://github.com/anomalyco/opencode/blob/main/packages/opencode/src/cli/cmd/acp.ts), which instantiates the `ACPServer` and begins listening on stdin/stdout for JSON-RPC messages.

### Handling ACP Requests

When an editor connects, OpenCode processes the ACP request flow through [`agent.ts`](https://github.com/anomalyco/opencode/blob/main/agent.ts):

1. **Initialization** – The `initialize` request negotiates protocol version 1 and advertises capabilities including session handling, tool support, and permission management.

2. **Session Creation** – The `session/new` request triggers `ACPSessionManager` to spawn a native OpenCode session, storing the working directory and MCP configuration. The agent returns the ACP session ID and available models.

3. **Prompt Processing** – The `session/prompt` request converts ACP content blocks (text, images, resources) into OpenCode’s internal `SessionPrompt` format, dispatches the request to the core SDK, and returns the model’s response via `sessionUpdate` notifications.

### Tool Execution and Permissions

OpenCode bridges its tool system to ACP through event translation:

- **Tool Calls** – When the model invokes tools like `edit`, `bash`, or `webfetch`, [`agent.ts`](https://github.com/anomalyco/opencode/blob/main/agent.ts) emits `sessionUpdate` notifications with `tool_call` and `tool_call_update` types to the client.

- **Permission Handling** – If a tool requires user consent, the agent forwards a `requestPermission` call to the client, queues concurrent permission requests per session, and resumes execution once the user responds. This logic resides in the permission handling blocks of [`agent.ts`](https://github.com/anomalyco/opencode/blob/main/agent.ts).

## Code Examples: Working with ACP in OpenCode

### Starting the Server Programmatically

For testing or custom editor integrations, boot the server directly:

```typescript
import { ACPServer } from "opencode/src/acp/server";

// Boots the JSON-RPC stdio server
await ACPServer.start();

```

### Sending an Initialize Request

A minimal ACP client request to initialize the connection:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": { "protocolVersion": 1 }
}

```

### Creating a New Session

Requesting a session from the OpenCode ACP server:

```typescript
const response = await connection.request("session/new", {
  cwd: "/path/to/project",
  mcpServers: ["filesystem", "github"],
  preferredModel: "claude-3-opus"
});

// Returns: { sessionId: "acp-123", models: [...], modes: [...] }

```

### Sending a Prompt

Dispatching a prompt to an active session:

```typescript
await connection.request("session/prompt", {
  sessionId: "acp-123",
  prompt: [
    { type: "text", text: "Refactor this function to use async/await" }
  ],
  cwd: "/repo"
});

```

### Handling Permission Requests

Example of how the agent requests user permission for sensitive operations:

```typescript
await this.connection.requestPermission({
  sessionId: "acp-123",
  toolCall: {
    toolCallId: "call-456",
    status: "pending",
    title: "edit",
    kind: "edit",
    rawInput: { path: "src/config.ts", content: "..." }
  },
  options: [
    { optionId: "once", kind: "allow_once", name: "Allow once" },
    { optionId: "always", kind: "allow_always", name: "Always allow" }
  ]
});

```

## Summary

- The **Agent Client Protocol (ACP)** is a JSON-RPC specification that standardizes communication between AI agents and editor clients, enabling editor-agnostic AI assistance.
- OpenCode implements a **protocol-compliant ACP server** in `packages/opencode/src/acp/`, exposing its session management, tool execution, and permission systems to external editors.
- The architecture separates concerns across **[`agent.ts`](https://github.com/anomalyco/opencode/blob/main/agent.ts)** (protocol logic), **[`session.ts`](https://github.com/anomalyco/opencode/blob/main/session.ts)** (state bridging), **[`types.ts`](https://github.com/anomalyco/opencode/blob/main/types.ts)** (definitions), and **[`server.ts`](https://github.com/anomalyco/opencode/blob/main/server.ts)** (transport).
- Editors connect via the **`opencode acp`** CLI command, which launches the JSON-RPC server on stdio, allowing clients to create sessions, send prompts, and receive streaming updates.
- OpenCode bridges its native tool system to ACP through **`tool_call`** notifications and handles user permissions via **`requestPermission`** calls, ensuring secure execution of sensitive operations.

## Frequently Asked Questions

### What is the Agent Client Protocol used for?

The Agent Client Protocol (ACP) standardizes how code editors and IDEs communicate with AI coding agents. It defines JSON-RPC methods for initializing connections, creating sessions, sending prompts, and handling tool execution. This allows any ACP-compatible editor—such as Zed or VS Code—to drive AI assistance without requiring editor-specific integrations.

### How do I start the OpenCode ACP server?

Start the server using the OpenCode CLI command `opencode acp` from your project directory. For specific working directories, use the `--cwd` flag: `opencode acp --cwd /path/to/project`. This launches the JSON-RPC server on stdin/stdout, ready to accept connections from ACP clients. The implementation resides in [`packages/opencode/src/cli/cmd/acp.ts`](https://github.com/anomalyco/opencode/blob/main/packages/opencode/src/cli/cmd/acp.ts).

### Which editors support the Agent Client Protocol?

ACP is designed to be editor-agnostic. Currently, editors like **Zed** support ACP through configuration in [`settings.json`](https://github.com/anomalyco/opencode/blob/main/settings.json) by declaring an `agent_server` pointing to the `opencode acp` command. VS Code and other editors can implement ACP clients using the official SDK, allowing them to connect to OpenCode’s agent capabilities through the standardized protocol.

### How does OpenCode handle permissions in ACP?

When a tool requires user consent, OpenCode’s [`agent.ts`](https://github.com/anomalyco/opencode/blob/main/agent.ts) forwards a `requestPermission` call to the client via the ACP connection. The agent queues concurrent permission requests per session to prevent race conditions. Once the user responds through their editor, OpenCode resumes execution. This mechanism ensures that sensitive operations—such as file edits or shell commands—receive explicit user approval before proceeding.