AI 编程工具越来越多:Claude Code 擅长理解项目上下文,Codex 适合代码生成和修改,Gemini CLI 可以承担分析、解释、文档等任务。问题在于,每个工具都有自己的命令、会话模型、权限策略和接入方式。
如果一个平台想同时接入这些工具,最笨但最常见的做法是:为每个 Agent 单独写适配代码。
OpenClaw 支持 ACP 后,事情变得更像硬件里的 USB-C:客户端只要理解一个协议,就能对接多个兼容的 AI Agent(人工智能智能体,后面简称 Agent)。Agent 也不需要为每个编辑器、聊天工具或调度平台重复开发插件。
ACP 是什么
ACP(Agent Client Protocol,智能体客户端协议)是一套连接客户端和编码 Agent 的通信协议。
这里的“客户端”可以是代码编辑器,也可以是 OpenClaw 这样的调度入口;“Agent”可以是 Claude Code、Codex、Gemini CLI,或者其他实现了 ACP 的代码助手。
一句话概括:
ACP 把“客户端如何启动 Agent、发送任务、接收结果、管理会话、取消任务、处理权限”标准化了。
它解决的不是模型能力问题,而是工具之间的连接问题。
可以把 ACP 和 LSP(Language Server Protocol,语言服务器协议)放在一起理解:
| 协议 | 主要连接对象 | 解决的问题 |
|---|---|---|
| LSP | 编辑器 ↔ 语言服务器 | 让不同编辑器复用代码补全、跳转、诊断等语言能力 |
| ACP | 客户端 ↔ 编码 Agent | 让不同客户端复用 AI 编码、审查、解释、修改等 Agent 能力 |
LSP 让 VS Code、Neovim、JetBrains 等编辑器不必分别实现每门语言的全部能力;ACP 的目标类似,只不过它标准化的是 AI 编程 Agent 的接入方式。
没有 ACP 时,集成成本为什么高
假设有 3 个客户端和 4 个 Agent。如果没有统一协议,每个客户端都要分别适配每个 Agent,集成关系会膨胀成 3 × 4。
flowchart LR
subgraph Clients[客户端]
C1[OpenClaw]
C2[编辑器 A]
C3[终端工具 B]
end
subgraph Agents[编码 Agent]
A1[Claude Code]
A2[Codex]
A3[Gemini CLI]
A4[其他 Agent]
end
C1 --> A1
C1 --> A2
C1 --> A3
C1 --> A4
C2 --> A1
C2 --> A2
C2 --> A3
C2 --> A4
C3 --> A1
C3 --> A2
C3 --> A3
C3 --> A4
这种模式有三个直接问题。
| 问题 | 表现 | 后果 |
|---|---|---|
| 集成成本高 | 每新增一个 Agent,都要写一套适配层 | 客户端维护压力越来越大 |
| 兼容性差 | 某些 Agent 只支持少数编辑器或入口 | 开发者被迫在工具能力和使用习惯之间取舍 |
| 迁移成本高 | 会话、权限、配置各不相同 | 换 Agent 或换客户端都很麻烦 |
ACP 的做法是把中间的连接方式抽象成协议。客户端只接 ACP,Agent 只实现 ACP,双方不再互相绑定私有 API。
flowchart LR
subgraph Clients[客户端]
C1[OpenClaw]
C2[编辑器]
C3[聊天入口]
end
P[ACP 协议层]
subgraph Agents[ACP Agent]
A1[Claude Code Adapter]
A2[Codex Adapter]
A3[Gemini CLI Adapter]
end
C1 --> P
C2 --> P
C3 --> P
P --> A1
P --> A2
P --> A3
这就是 ACP 的核心价值:把“多对多”的集成关系压成“多对一再到多”。
ACP 的基本工作方式
ACP 使用 JSON-RPC(基于 JSON 的远程过程调用协议)2.0 作为消息格式。客户端通过请求、响应和通知来控制 Agent。
本地 Agent 通常走 stdio(标准输入/输出)管道,也就是客户端启动一个本地进程,然后通过 stdin/stdout 传递 JSON-RPC 消息;远程 Agent 可以走 HTTP(超文本传输协议)或 WebSocket(长连接通信协议)。
flowchart TB
U[用户指令] --> C[OpenClaw / 编辑器 / 其他客户端]
C -->|JSON-RPC 2.0| T{传输方式}
T -->|本地进程| S[stdio 管道]
T -->|远程服务| H[HTTP / WebSocket]
S --> A[ACP Agent]
H --> A
A --> M[Claude Code / Codex / Gemini CLI]
M --> A
A -->|Markdown 结果 / 状态 / 工具调用信息| C
C --> U
ACP 选择 Markdown 作为用户可读内容的默认格式,这一点很实际:AI 编码结果经常包含代码块、列表、解释、diff 说明,用 Markdown 就能直接表达,不需要客户端额外渲染 HTML。
ACP 标准化了哪些能力
ACP 不只是“发一句 prompt 给 Agent”。一个可用的编码 Agent 接入层,至少要处理会话、状态、取消、权限、工作目录等问题。
1. 会话生命周期
编码任务通常不是一次性问答。用户可能先让 Agent 阅读项目结构,再要求修改某个模块,随后继续追问测试失败原因。为了让上下文连续,客户端需要创建并维护会话。
常见生命周期可以理解成这样:
stateDiagram-v2
[*] --> Created: spawn 创建会话
Created --> Running: 发送任务
Running --> Waiting: Agent 等待用户确认或补充
Waiting --> Running: 用户继续指令
Running --> Completed: 任务完成
Running --> Cancelled: cancel 取消
Completed --> Closed: close 关闭
Cancelled --> Closed: close 关闭
OpenClaw 接入 ACP 后,可以把某个聊天线程和某个 ACP 会话绑定起来。这样用户在同一个线程里继续追问时,不需要重新解释上下文。
2. 线程绑定模式
线程绑定决定“用户当前所在的对话线程”和“ACP 会话”之间如何关联。
| 模式 | 行为 | 适合场景 |
|---|---|---|
auto | 在线程里就绑定当前线程;不在线程里就新建子线程并绑定 | 默认推荐,兼顾自动化和上下文连续 |
here | 必须在活动线程里运行,否则失败 | 需要严格保证任务只在当前线程上下文里执行 |
off | 不绑定线程,会话保持游离状态 | 批处理、一次性任务、无需后续追问的任务 |
如果希望 OpenClaw 在 Discord 等通道里自动创建并绑定 ACP 会话,需要同时打开两个开关:
session.threadBindings.enabled = true- 通道级
spawnAcpSessions = true
缺少任意一个,线程里的消息都可能无法自动生成对应的 ACP 会话。
3. 权限、目录和超时
编码 Agent 往往不只是回答问题,还可能读取文件、修改代码、运行命令。ACP 需要让客户端能够控制这些行为。
常见控制项包括:
| 控制项 | 作用 |
|---|---|
工作目录 cwd | 限定 Agent 在哪个项目目录下工作 |
权限策略 permissions | 控制读文件、写文件、执行命令是否需要审批 |
超时时间 timeout | 防止长任务无限运行 |
模型选择 model | 临时切换某个 Agent 使用的模型 |
取消任务 cancel | 用户发现方向不对时立刻停止当前任务 |
这些能力看似琐碎,但它们决定了 ACP 是否能用于真实开发环境。没有权限和超时控制,Agent 很容易变成一个不可控的后台进程。
OpenClaw、acpx 和具体 Agent 的关系
在 OpenClaw 的 ACP 链路里,acpx 扮演的是后端和会话管理工具的角色。以 Claude Code 为例,调用路径可以这样理解:
OpenClaw → acpx → claude-agent-acp → Claude Code
每一层负责的事情不同:
| 层级 | 职责 |
|---|---|
| OpenClaw | 接收用户指令,管理通道、线程和交互入口 |
| acpx | 创建 ACP 会话,转发 prompt,管理运行参数 |
| claude-agent-acp | 把 ACP 消息转换成 Claude Code 可理解的调用 |
| Claude Code | 真正执行代码理解、修改、审查等任务 |
换成 Codex 或 Gemini CLI 时,OpenClaw 不需要理解每个工具的细节,只要后面的 Agent 适配层符合 ACP 即可。
acpx 的会话复用能力
acpx 创建的会话可以和 Claude Code 命令行复用。这样就能在 OpenClaw 或终端里启动任务,再切回 Claude Code CLI(Command Line Interface,命令行界面)继续同一个上下文。
示例流程如下:
# 创建一个命名会话
acpx claude sessions new --name abc
# 在这个会话里执行一次任务
acpx --approve-all claude prompt "分析这个项目的架构" -s abc
# 打开 Claude Code CLI,继续使用已有上下文
claude
这里的关键点不是命令本身,而是会话状态不再被某个入口锁死。终端、OpenClaw、Claude Code CLI 可以围绕同一段上下文协作。
不过,--approve-all 只适合可信项目和低风险环境。涉及生产代码、敏感文件或可能执行命令的任务,更稳妥的做法是开启人工审批。
OpenClaw 的 /acp 命令
OpenClaw 提供了一组 /acp 命令,用来管理 ACP 会话和运行参数。
| 命令 | 作用 |
|---|---|
/acp spawn | 创建新的 ACP 会话 |
/acp steer | 向运行中的会话发送指令 |
/acp cancel | 取消当前任务 |
/acp close | 结束会话 |
/acp status | 查看会话状态 |
/acp set-mode | 设置运行模式 |
/acp set | 写入通用配置选项 |
/acp doctor | 诊断连接问题 |
/acp install | 输出安装和启用步骤 |
/acp model | 临时切换模型 |
/acp cwd | 设置工作目录 |
/acp permissions | 设置审批策略 |
/acp timeout | 设置超时时间 |
/acp reset-options | 重置运行选项覆盖 |
/acp sessions | 列出最近的 ACP 会话 |
/acp sessions read | 查看指定会话详情 |
这组命令覆盖了会话的完整生命周期:创建、发送任务、调整参数、诊断问题、关闭会话。
一个典型使用场景:在聊天线程里审查 PR
PR(Pull Request,合并请求)审查很适合展示 ACP 的价值。假设团队在 Discord 里讨论一个 PR,用户可以直接让 OpenClaw 调用 Claude Code:
@OpenClaw 用 Claude 帮我 review 这个 PR,重点关注安全性
对应的调用过程如下:
sequenceDiagram
participant User as 用户
participant Chat as Discord 线程
participant OC as OpenClaw
participant ACP as acpx / ACP
participant Claude as Claude Code
User->>Chat: 发送 PR 审查指令
Chat->>OC: 转发消息
OC->>ACP: 创建或复用线程绑定会话
ACP->>Claude: 请求审查 PR
Claude-->>ACP: 返回安全风险、代码问题和建议
ACP-->>OC: 返回 Markdown 结果
OC-->>Chat: 输出审查结果
User->>Chat: 继续追问某个风险点
Chat->>OC: 同线程消息
OC->>ACP: 复用已绑定会话
ACP->>Claude: 基于上下文继续分析
如果线程绑定正常工作,后续追问不需要重复提供 PR 链接、项目背景和审查重点。OpenClaw 会把同一个聊天线程映射到同一个 ACP 会话。
最小可用配置
基础配置可以从启用 ACP、选择 acpx 后端、限制允许使用的 Agent 开始:
{
"acp": {
"enabled": true,
"backend": "acpx",
"allowedAgents": ["claude", "codex", "gemini"]
}
}
如果要让聊天线程自动创建 ACP 会话,还需要打开线程绑定和通道级自动创建能力。不同部署方式的配置层级可能不完全一样,但核心开关是这两个:
{
"session": {
"threadBindings": {
"enabled": true
}
},
"channels": {
"discord": {
"spawnAcpSessions": true
}
}
}
排查配置时,可以优先检查三件事:
| 检查项 | 现象 |
|---|---|
acp.enabled 是否为 true | 没开启时 /acp spawn 无法正常创建会话 |
allowedAgents 是否包含目标 Agent | 不在白名单里的 Agent 无法被调用 |
| 线程绑定和通道创建开关是否同时开启 | 缺少任意一个都会影响自动绑定 |
OAuth 风险和账号边界
OAuth(Open Authorization,开放授权)常用于第三方客户端登录或授权。某些第三方客户端如果接入方式不规范,可能触发账号限制或安全审查。
ACP 不应该被理解成绕过平台风控的手段。更稳妥的理解是:它把调用链分层,让 OpenClaw、acpx、Agent 适配层和具体 CLI 各自承担职责。使用受支持的本地 CLI 和明确的适配层,可以减少把账号凭证交给不明客户端的机会。
对账号安全敏感的环境,建议遵守三条原则:
| 原则 | 说明 |
|---|---|
| 优先使用可信适配器 | 不要把账号授权交给来源不明的客户端 |
| 明确凭证存放位置 | 知道 token、cookie 或 CLI 登录态由哪个工具管理 |
| 保留审批流程 | 不要在高风险项目里默认放开所有文件修改和命令执行权限 |
适合用 ACP 的场景
ACP 适合“一个入口调度多个 Agent”的工作流,尤其是团队协作和长上下文任务。
| 场景 | 是否适合 | 原因 |
|---|---|---|
| 在聊天线程里让 Agent 审查 PR | 适合 | 线程绑定可以保留上下文 |
| 在 OpenClaw 中切换 Claude、Codex、Gemini CLI | 适合 | ACP 屏蔽不同 Agent 的调用差异 |
| 批量分析多个仓库 | 适合 | acpx 可以创建命名会话并执行任务 |
| 只在本地终端偶尔问一次问题 | 不一定需要 | 直接使用对应 CLI 可能更简单 |
| Agent 没有 ACP 适配层 | 暂时不适合 | 仍然需要额外封装 |
| 权限要求极严格的生产环境 | 需要谨慎 | 必须配置审批、目录隔离和超时 |
常见坑
Agent 白名单没有配置
allowedAgents 没有包含目标 Agent 时,即使后端可用,OpenClaw 也不会调用它。这个设计是必要的,因为编码 Agent 可能修改文件或执行命令,不能默认全部开放。
线程没有自动绑定
如果用户在同一个 Discord 线程里继续追问,但 Agent 像新会话一样重新开始,通常要检查:
session.threadBindings.enabled = true
通道级 spawnAcpSessions = true
两个条件必须同时满足。
工作目录不对
Agent 分析项目时依赖当前工作目录。目录错了,轻则找不到文件,重则在错误项目里修改代码。运行任务前可以用:
/acp cwd
明确当前目录。
权限过宽
--approve-all 或类似自动审批策略可以减少交互,但风险也更高。处理陌生仓库、生产代码、包含密钥的项目时,应使用更严格的审批策略。
任务卡住但没有超时
长任务需要设置超时时间,否则 Agent 可能一直占用会话。可以用:
/acp timeout
给任务加上边界。
资料入口
- OpenClaw ACP Agents 文档:https://docs.openclaw.ai/tools/acp-agents
- acpx GitHub 仓库:https://github.com/openclaw/acpx
- Agent Client Protocol 标准:https://github.com/agentclientprotocol/agent-client-protocol
- ACP TypeScript SDK:https://github.com/agentclientprotocol/typescript-sdk