Back to Blog
ACP:AI 时代的 Agent 接入标准

ACP:AI 时代的 Agent 接入标准

ACP:AI 时代的 Agent 接入标准

·Unknown

一、先从一个真实的场景说起

假设你想给自己做一个 AI 产品——可能是一个定制化的代码助手、一个内部知识库 Agent、一个贴合团队工作流的 Coding Copilot,或者就是一个能自动帮你写日报、跑脚本、改项目的"私人助理"。

你很快会面临一个现实问题:要不要自己从零实现一个 Code Agent?

  • 自己从头撸,意味着你要处理 prompt 工程、工具调用、上下文管理、沙箱执行、权限系统……这些都是 Claude Code、Codex、Gemini CLI 这些产品已经打磨过无数遍的事情
  • 而且这些头部 Agent 在代码理解和执行效果上已经非常能打,自己重新造一个,大概率不如直接复用

所以更合理的做法是:把 Claude Code / Codex / Gemini CLI 这类成熟 Agent 当作"引擎",自己只做上层的交互外壳和业务编排。

可问题接着就来了:

  • Claude Code 有自己的 CLI 和交互方式
  • Codex 有自己的 SDK 和调用协议
  • Gemini CLI 又是另一套玩法
  • 想让它们跑在你自研的 Web 界面 / 内部 IDE 插件 / 自动化工作流里,每接一个都得写一套适配

反过来,这些 Agent 厂商也头疼:每出一款新 IDE、每冒出一个新平台,他们都得重新做一遍前端对接。

这就是典型的 N × M 问题

Agent A ─┐                  ┌─ 你的产品 X
Agent B ─┼── N × M 适配 ────┼─ 自研 IDE Y
Agent C ─┘                  └─ 自动化平台 Z

软件工程史上解决这种问题的办法只有一个——在中间抽一层标准协议,把 N × M 压成 N + M:

Agent A ─┐                  ┌─ 你的产品 X
Agent B ─┼────── ACP ───────┼─ 自研 IDE Y
Agent C ─┘                  └─ 自动化平台 Z

ACP 就是这一层。它让你可以只做好"壳子",复用生态里最强的 Agent “内核”——这也是它在当下这个时间点最务实的价值。

还有一个很现实的好处容易被忽视:ACP 让你可以"不走 API"就用上 Claude Code / Codex。

自己基于模型 API 造 Agent,意味着每一次思考、每一次 tool_call、每一次长上下文回看,都在按 token 烧钱——稍微跑几个重活,一个月账单轻松三位数美金。而 Claude Code / Codex 这类产品自带订阅额度(Claude Pro / ChatGPT Plus 的 Max 套餐),你通过 ACP 把它们"借"进自己的壳程序,消耗的是固定月费的订阅池,不是按量计费的 API。

对个人和小团队来说,这一条差价大到几乎可以单独成为选 ACP 的理由。


二、ACP 是什么

一句话:ACP(Agent Client Protocol)是一个用来规范 IDE/UI 与 AI Agent 之间通信的开放协议。

几个关键信息:

  • 全称:Agent Client Protocol
  • 官网https://agentclientprotocol.com/
  • 主导方:Zed 编辑器团队
  • 定位:在"Agent 能力"和"产品形态"之间,抽出一层标准接口
  • 关键特性双向——不仅 UI 能调 Agent,Agent 也能反过来请求 UI 的能力(读文件、请求授权、流式推送思考过程等)

用类比快速建立认知

如果你熟悉下面任何一个协议,ACP 都能找到对应:

协议解决的问题类比关系
HTTP浏览器 ↔ Web 服务任意浏览器访问任意网站
LSP编辑器 ↔ 语言服务任意编辑器支持任意语言
MCPLLM ↔ 工具任意模型调用任意工具
ACPIDE/UI ↔ Agent任意 IDE 驱动任意 Agent

如果你是后端出身,把它当 “Agent 版 HTTP” 理解;如果你写过编辑器插件,把它当 “Agent 版 LSP” 理解——结构几乎同构。

最容易混淆的一页:ACP vs MCP

这是我被问得最多的问题,所以直接放在最前面:

MCPACP
连接谁LLM ↔ ToolClient (IDE) ↔ Agent
视角给模型给 UI
典型场景Claude 调用 GitHub APIZed 驱动 Claude Code 改代码
一句话“让模型长出手”“让 Agent 长出脸”

两者不是替代关系,是互补关系:一个 Coding Agent 内部用 MCP 调工具,对外用 ACP 和 IDE 对话,完全不冲突。


三、ACP 协议内容

聊到这里你可能会好奇:ACP 协议到底规定了什么?会不会很复杂?

我的结论是:ACP 本身并不厚。你可以用三个维度把它整个记住——角色、消息模型、传输方式

3.1 两个角色

ACP 的世界里只有两个角色:

角色职责可以类比成
Agent真正干活的一方:接收 prompt、管理会话、推送过程、必要时反向请求用户授权或 IDE 能力后端服务
Client直面用户的一方:发 prompt、渲染 Agent 推送的中间过程、响应 Agent 的反向请求前端 / 浏览器
做上层产品的时候,你要么实现 Client(复用 Claude Code / Codex 这类成熟 Agent),要么实现 Agent(把自家能力接入 Zed 等 ACP 宿主),两者很少同时做。

3.2 双向消息模型

ACP 最不同于传统 HTTP API 的一点,是它的消息流是双向的

传统 HTTP:
  Client ───── request ─────▶ Server
  Client ◀──── response ───── Server
ACP:
  Client ───── prompt ─────────▶ Agent        ← 你让 Agent 做事
  Client ◀──── 读文件 / 要授权 ── Agent        ← Agent 反过来请你帮忙
  Client ◀──── 流式思考 / diff ── Agent        ← Agent 把过程持续推给你
  Client ───── cancel ─────────▶ Agent        ← 你随时能打断它

也就是说,Agent 不是一个"请求 / 响应"式的被动 API,而是一个能主动说话的参与方。这一点决定了 ACP 能承载 “AI 结对编程” 这类交互的全貌:思考过程要可见、危险动作要授权、跑到一半能叫停。

3.3 一次完整交互长什么样

用一次"用户让 Agent 改代码"的完整流程把上面这些东西串起来:

Client (你的产品)                                   Agent (Claude Code 等)
    │                                               │
    │────────── initialize ───────────────────────▶│   协商协议版本与能力
    │◀───────── initialize response ───────────────│
    │                                               │
    │────────── session/new ──────────────────────▶│   开一个会话
    │◀───────── session_id ────────────────────────│
    │                                               │
    │────────── session/prompt ───────────────────▶│   用户:"帮我把 foo 改成 bar"
    │                                               │
    │◀───────── fs/read_text_file ─────────────────│   Agent:先读一下相关文件
    │────────── file content ─────────────────────▶│
    │                                               │
    │◀───────── session/update (thought) ──────────│   流式推送思考过程
    │◀───────── session/update (tool_call) ────────│   流式推送工具调用
    │                                               │
    │◀───────── session/request_permission ────────│   "我要改这个文件,可以吗?"
    │────────── allow ────────────────────────────▶│
    │                                               │
    │◀───────── session/update (diff) ─────────────│   流式推送 diff
    │◀───────── session/prompt response ───────────│   任务完成
    │                                               │
    │────────── session/cancel(可选)────────────▶│   用户中途取消

四个关键看点:

  1. 双向:Agent 不只是被动回答,它会反过来请求 IDE / 产品能力
  2. 流式session/update 一路推送,用户能看到"AI 在想什么"
  3. 权限可控:改文件、跑命令等危险动作,最终由用户拍板,Agent 不能越权
  4. 可中断:用户随时能 cancel,协议天然支持

换句话说:如果你做的产品里需要 “AI 边思考边干活、干之前要请示、干到一半能叫停”,ACP 几乎是现成的一张协议模板

3.4 传输方式:协议和运输分离

ACP 在设计上把"说什么"(语义)和"怎么运"(传输)分得很干净,同一套协议可以跑在三种传输上:

传输特点典型场景
stdio子进程 + 标准输入输出,零依赖Zed 默认方式,本地把 Agent 当子进程拉起
Streamable HTTPPOST 发请求 + SSE 收反向流远程部署,对企业网络 / 防火墙最友好
WebSocket全双工长连接远程部署,追求低延迟

对做产品的你来说,选型其实很直白:

  • 本地 Agent + 桌面端产品 → 首选 stdio,零部署、零网络配置
  • 远程 Agent + Web 产品 / 多端接入 → 选 Streamable HTTP,SSE 穿透性最好
  • 有长连接需求 / 对延迟敏感 → 选 WebSocket

换传输不需要改业务代码,只需要换一下连接初始化方式——这也是 ACP 比"自己造一套 HTTP API"更值得的一点。

3.5 除此之外:扩展机制

ACP 预留了 _ 前缀的自定义方法,你可以在不破坏标准兼容性的前提下给它加私有能力(比如你的产品有一个"埋点上报"的私有协议想走同一条连接),详见官方扩展文档。这一点让 ACP 既能"做标准"也能"留口子",对工程落地很友好。


四、生态现状

已有实现

  • Zed 编辑器:原生支持 ACP,是 ACP 的首个主力宿主
  • Claude Code Adapter:把 Claude Code 包成 ACP Agent,让它能在 Zed 里跑
  • Gemini CLI Adapter:同上
  • 越来越多的适配器正在涌现

生态的好兆头是:同一个 Agent 开始能在多个 IDE 里跑,同一个 IDE 开始能接入多个 Agent——N × M 正在变成 N + M。

Go 版 SDK:eino-contrib/acp

官方主要提供 TypeScript/Rust 的实现,而我们因为字节内部 Go 技术栈 + Eino Agent 框架 需要以 ACP 方式对外暴露,做了一个 Go 版的 SDK:github.com/eino-contrib/acp

它提供的能力:

  • 双向 RPC 抽象conn.ClientConnection / conn.AgentConnection 屏蔽 JSON-RPC 细节
  • 三种传输层全支持:stdio / Streamable HTTP / WebSocket,HTTP & WS 基于 CloudWeGo Hertz
  • 远程服务器server.ACPServer 在同一路由上同时支持 HTTP 与 WS 升级
  • 协议扩展:原生支持 _ 前缀自定义方法
  • 代码生成:从官方 schema.json 自动生成类型与方法,协议升级跟得上

完整示例代码在仓库 examples/ 目录下,涵盖 Agent / Client 两端。


五、每个人都值得一个自己的 AI 壳程序

写到最后,我想把视角收回到个人这一侧。

AI 时代,每个人都值得给自己做一个"AI 壳程序"——可能是个命令行工具、本地客户端、Web 应用,甚至是挂在 IM 机器人后面的脚本。形态不重要,把 AI 驯化成贴合你自己工作流的样子,持续给你提效,才是重点。

这件事过去几乎"想想就算了":前端 / 后端 / 部署 / 权限折腾一圈,人先累死。但现在 Cursor / Claude Code / Codex 已经能把一个 idea 推到能跑的原型,搭壳子的门槛正在断崖式降低——真正的难点,已经不是 UI,而是里面跑的那个 Agent:上下文管理、工具调用、沙箱执行、权限系统……每一项都是大坑,全自己填基本等于放弃。

ACP 恰好解决了这个问题。

它让你可以直接"借用"Claude Code、Codex、Gemini CLI 这些已经被打磨得非常能打的 Agent 作为可替换的内核,而你只需要在外面做两件你最懂、也最值得自己做的事:

  • 流程编排:怎么把 AI 的能力串进你自己的工作流
  • 贴合你工作流的 Skill:那些只有你自己在意、只有你自己知道怎么做对的"个性化能力"

这是一个非常划算的分工: 把最难、最耗资源的"智能内核"交给最强的产品去做; 把最懂你、最无法被外人复刻的"流程和 Skill"留给你自己。

而且因为是走协议,今天你跑 Claude Code,明天出了更强的 Agent,只要换一个 ACP 连接就能无缝切换——你的壳子是沉淀资产,引擎是可替换部件


六、抛砖引玉:一些个人的最佳实践

6.1 CodeReview 场景

用 Agent 做 Code Review 时,你多半会踩到两个坑:

  • 结果不稳定:LLM 输出本身带随机性,同一份 diff 跑两次,评审意见可能一次说 “有问题”、一次说 “没问题”
  • 假阳性偏多:模型容易把"风格建议"、"可读性吐槽"和"真实 bug"混成一张 Issue List,让你在噪声里捞信号

所以在壳程序里,我把这件事拆成了一条流水线

  1. Reviewer:通读 diff,产出一份粗粒度的 Issue List(允许有噪声)
  2. Double Checker:把 Issue List 逐条喂回去做二次校验,只保留"真的可能是 bug"的条目
  3. Cross Reviewer(换一个 Agent):把二次校验的结果交给另一家 Agent 再 Review 一遍,借不同模型的视角差异把剩下的假阳性再滤一轮,真正跑出去的全是被双方都认可的高置信 Issue
  4. Fixer:对最终确认的 Issue 生成修复补丁
  5. Loop(可重复 N 轮):把补丁合回 diff 后,再开一个新的 Session 从第 1 步跑一遍;按需重复 N 轮,直到这一轮 Reviewer 不再报新问题为止

这么一拆,随机性被多轮投票抹平,假阳性被双 Agent 交叉复核过滤,Review 和 Fix 也不再是同一个 Agent 自说自话。而在 ACP 的模型下,这一套流水线就是"开几条 ACP 连接 + 在壳程序里写一小段编排代码"的事——每个节点都能按"效果 / 成本"独立选型

举个我自己的搭配:前两轮 Reviewer 和 Double Checker 的工作量大、但任务相对简单(过滤明显噪声),我一般用 ChatGPT(Codex) 顶——跑起来快、消耗便宜;到了第 3 步 Cross Reviewer 和第 4 步 Fixer,要的是判断力和代码能力,这时我才切到 Claude Opus 来收尾。整条链路跑下来,效果接近"全程 Opus",但 Token 账单能省一大截。

这就是 ACP “引擎是可替换部件” 的真正威力——不仅可以换,还可以在一条流水线里按需混用,今天 Claude Code,明天 Codex,甚至同一个任务里不同阶段跑不同 Agent,工作流本身都不动。

6.2 定时任务:让 Agent 成为"永远在岗的后台同事"

作为 Claude Code 的重度用户,我习惯紧跟它的每次更新。但光看官方 Change Log 往往不够——很多改动描述得很含糊,真正想知道"这个新功能到底怎么实现的",还得去翻源码。而 Claude Code 的 cli.js 是打包压缩过的 bundle,肉眼几乎不可读。

以前我是出新版 → 手动下载 → 手动切分 → 手动贴给模型反编译 → 手动对着 Change Log 去找新功能的实现——每一步都不难,但加起来就是一件"值得做、但懒得做"的事。于是我把它整个做进了壳程序里的一条自动化流水线:

  1. 监听:一条定时 Shell 脚本每天轮询 GitHub,拿 Claude Code 最新 release 的版本号和 Change Log
  2. 取源码:发现新版本就自动拉取最新的 cli.js,按函数 / 模块边界切分成能塞进上下文的小块
  3. 反编译:把切分后的代码丢给 Agent,让它把压缩 bundle 还原成可读源码
  4. 定位新功能:让 Agent 结合 Change Log,在反编译结果里找到对应新功能的实现位置和关键代码片段
  5. 产出:把分析结果自动写成一份飞书文档,链接推到我的 IM

整个过程配好之后就是"版本发布 → 飞书链接到手",我只需要打开链接读结论。和 6.1 一样,这里的每个 Agent 节点也是按"效果 / 成本"独立选型的——前面的反编译任务量大但相对机械,用 ChatGPT(Codex)跑就够;到第 4 步"结合 Change Log 找关键实现"这种需要理解力的活,再切到 Claude Opus 收尾。

这就是我说的 “让 Agent 成为永远在岗的后台同事”:你不再是"有空了打开 AI 产品问一下",而是把一件件"值得知道但来不及跟进"的事,交给壳程序里的定时任务自动跑——等你回来,结论已经躺在那里了。

总结一下

上面两个例子看起来风格不同——一个是交互式的 Code Review,一个是后台跑的定时任务——但本质其实是同一件事:基于 ACP,把多个 Agent 编排起来,让它们去跑那些"值得做但人工跑很烦"的长任务

它们都踩中了个人提效最关键的两点:

  • 把"长任务"交给 Agent 去跑:单次一两分钟的事人做无所谓,但一件事要连做 5、6 步才有结果,就是 Agent 该接手的时机——流水线一旦搭好,每次调用都是边际成本极低的收益
  • 把"重复操作"从自己身上剥离:每天都要跑的 Review / 每次发版都要做的反编译 / 每周都要整理的日报……这些动作积少成多就是你一半的精力,交给壳程序后,你能把时间真正花在只有你能做的事情上

而 ACP 在整件事里的位置,是让"编排多 Agent"这件事从一个工程难题变成一段 orchestration 代码。没有 ACP,你得为每家 Agent 写一套对接;有了 ACP,不同 Agent 可以像乐高一样按成本 / 效果组合,工作流稳稳沉淀在你自己的壳程序里,引擎随时可以换——这也是我为什么说,真正值得你攒的不是某个 Agent,而是你自己那套"能把 Agent 编排起来"的壳程序

在你的壳程序里实现一次 ACP Client,就能像换引擎一样,随时接入 Claude Code、Codex、Gemini CLI 等各类 CLI 型 Agent,无需为每家单独做适配。

七、总结

ACP 的价值,本质上就是把 Agent 生态里的 N × M 适配压成了 N + M:让强大的 Agent 成为可随时替换的"引擎",让每个人都能安心去攒自己的"壳程序"。而真正值得沉淀的,也从来不是某个具体的 Agent,而是你围绕自己工作流编排出来的那一整套自动化能力——引擎可以随时换新,壳程序才是属于你自己的长期资产。