Agent Client Protocol 初学习

Published 2026-06-06 12:36 2642 words 14 min read

This post is not yet available in English. Showing the original.
认识 Agent Client Protocol 什么是 Agent Client Protocol? Agent Client Protocol(简称 ACP)是一种专门用于 AI Agent 与客户端(编辑器、IDE、终端、Web 应用等)之间通信的开放协议,用来规范 AI 编码智能体与代码编辑器 / IDE 等客户端之间如何交互、同步状态和下发命令。 简单来说,ACP...

认识 Agent Client Protocol

什么是 Agent Client Protocol?

Agent Client Protocol(简称 ACP)是一种专门用于 AI Agent 与客户端(编辑器、IDE、终端、Web 应用等)之间通信的开放协议,用来规范 AI 编码智能体与代码编辑器 / IDE 等客户端之间如何交互、同步状态和下发命令。

简单来说,ACP 定义了一套统一的通信标准,让任何支持 ACP 的编辑器都可以连接任何支持 ACP 的 AI Agent。

ACP 的核心目标,是让任何代码编辑器可以连接任何 AI 编码智能体,通过一套统一协议完成会话管理、能力协商、状态同步和操作执行,解决的就是 “编辑器如何与 AI 编码代理通信” 的问题。

例如 VS Code、Cursor、Windsurf、JetBrains IDE、自研 IDE 等等类似的产品都属于 Client(客户端),而 Claude Code、OpenAI Codex Agent、Gemini CLI、Aider、自研 Coding Agent 都属于 Agent,ACP 就是他们之间通信连接的“通用语言”。

为什么会产生 Agent Client Protocol?

在 ACP 出现之前:

VS Code   <--私有协议-->  Claude Code
Cursor    <--私有协议-->  Claude Code
JetBrains <--私有协议-->  Claude Code
Windsurf  <--私有协议-->  Claude Code

每一个编辑器都要单独适配 Claude Code、单独适配 Codex、单独适配 Gemini …,而每个 Agent 也要:单独支持 VS Code、单独支持 Cursor、单独支持 JetBrains …,产生出 N × M 个适配问题,可以想象如果没有一个统一的通信协议,这些 Client(客户端)和 Agent 之间通信连接的建立与维护,成本都是极高的。

同时,AI 智能体任务越来越长时、多步、需要频繁读写文件、调用终端,缺少统一协议会导致过程不可观测、结果不可复现、权限控制混乱,就难以满足企业落地和团队协作的需求。

以上这些问题正是 ACP 产生的根本原因:

AI 编码智能体越来越强大,而编辑器与智能体之间缺少统一标准,导致生态割裂、重复适配成本高。ACP 通过定义 Agent 与 Client 的标准通信协议,实现 “任意客户端连接任意 Agent” 的互操作能力。

理解 Agent Client Protocol

理解 ACP,最重要的不是把所有 method 名背下来,而是抓住它的几个核心概念和流程

Client 和 Agent:谁负责什么?

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

  • Client(客户端)
    • 典型角色:VS Code、JetBrains、Zed、Neovim 插件、自研 Web IDE、命令行工具等。
    • 职责:
      • 与用户交互(UI、输入输出)。
      • 掌控本地能力:文件系统、终端/命令执行、网络访问、弹窗等。
      • 决定是否给 Agent 授权执行某些操作,并记录日志做审计。
  • Agent(智能体)
    • 典型角色:一个使用大模型的编码助手服务,可以运行在本地进程或远程服务器。
    • 职责:
      • 理解用户需求、分析代码、规划修改方案。
      • 通过 ACP 请求 Client 提供所需的环境能力(读文件、写文件、运行测试等)。
      • 以流式消息、事件形式把思考过程和结果反馈给 Client。

两者之间通过 ACP 交流,一端发 JSON‑RPC 请求/通知,一端响应或推回事件,形成一个完整的事件流。

JSON‑RPC 是什么?

JSON‑RPC 的核心概念

JSON‑RPC(JavaScript Object Notation Remote Procedure Call):

  • 是一种基于 JSON 的远程过程调用协议本质是用 JSON 来描述“调用某个远程函数”的请求和结果
  • 它不规定我们调用时必须用什么传输层(可以是 HTTP、WebSocket、TCP、自定义管道甚至标准输入输出),只规定消息的格式
  • 目标是让两个进程/服务之间的通信看起来就像是本地函数调用
    • 指定方法名(method)
    • 传入参数(params)
    • 得到返回值(result 或 error)

我们可以把它当成用 JSON 写的 RPC 协议,和 REST 那种资源 + HTTP 动词风格不太一样,它更偏向直接调用函数

JSON‑RPC 的三种消息类型

在 JSON‑RPC 2.0 里,有三种核心消息形式:

  1. 请求(Request)

    • id 字段。

    • 结构大致是:

      {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "someMethod",
        "params": { "foo": "bar" }
      }
    • 含义:我要调用你那边名为 someMethod 的方法,参数是 params,请给我一个响应。

  2. 响应(Response)

    • 必须带上对应请求的 id

    • 成功时包含 result,失败时包含 error

      {
        "jsonrpc": "2.0",
        "id": 1,
        "result": { ... }
      }

      {
        "jsonrpc": "2.0",
        "id": 1,
        "error": { "code": -32602, "message": "Invalid params" }
      }
  3. 通知(Notification)

    • 没有 id,表示不需要响应

    • 结构类似请求:

      {
        "jsonrpc": "2.0",
        "method": "log",
        "params": { "level": "info", "message": "hello" }
      }
    • 场景:发日志、发进度事件、发状态变更,不需要对方回一个响应。

JSON‑RPC 的几个特点
  • 轻量:消息就是 JSON,易读易调试。
  • 无状态:协议层不强制会话概念(像 ACP 这样需要会话,会自己在 params 里带 sessionId)。
  • 双向:只要底层连接是双向(如 WebSocket / stdio),双方都可以当「客户端」发请求,对方当「服务端」响应。
  • 支持批量调用:可以一次发一个 JSON 数组,里面多个请求一起处理。

初始化与能力协商

ACP 一切交互的起点是 initialize

当 Client 启动并连接到一个 ACP Agent 时,它会先发送一个 initialize 请求,用来协商:

  1. 协议版本(protocolVersion)
  2. 彼此支持的能力和扩展
  3. 协商身份验证方法
  4. 一些基础元信息(客户端名称、Agent 名称等)

这一步的意义在于:

  1. 避免版本不兼容:比如 Client 是 v1,Agent 是 v2,就可以在这里检测并处理。
  2. 让双方提前知道对方支持哪些扩展功能,比如是否支持某种文件系统 API、是否支持多 Agent 协作等。

写在代码层,我们基本可以抽象成一个 acpClient.initialize() 的高层调用,之后所有方法都建立在这一步成功的前提下。

这其实就是相当于在让客户端和智能体建立连接,连接建立后,我们可以进行身份认证,然后创建会话并开始与智能体的对话。

更详细信息的可查看官方文档:https://agentclientprotocol.com/protocol/v1/initialization

会话管理:session 是一条「长期关系」

ACP 里有一个非常重要的概念:session(会话)

  • Client 会调用 session/new 创建一个新的会话,通常会附带一些上下文信息,比如当前工作目录、项目路径、打开的文件列表等。
  • 返回的 sessionId 用来标识接下来的一整段交互(类似一个长期聊天频道),后续的所有 prompt、工具调用、状态更新都挂在这个 session 下面。

可以这样类比:

如果说 HTTP 请求偏向于一次性的动作交换,那么 ACP 的 session 更像是一个长期的工作房间,你和 Agent 在同一个房间里做很多轮对话和修改。

在代码设计上,我们可以把 session 映射为一个对象,比如:

const session = await acpClient.newSession({ cwd: projectPath });
// 后续所有与这个项目相关的提示都用 session.id

这样我们的 UI 或后端可以轻松地把某个项目或某个 tab 绑定到一个 session 上面。

详细内容可见官方文档:https://agentclientprotocol.com/protocol/v1/session-setup

一次完整交互:prompt turn

在 session 之上,ACP 定义了一次完整往返的单位:prompt turn

官方的定义是:一次 prompt turn 是从用户发出一条消息开始,到 Agent 完成这一轮响应(或被终止)为止的完整交互周期。

官方文档:https://agentclientprotocol.com/protocol/v1/prompt-turn

在我们的真实项目中:

  • Client 通过 session/prompt 发起一次 prompt turn:
    • 指定 sessionId
    • 带上当前这一轮的用户消息(可以是文本、代码片段等富内容)
  • Agent 收到后开始工作,在这一轮期间会以事件流的方式不断往回推:
    • 流式输出 token / 分段消息(让你实现「打字机」效果)。
    • 工具调用请求(比如请求读文件、执行命令)。
    • 权限请求(例如想修改哪些文件)。
    • 进度和状态事件。
  • 当 Agent 觉得这轮结束了,会发一个「完成」的事件,该轮 turn 宣告结束,下一轮 prompt 可以开始。

我的理解就是,session/prompt 是 ACP 的函数调用,而 prompt turn 是这次调用从开始到结束的整个生命周期

为什么使用函数调用来打比方,是因为 ACP(以及底层的 JSON‑RPC)本质上就是:一端给另一端发 我要调用你某个方法 的请求,对方执行完再把结果返回

这个模式和我们在代码里写 someFunction(params) 很像,所以用函数调用来帮助理解协议里的一次请求与响应是什么关系。

所以,我们可以暂时先忘掉高级 AI 概念,只把 ACP 当作两段程序之间远程互相调函数的规则。

工具调用、文件系统和权限

强大的 Agent 必须能够操作环境:读写文件、运行测试、调用外部服务。ACP 在这里提供了一个统一的工具调用接口层,典型能力包括:

  • 文件系统(fs)相关方法:
    • 读取文件内容、列目录、写入或创建文件等。
  • 终端 / 命令执行:
    • 运行 npm testpytest、编译命令等,把 stdout/stderr 结果回给 Agent。
  • 权限请求:
    • Agent 不直接「悄悄改文件」,而是通过类似 session/request_permission 请求,告知我想修改 A、B、C 这几个文件,由 Client 弹窗给用户确认,然后再执行。

这一层是 ACP 特别适合企业和团队场景的原因之一,它安全、可控、可审计,而不是让 Agent 获得完全不受控的本地能力。

官方文档:

总结

以上知识我在看 Agent Client Protocol 文档,了解学习 ACP 的一次初学习理解记录,如果想要深入,还是应该动手先跑一遍最小 demo,再实际中学习基础用法,然后再考虑将它落实道自己最熟悉的应用形态里面。但是以上提到的 ession + prompt turn + 事件流 + 工具调用,算是 ACP 的一个主线流程,我们可以先理解这个,再慢慢在实践中进行深入学习。

If you enjoyed this, leave a comment~