# ACP · 让 grok 当编辑器的后端

> 同一个 agent 内核，除了 TUI，还能被 Zed、Neovim 等编辑器当后端驱动——靠 ACP（Agent Client Protocol）。这一章看 xai-acp-lib 的类型化封装、四种传输如何汇入同一个 MvpAgent，以及 leader 模式怎么让多客户端共享一个后端、崩了还能重放恢复。

- 作者：David（道雾轩）
- 专栏：Grok Build 源码解读（https://daiw.org/manual/grok-build.md）
- 最后更新：2026-09-13
- 原文：https://daiw.org/manual/grok-build/acp
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# ACP · 让 grok 当编辑器的后端

grok 的三种运行形态里，最有意思的是**当编辑器后端**——Zed、Neovim、Emacs 直接驱动 grok 的 agent 内核。靠的是 **ACP(Agent Client Protocol)**。

## 一层类型化封装，多种传输

`xai-acp-lib` 是对 `agent-client-protocol` crate 的**传输无关**类型化封装。它把消息分成两向：

- **`AcpAgentMessage`**(发给 agent):`Initialize` / `NewSession` / `Prompt` / `Cancel` / …
- **`AcpClientMessage`**(发给客户端)：`RequestPermission` / `ReadTextFile` / `SessionNotification` / …

一个 `AcpGatewaySender/Receiver` 把消息转到真正的 ACP 连接上。关键设计：**`session_notification` 是 fire-and-forget**(发了不等 ACK)——因为一旦某个中继 WebSocket 半死不活，阻塞等 ACK 会把整个流式循环冻住。

协议本身是 JSON-RPC 2.0，生命周期：`initialize` → `session/new` → `session/prompt` → 流式 `session/update`(`agent_message_chunk`/`tool_call`/…)。grok 还扩展了一堆 `x.ai/*` 方法(文件、git、终端、rewind、worktree……)。

## 四种传输，同一个 MvpAgent

漂亮的地方：**stdio、WS-serve、WS-relay、leader 四种传输，全汇入同一个 `MvpAgent`**(它 `impl acp::Agent`):

| 传输 | 命令 | 场景 |
| --- | --- | --- |
| **stdio** | `grok agent stdio` | 编辑器集成(主路径) |
| **WS serve** | `grok agent serve` | 起个 WebSocket 服务，一个 MvpAgent 复用于所有重连 |
| **WS relay** | headless | 经 grok.com 中继的无头自动化 |
| **leader** | `grok agent leader` | 多客户端**共享**一个后端进程 |

```mermaid
flowchart LR
  ED[编辑器 stdio] --> GW[GatewaySender]
  WS[WebSocket] --> GW
  LD[leader Unix socket] --> GW
  GW --> MA["MvpAgent (impl acp::Agent)"]
  MA --> S[Part 1 的 SessionActor]
```

## leader 模式：共享后端 + 崩溃重放

`leader` 是个精巧的模式：**一个共享的 `MvpAgent` 进程**(持 `~/.grok/…sock` 锁)，多个客户端把原始 JSON 桥接过 Unix socket。妙在**崩溃恢复**：leader 挂了，客户端 `reconnect` 后走一个**重放状态机**——缓存过 `initialize` 和每个 `session/load` 请求，重连后**顺序重放**它们(转发重放出的 `session/update`、只吞掉重放的响应)，再发 `x.ai/leader_reconnected`。于是 leader 换新二进制自更新、或崩溃，客户端**几乎无感**。

<Callout type="info">
  一个连贯的设计哲学：整套 ACP 是**传输无关**的——协议逻辑写一遍，stdio / WebSocket / Unix socket 都复用。这和[工具协议](https://daiw.org/manual/grok-build/tool-protocol)的「一套契约、两种传输」、[采样器](https://daiw.org/manual/grok-build/custom-models)的「URL-agnostic」是同一种思维：**把协议和传输解耦**，是 grok 反复出现的架构主线。
</Callout>

## 和《从 LLM 到 Coding Agent》对照

那本的 agent 是自成一体的 CLI，不考虑「被别的程序当后端」。grok 的增量是把 agent 内核抽象到一个协议后面(ACP)，于是同一个大脑能长在 TUI 里、也能长在 Zed 里、还能一个后端服务多个前端。这是「从一个工具，到一个可嵌入的 agent 运行时」的跨越。下一章看它怎么并行跑后台任务。

---

上一篇：[Headless 模式](https://daiw.org/manual/grok-build/headless) · 下一篇：[后台任务、loop 与 monitor](https://daiw.org/manual/grok-build/background-tasks)
