# ACP (Agent Client Protocol) 协议详细描述文档 > 基于 `vscode-acp` 项目源码分析提取,SDK 版本:`@agentclientprotocol/sdk ^0.21.1` --- ## 1. 协议概述 ACP (Agent Client Protocol) 是一种用于 **AI 编程代理(Agent)与客户端(Client/IDE)之间通信** 的标准化协议。它定义了客户端如何启动、管理和与 AI 代理交互的完整生命周期,类似于 LSP (Language Server Protocol) 的设计理念,但专门面向 AI 代理场景。 ### 1.1 核心设计理念 - **进程隔离**:Agent 以独立子进程方式运行,通过 stdin/stdout 与客户端通信 - **协议版本化**:每次连接通过 `initialize` 握手交换 `protocolVersion` - **能力协商**:客户端和代理通过初始化阶段声明各自支持的能力 - **会话管理**:支持创建、加载、恢复、列举会话 - **双向通信**:代理可以向客户端发起请求(如文件读写、终端操作、权限请求) ### 1.2 传输层 | 属性 | 描述 | | ---------- | --------------------------------------------------------------------------- | | 传输方式 | 子进程的 stdin(写入)/ stdout(读取) | | 序列化格式 | **ND-JSON**(Newline Delimited JSON) | | 流适配 | Node.js Stream → Web Streams API (`ReadableStream` / `WritableStream`) | | SDK 入口 | `ndJsonStream(writable, readable)` 创建双向流 | --- ## 2. 连接生命周期 ### 2.1 Agent 进程启动 ``` Client Agent Process | | |--- spawn(command, args, {stdio: pipe}) --------->| | | |<========= stdin/stdout pipe established ========>| ``` Agent 配置结构: ```typescript interface AgentConfigEntry { command: string; // 启动命令,如 "npx" args?: string[]; // 命令行参数 env?: Record; // 环境变量 displayName?: string; // 显示名称 } ``` ### 2.2 初始化握手(Initialize) 连接建立后,客户端必须发送 `initialize` 请求: **请求方向**:Client → Agent ```typescript // 客户端发送的初始化参数 { protocolVersion: PROTOCOL_VERSION, // 协议版本号 clientInfo: { name: 'vscode-acp-client', // 客户端名称 version: '0.2.0', // 客户端版本 }, clientCapabilities: { fs: { readTextFile: true, // 支持文件读取 writeTextFile: true, // 支持文件写入 }, terminal: true, // 支持终端操作 }, } ``` **响应结构** (`InitializeResponse`): ```typescript interface InitializeResponse { agentInfo?: { name: string; // Agent 名称 title?: string; // Agent 显示标题 version?: string; // Agent 版本 }; agentCapabilities?: AgentCapabilities; // Agent 能力声明 authMethods?: AuthMethod[]; // 支持的认证方式 } interface AgentCapabilities { sessionCapabilities?: { list?: boolean; // 是否支持 session/list resume?: boolean; // 是否支持 session/resume }; loadSession?: boolean; // 是否支持 session/load } interface AuthMethod { id: string; // 认证方式 ID name: string; // 认证方式名称 description?: string; // 认证方式描述 } ``` ### 2.3 认证流程(Authentication) 当 Agent 需要认证时(错误码 `-32000`),客户端启动认证流程: ``` Client Agent | | |-- newSession() ------------------->| |<-- Error: auth required (-32000) --| | | |-- authenticate({methodId}) ------->| |<-- success ------------------------| | | |-- newSession() (retry) ----------->| |<-- NewSessionResponse -------------| ``` 认证请求: ```typescript { methodId: string } // 用户选择的认证方式 ID ``` --- ## 3. 会话管理(Session Management) ### 3.1 创建新会话(session/new) **请求方向**:Client → Agent ```typescript // 请求参数 interface NewSessionRequest { cwd: string; // 工作目录路径 mcpServers: any[]; // MCP 服务器列表(当前为空数组) } // 响应 interface NewSessionResponse { sessionId: string; // 会话唯一标识 modes?: SessionModeState; // 可用模式(legacy) models?: SessionModelState; // 可用模型(experimental) configOptions?: SessionConfigOption[]; // 通用配置选项(新版,优先级高于 modes/models) } ``` ### 3.2 列举会话(session/list) **前提**:Agent 在初始化时声明 `sessionCapabilities.list = true` ```typescript // 请求参数 interface ListSessionsRequest { cwd?: string; // 按工作目录过滤 cursor?: string; // 分页游标 } // 响应 interface ListSessionsResponse { sessions: SessionInfo[]; // 会话列表 nextCursor?: string; // 下一页游标(分页) } interface SessionInfo { sessionId: string; title?: string; createdAt?: string; updatedAt?: string; } ``` ### 3.3 加载会话(session/load) **前提**:Agent 声明 `loadSession = true` 重量级操作,完整重放会话历史: ```typescript // 请求参数 interface LoadSessionRequest { sessionId: string; cwd: string; mcpServers: any[]; } // 响应(同 NewSessionResponse) interface LoadSessionResponse { modes?: SessionModeState; models?: SessionModelState; configOptions?: SessionConfigOption[]; } ``` 加载过程中 Agent 会通过 `session/update` 通知回放所有历史消息。 ### 3.4 恢复会话(session/resume) **前提**:Agent 声明 `sessionCapabilities.resume = true` 轻量级操作,不回放历史: ```typescript // 请求参数 interface ResumeSessionRequest { sessionId: string; cwd: string; mcpServers: any[]; } // 响应 interface ResumeSessionResponse { modes?: SessionModeState; models?: SessionModelState; configOptions?: SessionConfigOption[]; } ``` --- ## 4. 对话交互(Prompt/Response) ### 4.1 发送提示(prompt) **请求方向**:Client → Agent ```typescript // 请求参数 interface PromptRequest { sessionId: string; prompt: ContentBlock[]; // 内容块数组 } interface ContentBlock { type: 'text'; // 内容类型 text: string; // 文本内容 } // 响应 interface PromptResponse { stopReason: string; // 停止原因:"end_turn" | "error" | "cancelled" 等 usage?: { // Token 用量统计(可选) // 具体字段取决于 Agent 实现 }; } ``` ### 4.2 取消当前轮次(cancel) **请求方向**:Client → Agent ```typescript interface CancelRequest { sessionId: string; } ``` --- ## 5. 会话实时通知(Session Notifications) Agent 通过 `session/update` 向客户端推送实时状态更新。这是 ACP 协议中最丰富的通知机制。 **通知方向**:Agent → Client ```typescript interface SessionNotification { sessionId: string; update: SessionUpdate; // 更新内容(以下各种类型之一) } ``` ### 5.1 消息流(Streaming) #### `agent_message_chunk` — Agent 文本流式输出 ```typescript { sessionUpdate: 'agent_message_chunk', content: { type: 'text', text: string // 增量文本片段 } } ``` #### `user_message_chunk` — 用户消息回放(仅 session/load 使用) ```typescript { sessionUpdate: 'user_message_chunk', content: { type: 'text', text: string } } ``` #### `agent_thought_chunk` — Agent 思维过程流式输出 ```typescript { sessionUpdate: 'agent_thought_chunk', content: { type: 'text', text: string // 思考过程增量文本 } } ``` ### 5.2 工具调用(Tool Calls) #### `tool_call` — 新工具调用 ```typescript { sessionUpdate: 'tool_call', toolCallId: string, // 工具调用唯一ID title: string, // 工具调用标题/描述 status: 'pending' | 'running' | 'completed' | 'failed' } ``` #### `tool_call_update` — 工具调用状态更新 ```typescript { sessionUpdate: 'tool_call_update', toolCallId: string, // 对应的工具调用ID status: 'pending' | 'running' | 'completed' | 'failed', title?: string // 可选的标题更新 } ``` ### 5.3 计划(Plan) #### `plan` — Agent 执行计划 ```typescript { sessionUpdate: 'plan', entries: PlanEntry[] } interface PlanEntry { title?: string; description?: string; content?: string; status: 'pending' | 'in_progress' | 'completed' } ``` ### 5.4 会话配置更新 #### `current_mode_update` — 模式变更通知 ```typescript { sessionUpdate: 'current_mode_update', currentModeId: string // 新的当前模式 ID } ``` #### `config_option_update` — 配置选项全量更新 ```typescript { sessionUpdate: 'config_option_update', configOptions: SessionConfigOption[] // 完整的配置选项数组 } ``` #### `available_commands_update` — 可用命令更新 ```typescript { sessionUpdate: 'available_commands_update', availableCommands: AvailableCommand[] } interface AvailableCommand { name: string; // 命令名(用于 /slash 命令) description: string; // 命令描述 input?: { hint?: string; // 输入提示文字 }; } ``` #### `session_info_update` — 会话元信息更新 ```typescript { sessionUpdate: 'session_info_update', title?: string | null, // 会话标题(null 表示清除) updatedAt?: string | null // 最后更新时间(ISO 格式) } ``` --- ## 6. Agent → Client 请求(反向调用) Agent 可以向客户端发起以下请求,由客户端实现 `Client` 接口来处理。 ### 6.1 文件系统操作 #### `readTextFile` — 读取文本文件 ```typescript // 请求 interface ReadTextFileRequest { path: string; // 文件绝对路径 line?: number; // 起始行号(1-based) limit?: number; // 读取行数限制 } // 响应 interface ReadTextFileResponse { content: string; // 文件内容 } ``` **实现特性**: - 优先读取编辑器中未保存的内容(dirty buffer) - 支持行范围读取(line + limit) #### `writeTextFile` — 写入文本文件 ```typescript // 请求 interface WriteTextFileRequest { path: string; // 文件绝对路径 content: string; // 要写入的内容 } // 响应 interface WriteTextFileResponse {} // 空响应表示成功 ``` **实现特性**: - 自动创建父目录 - 写入后在编辑器中打开文件 ### 6.2 终端操作 #### `createTerminal` — 创建终端 ```typescript // 请求 interface CreateTerminalRequest { command: string; // 要执行的命令 args?: string[]; // 命令参数 cwd?: string; // 工作目录 env?: EnvVar[]; // 环境变量列表 outputByteLimit?: number; // 输出缓冲区大小限制(默认 1MB) } interface EnvVar { name: string; value: string; } // 响应 interface CreateTerminalResponse { terminalId: string; // 终端唯一标识 } ``` #### `terminalOutput` — 获取终端输出 ```typescript // 请求 interface TerminalOutputRequest { terminalId: string; } // 响应 interface TerminalOutputResponse { output: string; // 累积的输出内容 truncated: boolean; // 是否因超出限制被截断 exitStatus?: { // 进程已退出时提供 exitCode: number | null; signal: string | null; }; } ``` #### `waitForTerminalExit` — 等待终端退出 ```typescript // 请求 interface WaitForTerminalExitRequest { terminalId: string; } // 响应 interface WaitForTerminalExitResponse { exitCode: number | null; signal: string | null; } ``` #### `killTerminal` — 终止终端 ```typescript // 请求 interface KillTerminalRequest { terminalId: string; } // 响应 interface KillTerminalResponse {} // 空响应 ``` #### `releaseTerminal` — 释放终端资源 ```typescript // 请求 interface ReleaseTerminalRequest { terminalId: string; } // 响应 interface ReleaseTerminalResponse {} // 空响应 ``` **实现特性**: - 如果进程仍在运行,先发送 SIGTERM - VS Code 终端保持可见(不自动关闭),符合 ACP 规范 ### 6.3 权限请求 #### `requestPermission` — 请求用户授权 ```typescript // 请求 interface RequestPermissionRequest { toolCall?: { title?: string; // 权限请求标题 }; options: PermissionOption[]; // Agent 提供的选项列表 } interface PermissionOption { optionId: string; // 选项唯一 ID name: string; // 选项显示名称 kind: 'allow_once' | 'allow_always' | 'deny' | string; // 选项类型 } // 响应 interface RequestPermissionResponse { outcome: { outcome: 'selected' | 'cancelled'; optionId?: string; // 用户选择的选项 ID }; } ``` --- ## 7. 会话配置系统 ### 7.1 Session Mode(模式 — Legacy) ```typescript interface SessionModeState { currentModeId: string; availableModes: SessionMode[]; } interface SessionMode { id: string; name: string; description?: string; } ``` **设置模式**:Client → Agent ```typescript // setSessionMode 请求 { sessionId: string; modeId: string; } ``` ### 7.2 Session Model(模型 — Experimental) ```typescript interface SessionModelState { currentModelId: string; availableModels: SessionModel[]; } interface SessionModel { modelId: string; name: string; description?: string; } ``` **设置模型**:Client → Agent(unstable API) ```typescript // unstable_setSessionModel 请求 { sessionId: string; modelId: string; } ``` ### 7.3 Session Config Options(通用配置选项 — 推荐) 这是取代 modes/models 的新统一 API。当 Agent 同时提供 `configOptions` 和 `modes` 时,客户端**必须**仅使用 `configOptions`。 ```typescript interface SessionConfigOption { id: string; // 配置项唯一 ID type: 'select'; // 配置类型(目前仅支持 select) name: string; // 配置项名称 description?: string; // 配置项描述 category: 'mode' | 'model' | 'thought_level' | string; // 分类 currentValue: string; // 当前值 options: SelectOption[] | GroupedOptions[]; // 可选值列表 } interface SelectOption { value: string; name: string; description?: string; } interface GroupedOptions { group: string; name?: string; options: SelectOption[]; } ``` **设置配置选项**:Client → Agent ```typescript // setSessionConfigOption 请求 { sessionId: string; configId: string; value: string; } // 响应 — 包含更新后的完整 configOptions(级联更新) { configOptions: SessionConfigOption[]; } ``` --- ## 8. 协议错误码 | 错误码 | 含义 | 触发场景 | | ---------- | ------------------------ | ------------------------------------------------------- | | `-32000` | 需要认证 (Auth Required) | `newSession` / `listSessions` 调用时 Agent 需要认证 | 错误通过 `RequestError` 类传递: ```typescript class RequestError extends Error { code: number; message: string; } ``` --- ## 9. 完整交互流程示例 ``` ┌─────────┐ ┌─────────┐ │ Client │ │ Agent │ └────┬────┘ └────┬────┘ │ │ │──── spawn process (stdin/stdout pipe) ──────>│ │ │ │──── initialize ─────────────────────────────>│ │<─── InitializeResponse (agentInfo, caps) ────│ │ │ │──── newSession({cwd, mcpServers}) ──────────>│ │<─── NewSessionResponse {sessionId, modes} ───│ │ │ │<─── session/update: available_commands ───────│ │<─── session/update: config_option_update ────│ │ │ │──── prompt({sessionId, prompt}) ────────────>│ │ │ │<─── session/update: agent_thought_chunk ─────│ (思考过程) │<─── session/update: agent_thought_chunk ─────│ │ │ │<─── session/update: tool_call ───────────────│ (工具调用) │ │ │<─── requestPermission ───────────────────────│ (请求权限) │──── {outcome: 'selected', optionId} ────────>│ │ │ │<─── readTextFile({path}) ────────────────────│ (读取文件) │──── {content} ──────────────────────────────>│ │ │ │<─── writeTextFile({path, content}) ──────────│ (写入文件) │──── {} ─────────────────────────────────────>│ │ │ │<─── createTerminal({command, args}) ─────────│ (创建终端) │──── {terminalId} ───────────────────────────>│ │ │ │<─── waitForTerminalExit({terminalId}) ───────│ │──── {exitCode} ────────────────────────────>│ │ │ │<─── session/update: tool_call_update ────────│ (工具完成) │<─── session/update: agent_message_chunk ─────│ (回复内容) │<─── session/update: agent_message_chunk ─────│ │ │ │<─── PromptResponse {stopReason: 'end_turn'}──│ │ │ │<─── session/update: session_info_update ─────│ (标题更新) │ │ │──── cancel({sessionId}) ────────────────────>│ (可选:取消) │ │ │──── [kill process] ─────────────────────────>│ (断开连接) │ │ ``` --- ## 10. Agent 注册表 ACP 提供了公共的 Agent 注册表服务: - **注册表地址**:`https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json` - **缓存策略**:客户端缓存 5 分钟 注册表数据结构: ```typescript interface Registry { agents: RegistryAgent[]; } interface RegistryAgent { name: string; description?: string; command: string; args?: string[]; homepage?: string; } ``` --- ## 11. 已知兼容的 ACP Agent | Agent 名称 | 命令 | 参数 | | -------------- | ------------ | ----------------------------------------------------------- | | GitHub Copilot | `npx` | `@github/copilot-language-server@latest --acp` | | Claude Code | `npx` | `@agentclientprotocol/claude-agent-acp@latest` | | Gemini CLI | `npx` | `@google/gemini-cli@latest --experimental-acp` | | Qwen Code | `npx` | `@qwen-code/qwen-code@latest --acp --experimental-skills` | | Auggie CLI | `npx` | `@augmentcode/auggie@latest --acp` | | Qoder CLI | `npx` | `@qoder-ai/qodercli@latest --acp` | | Codex CLI | `npx` | `@zed-industries/codex-acp@latest` | | OpenCode | `npx` | `opencode-ai@latest acp` | | OpenClaw | `npx` | `openclaw acp` | | Kiro CLI | `kiro-cli` | `acp` | | Hermes Agent | `hermes` | `acp` | --- ## 12. 客户端能力声明(Client Capabilities) 客户端在 `initialize` 时声明支持的能力: ```typescript interface ClientCapabilities { fs?: { readTextFile?: boolean; // 支持 Agent 读取文件 writeTextFile?: boolean; // 支持 Agent 写入文件 }; terminal?: boolean; // 支持 Agent 操作终端 } ``` Agent 据此判断可以向客户端发起哪些反向请求。 --- ## 13. 协议设计特点总结 1. **基于 JSON-RPC 风格**:请求-响应模式 + 通知模式 2. **ND-JSON 传输**:轻量级,易于解析和调试 3. **流式输出**:通过 `*_chunk` 通知实现实时流式展示 4. **双向通信**:Agent 既接收指令,也可主动向客户端发起操作请求 5. **能力协商**:初始化时双方声明能力,避免调用不支持的功能 6. **认证集成**:支持多种认证方式,认证失败后自动重试 7. **会话持久化**:支持会话的创建、列举、加载(回放历史)和轻量恢复 8. **配置灵活性**:从 legacy modes/models 到统一的 configOptions,平滑演进 9. **权限控制**:Agent 操作需要用户授权,支持自动批准策略 10. **版本化设计**:通过 `protocolVersion` 确保客户端和代理的兼容性 --- ## 14. 附录:消息流方向汇总 | 方法 | 方向 | 类型 | 说明 | | ---------------------------- | --------------- | ------------ | -------------------- | | `initialize` | Client → Agent | Request | 协议握手 | | `authenticate` | Client → Agent | Request | 认证 | | `newSession` | Client → Agent | Request | 创建会话 | | `listSessions` | Client → Agent | Request | 列举会话 | | `loadSession` | Client → Agent | Request | 加载会话(重放历史) | | `resumeSession` | Client → Agent | Request | 恢复会话(无重放) | | `prompt` | Client → Agent | Request | 发送提示 | | `cancel` | Client → Agent | Request | 取消当前轮次 | | `setSessionMode` | Client → Agent | Request | 设置模式 | | `setSessionConfigOption` | Client → Agent | Request | 设置配置选项 | | `unstable_setSessionModel` | Client → Agent | Request | 设置模型 | | `session/update` | Agent → Client | Notification | 会话状态推送 | | `readTextFile` | Agent → Client | Request | 读取文件 | | `writeTextFile` | Agent → Client | Request | 写入文件 | | `createTerminal` | Agent → Client | Request | 创建终端 | | `terminalOutput` | Agent → Client | Request | 获取终端输出 | | `waitForTerminalExit` | Agent → Client | Request | 等待终端退出 | | `killTerminal` | Agent → Client | Request | 终止终端 | | `releaseTerminal` | Agent → Client | Request | 释放终端 | | `requestPermission` | Agent → Client | Request | 请求用户授权 |