Lesson 10
Agent Client Protocol (ACP)
What ACP Is
The Agent Client Protocol (ACP) is an open standard that standardises communication between code editors and AI coding agents. To understand why this matters, it helps to know about LSP:
A quick detour: LSP (Language Server Protocol)
Before LSP, every editor had to build its own support for every language. TypeScript in VS Code? Someone builds a TS plugin for VS Code. TypeScript in Vim? Someone builds a different TS plugin for Vim. N editors × M languages = N×M integrations to maintain.
LSP fixed this: a "language server" is built once (for TypeScript, Python, etc.) and any editor that speaks the LSP protocol can use it. Now it's N + M - one server per language, one LSP client per editor. You use LSP right now in Kiro - it's how you get autocomplete, go-to-definition, and error highlighting for TypeScript without Kiro needing to understand TypeScript itself.
ACP = LSP, but for AI agents
Same problem, new domain. Before ACP: each AI agent (Kiro, Gemini, etc.) needs custom integration for each editor. After ACP: any agent that implements ACP works in any editor that supports it. One standard, universal compatibility.
Why It Matters
Without ACP, each AI agent needs a custom integration for each editor. With ACP:
- Users - can use their preferred agent in their preferred editor (not locked into one pairing)
- Agent developers - build once, work everywhere (no per-editor integration)
- Editor makers - get AI capabilities from any ACP-compatible agent without building their own
How Kiro Uses ACP
The Kiro CLI implements ACP. This means you can use Kiro's agent in:
- JetBrains IDEs (IntelliJ, WebStorm, PyCharm, etc.) - via the ACP agent registry
- Zed - the editor that co-created ACP
- Neovim, Eclipse, Emacs, Toad - and other ACP-compatible editors
Your steering, skills, hooks, MCP servers, and custom agents all work through ACP - the protocol carries the full Kiro experience, not just chat.
The Protocol at a Glance
ACP uses JSON-RPC over stdio (same transport as MCP). Here's what the messages look like on the wire:
Editor sends a user message to the agent
{
"jsonrpc": "2.0",
"id": 1,
"method": "conversation/sendMessage",
"params": {
"conversationId": "conv-123",
"message": {
"role": "user",
"content": "Refactor UserService to use signals"
},
"context": {
"activeFile": "src/app/services/user.service.ts",
"workspace": "/home/dev/my-angular-app"
}
}
}Agent responds with a file edit
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"messages": [{
"role": "assistant",
"content": "I'll refactor UserService to use signals instead of BehaviorSubjects."
}],
"actions": [{
"type": "editFile",
"path": "src/app/services/user.service.ts",
"edits": [{
"range": { "start": { "line": 5, "character": 0 }, "end": { "line": 12, "character": 1 } },
"newText": " currentUser = signal<User | null>(null);\n"
}]
}]
}
}Agent requests permission to run a command
{
"jsonrpc": "2.0",
"method": "agent/requestPermission",
"params": {
"type": "executeCommand",
"command": "ng lint",
"reason": "Running lint to verify changes"
}
}The editor then shows a permission dialog and responds with approval or denial. All plain text JSON - you could read it directly if you piped the stdio stream to a file.
Key insight: the agent never directly edits files
The AI doesn't touch the filesystem directly for code edits. It sends structured instructions ("edit this range in this file with this text") and the IDE applies them. This is what enables:
- Showing you diffs before applying changes
- Supervised mode's accept/reject per hunk
- Undo history in the editor
- File watchers and formatters running on the result
- Hooks firing (PostFileSave, etc.)
The agent always operates through an intermediary - it's a request/response model, not raw disk access.
execute_bash, that does run directly with your system privileges. The command executes outside the editor's mediation layer. This is why shell commands get permission gates and hooks can block them - there's no "undo" for a shell command.
The protocol handles:
| Capability | What it does |
|---|---|
| Context provision | Editor sends project context (files, workspace, diagnostics) to the agent |
| Rich updates | Agent sends file edits, terminal commands, and UI actions back to the editor |
| Permissions | Editor manages approval flows for file writes, commands, etc. |
| Session management | Handles conversation state, model selection, configuration |
ACP vs MCP
These are complementary, not competing:
| ACP | MCP | |
|---|---|---|
| Direction | Editor ↔ Agent | Agent ↔ External tools |
| Purpose | Connects an agent to an IDE | Connects an agent to external services |
| Who implements | Agents (like Kiro CLI) and editors (like Zed, JetBrains) | Tool providers (GitHub, Jira, databases) |
| Analogy | LSP (editor ↔ language server) | Database drivers (app ↔ database) |
MCP gives the agent tools. ACP gives the agent a home in an editor. Kiro uses both.
Who's Involved
- Zed - co-created the protocol, initial reference implementation
- JetBrains - launched an ACP agent registry for their IDEs
- Kiro CLI - implements ACP so the Kiro agent works in any compatible editor
- Google (Gemini CLI) - initial third-party agent using ACP
- Open spec: agentclientprotocol.com, GitHub repo
When This Becomes Relevant to You
- If you want to use Kiro's agent in WebStorm (JetBrains) for Angular work
- If team members use different editors but you want shared Kiro config (steering, hooks, skills) to work everywhere
- If you want to try Zed but keep your Kiro agent and all its configuration
- If you build a custom agent (Lesson 9) and want it available in multiple editors