基于
vscode-acp项目源码分析提取,SDK 版本:@agentclientprotocol/sdk ^0.21.1
ACP (Agent Client Protocol) 是一种用于 AI 编程代理(Agent)与客户端(Client/IDE)之间通信 的标准化协议。它定义了客户端如何启动、管理和与 AI 代理交互的完整生命周期,类似于 LSP (Language Server Protocol) 的设计理念,但专门面向 AI 代理场景。
initialize 握手交换 protocolVersion| 属性 | 描述 |
|---|---|
| 传输方式 | 子进程的 stdin(写入)/ stdout(读取) |
| 序列化格式 | ND-JSON(Newline Delimited JSON) |
| 流适配 | Node.js Stream → Web Streams API (ReadableStream / WritableStream) |
| SDK 入口 | ndJsonStream(writable, readable) 创建双向流 |
Client Agent Process
| |
|--- spawn(command, args, {stdio: pipe}) --------->|
| |
|<========= stdin/stdout pipe established ========>|
Agent 配置结构:
interface AgentConfigEntry {
command: string; // 启动命令,如 "npx"
args?: string[]; // 命令行参数
env?: Record<string, string>; // 环境变量
displayName?: string; // 显示名称
}
连接建立后,客户端必须发送 initialize 请求:
请求方向:Client → Agent
// 客户端发送的初始化参数
{
protocolVersion: PROTOCOL_VERSION, // 协议版本号
clientInfo: {
name: 'vscode-acp-client', // 客户端名称
version: '0.2.0', // 客户端版本
},
clientCapabilities: {
fs: {
readTextFile: true, // 支持文件读取
writeTextFile: true, // 支持文件写入
},
terminal: true, // 支持终端操作
},
}
响应结构 (InitializeResponse):
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; // 认证方式描述
}
当 Agent 需要认证时(错误码 -32000),客户端启动认证流程:
Client Agent
| |
|-- newSession() ------------------->|
|<-- Error: auth required (-32000) --|
| |
|-- authenticate({methodId}) ------->|
|<-- success ------------------------|
| |
|-- newSession() (retry) ----------->|
|<-- NewSessionResponse -------------|
认证请求:
{ methodId: string } // 用户选择的认证方式 ID
请求方向:Client → Agent
// 请求参数
interface NewSessionRequest {
cwd: string; // 工作目录路径
mcpServers: any[]; // MCP 服务器列表(当前为空数组)
}
// 响应
interface NewSessionResponse {
sessionId: string; // 会话唯一标识
modes?: SessionModeState; // 可用模式(legacy)
models?: SessionModelState; // 可用模型(experimental)
configOptions?: SessionConfigOption[]; // 通用配置选项(新版,优先级高于 modes/models)
}
前提:Agent 在初始化时声明 sessionCapabilities.list = true
// 请求参数
interface ListSessionsRequest {
cwd?: string; // 按工作目录过滤
cursor?: string; // 分页游标
}
// 响应
interface ListSessionsResponse {
sessions: SessionInfo[]; // 会话列表
nextCursor?: string; // 下一页游标(分页)
}
interface SessionInfo {
sessionId: string;
title?: string;
createdAt?: string;
updatedAt?: string;
}
前提:Agent 声明 loadSession = true
重量级操作,完整重放会话历史:
// 请求参数
interface LoadSessionRequest {
sessionId: string;
cwd: string;
mcpServers: any[];
}
// 响应(同 NewSessionResponse)
interface LoadSessionResponse {
modes?: SessionModeState;
models?: SessionModelState;
configOptions?: SessionConfigOption[];
}
加载过程中 Agent 会通过 session/update 通知回放所有历史消息。
前提:Agent 声明 sessionCapabilities.resume = true
轻量级操作,不回放历史:
// 请求参数
interface ResumeSessionRequest {
sessionId: string;
cwd: string;
mcpServers: any[];
}
// 响应
interface ResumeSessionResponse {
modes?: SessionModeState;
models?: SessionModelState;
configOptions?: SessionConfigOption[];
}
请求方向:Client → Agent
// 请求参数
interface PromptRequest {
sessionId: string;
prompt: ContentBlock[]; // 内容块数组
}
interface ContentBlock {
type: 'text'; // 内容类型
text: string; // 文本内容
}
// 响应
interface PromptResponse {
stopReason: string; // 停止原因:"end_turn" | "error" | "cancelled" 等
usage?: { // Token 用量统计(可选)
// 具体字段取决于 Agent 实现
};
}
请求方向:Client → Agent
interface CancelRequest {
sessionId: string;
}
Agent 通过 session/update 向客户端推送实时状态更新。这是 ACP 协议中最丰富的通知机制。
通知方向:Agent → Client
interface SessionNotification {
sessionId: string;
update: SessionUpdate; // 更新内容(以下各种类型之一)
}
agent_message_chunk — Agent 文本流式输出{
sessionUpdate: 'agent_message_chunk',
content: {
type: 'text',
text: string // 增量文本片段
}
}
user_message_chunk — 用户消息回放(仅 session/load 使用){
sessionUpdate: 'user_message_chunk',
content: {
type: 'text',
text: string
}
}
agent_thought_chunk — Agent 思维过程流式输出{
sessionUpdate: 'agent_thought_chunk',
content: {
type: 'text',
text: string // 思考过程增量文本
}
}
tool_call — 新工具调用{
sessionUpdate: 'tool_call',
toolCallId: string, // 工具调用唯一ID
title: string, // 工具调用标题/描述
status: 'pending' | 'running' | 'completed' | 'failed'
}
tool_call_update — 工具调用状态更新{
sessionUpdate: 'tool_call_update',
toolCallId: string, // 对应的工具调用ID
status: 'pending' | 'running' | 'completed' | 'failed',
title?: string // 可选的标题更新
}
plan — Agent 执行计划{
sessionUpdate: 'plan',
entries: PlanEntry[]
}
interface PlanEntry {
title?: string;
description?: string;
content?: string;
status: 'pending' | 'in_progress' | 'completed'
}
current_mode_update — 模式变更通知{
sessionUpdate: 'current_mode_update',
currentModeId: string // 新的当前模式 ID
}
config_option_update — 配置选项全量更新{
sessionUpdate: 'config_option_update',
configOptions: SessionConfigOption[] // 完整的配置选项数组
}
available_commands_update — 可用命令更新{
sessionUpdate: 'available_commands_update',
availableCommands: AvailableCommand[]
}
interface AvailableCommand {
name: string; // 命令名(用于 /slash 命令)
description: string; // 命令描述
input?: {
hint?: string; // 输入提示文字
};
}
session_info_update — 会话元信息更新{
sessionUpdate: 'session_info_update',
title?: string | null, // 会话标题(null 表示清除)
updatedAt?: string | null // 最后更新时间(ISO 格式)
}
Agent 可以向客户端发起以下请求,由客户端实现 Client 接口来处理。
readTextFile — 读取文本文件// 请求
interface ReadTextFileRequest {
path: string; // 文件绝对路径
line?: number; // 起始行号(1-based)
limit?: number; // 读取行数限制
}
// 响应
interface ReadTextFileResponse {
content: string; // 文件内容
}
实现特性:
writeTextFile — 写入文本文件// 请求
interface WriteTextFileRequest {
path: string; // 文件绝对路径
content: string; // 要写入的内容
}
// 响应
interface WriteTextFileResponse {} // 空响应表示成功
实现特性:
createTerminal — 创建终端// 请求
interface CreateTerminalRequest {
command: string; // 要执行的命令
args?: string[]; // 命令参数
cwd?: string; // 工作目录
env?: EnvVar[]; // 环境变量列表
outputByteLimit?: number; // 输出缓冲区大小限制(默认 1MB)
}
interface EnvVar {
name: string;
value: string;
}
// 响应
interface CreateTerminalResponse {
terminalId: string; // 终端唯一标识
}
terminalOutput — 获取终端输出// 请求
interface TerminalOutputRequest {
terminalId: string;
}
// 响应
interface TerminalOutputResponse {
output: string; // 累积的输出内容
truncated: boolean; // 是否因超出限制被截断
exitStatus?: { // 进程已退出时提供
exitCode: number | null;
signal: string | null;
};
}
waitForTerminalExit — 等待终端退出// 请求
interface WaitForTerminalExitRequest {
terminalId: string;
}
// 响应
interface WaitForTerminalExitResponse {
exitCode: number | null;
signal: string | null;
}
killTerminal — 终止终端// 请求
interface KillTerminalRequest {
terminalId: string;
}
// 响应
interface KillTerminalResponse {} // 空响应
releaseTerminal — 释放终端资源// 请求
interface ReleaseTerminalRequest {
terminalId: string;
}
// 响应
interface ReleaseTerminalResponse {} // 空响应
实现特性:
requestPermission — 请求用户授权// 请求
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
};
}
interface SessionModeState {
currentModeId: string;
availableModes: SessionMode[];
}
interface SessionMode {
id: string;
name: string;
description?: string;
}
设置模式:Client → Agent
// setSessionMode 请求
{ sessionId: string; modeId: string; }
interface SessionModelState {
currentModelId: string;
availableModels: SessionModel[];
}
interface SessionModel {
modelId: string;
name: string;
description?: string;
}
设置模型:Client → Agent(unstable API)
// unstable_setSessionModel 请求
{ sessionId: string; modelId: string; }
这是取代 modes/models 的新统一 API。当 Agent 同时提供 configOptions 和 modes 时,客户端必须仅使用 configOptions。
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
// setSessionConfigOption 请求
{
sessionId: string;
configId: string;
value: string;
}
// 响应 — 包含更新后的完整 configOptions(级联更新)
{
configOptions: SessionConfigOption[];
}
| 错误码 | 含义 | 触发场景 |
|---|---|---|
-32000 |
需要认证 (Auth Required) | newSession / listSessions 调用时 Agent 需要认证 |
错误通过 RequestError 类传递:
class RequestError extends Error {
code: number;
message: string;
}
┌─────────┐ ┌─────────┐
│ 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] ─────────────────────────>│ (断开连接)
│ │
ACP 提供了公共的 Agent 注册表服务:
https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json注册表数据结构:
interface Registry {
agents: RegistryAgent[];
}
interface RegistryAgent {
name: string;
description?: string;
command: string;
args?: string[];
homepage?: string;
}
| 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 |
客户端在 initialize 时声明支持的能力:
interface ClientCapabilities {
fs?: {
readTextFile?: boolean; // 支持 Agent 读取文件
writeTextFile?: boolean; // 支持 Agent 写入文件
};
terminal?: boolean; // 支持 Agent 操作终端
}
Agent 据此判断可以向客户端发起哪些反向请求。
*_chunk 通知实现实时流式展示protocolVersion 确保客户端和代理的兼容性| 方法 | 方向 | 类型 | 说明 |
|---|---|---|---|
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 | 请求用户授权 |