ACP Integration

Agent Client Protocol — use otto as a headless AI agent in any editor.

What is ACP?

The Agent Client Protocol is an open protocol (Apache 2.0) created by Zed Industries that standardizes communication between code editors (Clients) and AI coding agents (Agents). Think of it as “LSP but for AI agents.”

  • Protocol: JSON-RPC 2.0 over stdio
  • Version: 1 (integer-based, only bumped on breaking changes)
  • SDK: @agentclientprotocol/sdk on npm
  • No TUI required — the editor provides the entire UI

How It Works

Otto runs as a headless subprocess that communicates with the editor via JSON-RPC over stdin/stdout. The editor handles all UI rendering including messages, diffs, tool calls, permission prompts, and terminal management.

┌──────────────────────┐      stdio (JSON-RPC)      ┌──────────────────────┐
│      Client          │ ─────────────────────────▶ │      Agent           │
│  (Zed, JetBrains,   │ ◀───────────────────────── │  (otto)              │
│   Neovim, VS Code)  │                            │                      │
│                      │                            │  - Calls LLMs        │
│  - UI rendering      │                            │  - Runs tools        │
│  - File system       │                            │  - Sends updates     │
│  - Terminal mgmt     │                            │  - Requests perms    │
│  - Permission prompts│                            │                      │
└──────────────────────┘                            └──────────────────────┘

Supported Editors

EditorSupport
ZedNative (primary)
JetBrains IDEsNative
NeovimCodeCompanion, agentic.nvim, avante.nvim
VS CodeACP Client extension
Emacsagent-shell.el

Protocol Flow

1. Initialization

The client spawns otto as a subprocess and sends initialize with protocol version, client capabilities, and client info. Otto responds with its agent capabilities, info, and authentication methods.

2. Authentication

If otto requires authentication (API keys, OAuth), the client calls authenticate.

3. Session Setup

The client calls session/new with the working directory and optional MCP server configurations. Otto responds with a session ID, available models, and available modes.

4. Prompt Turn

  1. Client sends session/prompt with user message (text, images, files)
  2. Otto streams back via session/update notifications:
    • agent_message_chunk — text responses
    • agent_thought_chunk — reasoning
    • tool_call / tool_call_update — tool invocations and progress
    • plan — TODO list entries
  3. Otto may call client methods like fs/read_text_file, fs/write_text_file, terminal/create, and session/request_permission
  4. Turn ends with session/prompt response containing a stopReason

5. Cancellation

The client sends session/cancel; otto stops and responds with a cancelled stop reason.

Package Structure

packages/acp/
├── package.json          # @ottocode/acp
├── src/
│   ├── index.ts          # CLI entry point (stdio setup)
│   ├── agent.ts          # OttoAcpAgent implements Agent
│   └── utils.ts          # Helpers
└── tsconfig.json

Usage

Option A: ACP Registry

The preferred distribution method. Once registered, otto becomes available in Zed, JetBrains, and all ACP-compatible clients with one-click install and auto-updates.

Option B: Manual Configuration

Add otto as a custom agent in your editor settings. For example, in Zed’s settings.json:

{
  "agent_servers": {
    "Otto": {
      "type": "custom",
      "command": "otto",
      "args": ["--acp"],
      "env": {}
    }
  }
}

Implementation Details

  • stdio transport: stdout is reserved for JSON-RPC messages only — all logging goes to stderr
  • File operations: When the client supports fs.readTextFile / fs.writeTextFile, otto delegates file I/O through the editor for better UX (inline diffs, etc.)
  • Terminal operations: Delegated to the client when terminal capability is present
  • MCP support: Connects to MCP servers provided by the client during session setup
  • Tool permissions: Uses client.requestPermission() before executing destructive operations

Dependencies

{
  "@agentclientprotocol/sdk": "0.14.1"
}

The SDK handles JSON-RPC framing, message types, and transport. Everything else is powered by otto’s existing SDK and server infrastructure.