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/sdkon 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
| Editor | Support |
|---|---|
| Zed | Native (primary) |
| JetBrains IDEs | Native |
| Neovim | CodeCompanion, agentic.nvim, avante.nvim |
| VS Code | ACP Client extension |
| Emacs | agent-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
- Client sends
session/promptwith user message (text, images, files) - Otto streams back via
session/updatenotifications:agent_message_chunk— text responsesagent_thought_chunk— reasoningtool_call/tool_call_update— tool invocations and progressplan— TODO list entries
- Otto may call client methods like
fs/read_text_file,fs/write_text_file,terminal/create, andsession/request_permission - Turn ends with
session/promptresponse containing astopReason
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.jsonUsage
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
terminalcapability 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.