Agent 协议怎么选:一张工程分层地图

25 min

最近 Agent 协议一下子多了起来。MCP、Skills、A2A、ACP、AG-UI、A2UI、AP2、UCP、ARD、ANP,名字摆在一起,很容易让人误以为它们在解决同一个问题。

其实不是。它们更像一条工程链路上的不同接口:用户从前端或 IDE 发起任务,Agent runtime 负责规划和执行,中途会调用工具、加载技能,必要时把任务交给别的 Agent;如果任务涉及开放发现、交易和支付,还会多出目录、信任、授权和审计。

所以我不会先问”哪个协议最流行”,而是先问一句:它在 Agent 系统的哪一层?

先看地图:

flowchart LR
    U["用户"] --> C["视图层<br/>AG-UI / A2UI / ACP"]
    C --> R["Agent Runtime"]
    R --> K["能力层<br/>MCP / Skills"]
    K --> S["外部系统<br/>数据库 / SaaS / 内部 API"]

    R -.-> A["协作层<br/>A2A"]
    D["发现层<br/>skills.sh / MCP Registry / ARD / ANP"] -.-> K
    R -.-> O["观测层<br/>OTLP"]
    R --> T["业务层<br/>UCP / AP2"]
    T --> B["商家 / 支付 / 订单"]

这张图只保留几条关键线:视图层回答”用户怎么参与”;能力层回答”Agent 能调用什么”;协作层处理 Agent 之间的委托;发现层回答”能力从哪里来,能不能信”;观测层把过程串起来。UCP 和 AP2 这种业务层协议,则等任务真的进入交易场景时才需要。

一、快速选型参考

先按你遇到的问题选,不要按协议热度选:

工程问题分层优先看什么什么时候不需要
前端要展示 Agent 状态、工具调用、用户确认、中断视图层AG-UI只有一个普通聊天框,SSE/WebSocket 自己约定也够
Agent 要返回卡片、表单、按钮,但不能让模型吐任意 JSX视图层A2UIUI 很固定,前端自己写死即可
IDE 想接不同 Coding Agent,统一会话、diff、权限确认视图层ACP只是运行一个 CLI,不需要深度编辑器集成
Agent 要查库、读文件、调内部 API能力层MCP只有一两个固定 HTTP API,普通 tool calling 更简单
一套操作经验要复用给不同 Agent,比如 Vercel 优化、React 性能审查能力层Agent Skillsskills.sh只是单个函数调用,不需要打包知识和流程
MCP Server 太多,客户端不想分别配置、认证、监控能力层MCPHub / MCP Gateway只有一个 MCP Server
一个 Agent 要把任务交给另一个独立 Agent协作层A2A只是同一进程里的几个工具函数
Agent 要动态发现 MCP Server、Skills、Agent、OpenAPI 工具发现层MCP RegistryARD能力清单很小,手工配置即可
Agent 要完成购物、结账、支付、售后业务层UCP + AP2不碰交易和支付
想做开放 Agent 网络里的身份、发现、加密通信发现层ANP只需要静态内部目录时,内部 catalog 更简单
想追踪一次 Agent run 里模型、工具、检索、子 Agent 的耗时和错误观测层OpenTelemetry / OTLPDemo 或一次性脚本,普通日志先够用

下面按这几层展开。

二、视图层:用户怎么和 Agent 一起工作

这里不是模型能力,也不是工具调用。它解决的是用户界面和 Agent runtime 之间怎么协作。

1. AG-UI:前端和 Agent 后端之间的事件流

AG-UI 的定位是开放、轻量、事件驱动的协议,用来标准化用户前端和 Agent 后端的连接。它关心任务状态、文本增量、工具调用、用户确认、中断和共享状态。

一个长任务 Agent App 里,AG-UI 的位置大概是这样:

graph LR
    U["用户点击生成报价单"] --> FE["前端"]
    FE -->|"AG-UI run input"| AG["Agent Runtime"]
    AG -->|"AG-UI events"| FE
    FE -->|"展示状态、工具调用、确认按钮"| U
    U -->|"确认、中断、修改参数"| FE
    FE -->|"AG-UI user action"| AG

你可以把它理解成 Agent App 的”前后端事件合同”。没有 AG-UI,很多团队会自己发明一堆事件名:message_deltatool_startedhuman_approval_requiredrun_cancelled。短期能跑,长期就会变成每个 Agent 后端一套前端适配。

一个简化的事件可能长这样:

{
  "type": "tool_call_start",
  "runId": "run_42",
  "toolCallId": "call_weather",
  "toolName": "get_weather",
  "args": { "city": "Hangzhou" }
}

实现时别把 AG-UI 当成”聊天流换皮”。它真正适合的是长任务:用户能看见 Agent 正在做什么,能在关键步骤确认,也能中断。

2. A2UI:Agent 只给 UI 描述,不给可执行代码

A2UI 解决的是另一个问题:Agent 怎么生成可交互界面,但又不直接生成任意 HTML/JSX。Google 的介绍里强调过一点:A2UI 是声明式数据格式,不是可执行代码;客户端维护可信组件目录,Agent 只能请求渲染这些组件。

这比”让模型返回一段 React 代码”安全得多。一个 A2UI payload 可以像这样:

{
  "surfaceId": "checkout",
  "components": [
    {
      "id": "confirm-card",
      "component": "PaymentConfirmationCard",
      "props": {
        "merchant": "Acme Store",
        "amount": 129.99,
        "currency": "USD",
        "primaryAction": "confirm_payment"
      }
    }
  ]
}

客户端看到 PaymentConfirmationCard 后,决定能不能渲染、用哪个本地组件渲染、按钮点击后发什么事件。Agent 只描述意图,不碰前端执行环境。

AG-UI 和 A2UI 可以一起用:AG-UI 负责通道和事件,A2UI 负责某些事件里携带的 UI 描述。

3. ACP:编辑器怎样接入 Coding Agent

ACP(Agent Client Protocol)是 Zed 推出的编辑器/IDE 与 coding agents 通信协议。它假设用户主要待在编辑器里,Agent 可以是本地子进程,也可以是远程服务。

ACP 关心的是这些东西:

  • 会话和 prompt 如何传给 Agent。
  • Agent 的流式输出如何展示在编辑器面板里。
  • 文件 diff、补丁、工具调用如何展示。
  • 用户怎样确认 shell、文件写入、MCP 工具配置。

这和 A2A 不同。ACP 是”编辑器客户端到 Coding Agent”;A2A 是”Agent 到 Agent”。VS Code、Zed、JetBrains、Neovim 这类编辑器里的 Agent 面板更适合看 ACP;普通 Web App 里的聊天式 Agent,更贴近 AG-UI。

注意:历史上 IBM / BeeAI 也有一个 Agent Communication Protocol,同样缩写 ACP,但那个方向已经并入 Linux Foundation 旗下的 A2A 生态。现在说编辑器里的 ACP,通常指 Zed 的 Agent Client Protocol。

三、能力层:Agent 到底能做什么

Agent 本身只是推理和决策循环。真正让它有用的是接入外部系统、工具、文档、脚本和团队经验。

1. MCP:把工具、资源和提示词接进来

MCP(Model Context Protocol)是连接 AI 应用和外部系统的开放标准。官方文档里常见的三个 server 能力是 tools、resources、prompts:

概念怎么理解
Host用户正在使用的 AI 应用,比如 IDE、桌面客户端、Agent 平台
ClientHost 里负责连接 MCP Server 的部分
Server暴露工具、资源、提示词的服务
Tools可执行动作,比如查库、发请求、创建 issue
Resources可读取上下文,比如文件、文档、记录
Prompts可复用任务模板

用官方 TypeScript SDK 写一个最小 MCP tool,大概是这样:

import { McpServer } from '@modelcontextprotocol/server'
import { StdioServerTransport } from '@modelcontextprotocol/server/stdio'
import * as z from 'zod/v4'

const server = new McpServer({
  name: 'order-server',
  version: '1.0.0',
})

server.registerTool(
  'get_order',
  {
    description: '按订单号查询订单摘要。',
    inputSchema: z.object({
      orderId: z.string(),
    }),
  },
  async ({ orderId }) => ({
    content: [
      {
        type: 'text',
        text: JSON.stringify({
          orderId,
          status: 'paid',
          total: 129.99,
        }),
      },
    ],
  }),
)

const transport = new StdioServerTransport()
await server.connect(transport)

这个例子很小,但边界已经出来了:MCP Server 暴露一个命名稳定、schema 明确的工具;Host/Client 决定什么时候把这个工具提供给模型;模型只看到工具描述和参数 schema,不需要知道后面是数据库、HTTP API 还是一段脚本。

落地时,MCP 的重点不是”我支持了多少工具”,而是权限边界。一个 MCP Server 如果暴露了 run_shell_commanddelete_filesend_emailupdate_database 这类工具,就已经进入高风险区域。我会设几条底线:工具名和 schema 要稳定,别让模型猜参数;高风险工具默认需要确认;读写权限分开;工具返回要短而结构化;每次工具调用都要能审计。

MCP 是 Agent 的手,不是 Agent 的同事。

2. Skills:把工具、知识和流程打包成可复用能力

Skills 解决的不是”怎么通信”,而是”怎么把一套会做事的方法交给 Agent”。

Agent Skills 的基本格式很简单:一个目录,里面必须有 SKILL.md。可选地再放脚本、参考文档、模板和资产。

一个客服退款 Skill 可能长这样:

refund-support/
├── SKILL.md
├── scripts/
│   └── validate-refund.ts
├── references/
│   ├── refund-policy.md
│   └── escalation-rules.md
└── templates/
    └── customer-reply.md

SKILL.md 可以写成这样:

---
name: refund-support
description: 处理客服退款请求。适用于判断退款资格、生成客服回复、必要时升级给人工。
---

先读取 references/refund-policy.md。
如果订单超过 30 天,除非商品损坏,否则不要直接退款。
高于 500 美元的退款必须升级给人工。

需要校验订单状态时,调用 MCP 工具 get_order。
需要创建退款时,先运行 scripts/validate-refund.ts,再调用 create_refund。

这和 MCP Tool 的粒度完全不同:

概念粒度举个例子
MCP Tool一个可调用动作get_ordercreate_refundsend_email
Skill一套完成任务的方法”处理客服退款”,里面包含政策、脚本、工具调用顺序、升级规则

skills.sh 可以理解成 Skill 生态里的包目录。Vercel 的 Agent Skills 文档vercel-labs/agent-skills 就是很好的例子:vercel-react-best-practices 不是一个 API,也不是一个 MCP Server,而是一组 React/Next.js 性能和架构经验,给 coding agent 在写代码或审查代码时加载。

安装方式也接近包管理器:

npx skills add vercel-labs/agent-skills --skill vercel-react-best-practices

什么时候该用 Skills?一个判断很简单:如果你发现自己在不同 Agent 里反复解释同一套项目规约、调试步骤、发布流程、代码审查标准,就该把它变成 Skill。MCP 给 Agent 手,Skills 给 Agent 工作手册。

四、协作层:什么时候需要 A2A

A2A(Agent2Agent Protocol)的目标是让不同供应商、不同框架、不同平台里的 Agent 可以互相通信、交换状态、协调任务。规范里常见的核心概念包括 Agent Card、Task、Message、Artifact。

A2A 的价值只在一种情况下明显:系统里真的有多个独立 Agent。

不要把一个 Agent 里的几个函数拆成 A2A。也不要为了显得”多 Agent”就拆。A2A 适合的是这种边界:

graph LR
    PM["项目管理 Agent"] -->|"A2A Task"| Code["代码 Agent"]
    PM -->|"A2A Task"| Data["数据分析 Agent"]
    PM -->|"A2A Task"| Docs["文档 Agent"]
    Code -->|"Artifact: PR"| PM
    Data -->|"Artifact: report.csv"| PM
    Docs -->|"Artifact: spec.md"| PM

判断要不要 A2A,我会问三个问题:

  1. 对方是不是独立运行、独立部署、独立拥有权限边界的 Agent?
  2. 任务是不是需要生命周期,比如排队、执行中、等待用户、完成、失败、取消?
  3. 结果是不是需要作为 artifact 被另一个系统消费,而不只是返回一段文本?

如果答案都是”是”,A2A 才真正合适。

一个简化的 Agent Card 可以像这样:

{
  "name": "code-review-agent",
  "description": "审查 GitHub PR,返回风险列表和可操作建议。",
  "url": "https://agents.example.com/code-review",
  "skills": [
    {
      "id": "review_pull_request",
      "name": "Review Pull Request",
      "description": "输入仓库和 PR 编号,输出审查报告。"
    }
  ],
  "capabilities": {
    "streaming": true,
    "pushNotifications": false
  }
}

A2A 允许远端 Agent 保持黑盒。你能看到它能做什么、任务状态是什么、产物是什么,但不需要知道它内部用了哪些 MCP Server、哪些 prompt、哪套模型。跨团队、跨供应商协作时,暴露接口比暴露内部实现现实得多。

五、发现层:能力从哪里来

早期 Agent 系统通常把工具写死在配置里。小系统可以这么干,企业里很快就会出问题:工具、MCP Server、内部 Agent、Skills、OpenAPI 越来越多,Agent 怎么知道现在有哪些能力可用?怎么判断哪个可信?怎么避免所有能力都塞进上下文?

1. Skills 目录:给可复用能力找入口

skills.sh 是 Vercel 推出的 Agent Skills 目录和 leaderboard。Vercel changelog 里给的定位很直白:skills 是安装和管理 skill packages 的 CLI,skills.sh 是发现 skill packages 的目录。

这类目录解决的是”我需要一个现成工作手册”。比如:

  • 做 React/Next.js 性能审查,可以找 vercel-react-best-practices
  • 做 UI 审计,可以找 web-design-guidelines
  • 做 Vercel 成本优化,可以找 vercel-optimize

2. MCP Registry 和社区目录:让 MCP Server 可发现、可管理

当 MCP Server 多起来,问题会从”怎么写一个 server”变成”怎么发现、管理、路由、审核这些 server”。这里至少有三类东西:

类型代表解决什么
官方元数据注册表MCP Registry公开 MCP Server 的元数据、命名空间、安装信息
社区目录/市场mcp.so、mcpservers.org、LobeHub MCP搜索、筛选、评分、安装指引
本地/企业 Hub 或 GatewayMCPHub、mcp-hub、内部网关管理多个 MCP Server,向客户端暴露一个统一 endpoint

官方 MCP Registry 承载 metadata,不承载实际代码。MCPHub 这类项目是运行时管理器——多个 MCP Server 接进去,客户端只连一个 /mcp endpoint,Hub 负责命名空间、路由、认证和状态管理。

从发现到调用的完整链路:

graph LR
    REG2["MCP Registry<br/>公开元数据"] --> MARKET["目录 / 市场<br/>mcp.so、mcpservers.org"]
    MARKET --> DEV["开发者筛选和安装"]
    DEV --> HUB2["MCPHub / 企业 MCP Gateway"]
    CLIENT["Claude / Cursor / Codex"] --> HUB2
    HUB2 --> S1["GitHub MCP"]
    HUB2 --> S2["Postgres MCP"]
    HUB2 --> S3["内部 API MCP"]

一个企业里的实际部署:

graph LR
    C["Claude / Cursor / Codex"] --> HUB["MCPHub / 企业 MCP Gateway"]
    HUB --> FS["filesystem MCP"]
    HUB --> GH["GitHub MCP"]
    HUB --> PG["Postgres MCP"]
    HUB --> CRM["内部 CRM MCP"]
    REG["MCP Registry / 内部目录"] -.-> HUB

3. ARD:更通用的 Agentic Resource Discovery

ARD(Agentic Resource Discovery)是更通用的发现协议。Google 的介绍里说,一个 provider 可以在自己的域名下发布 ai-catalog.json,catalog 里可以列 MCP servers、A2A agents、OpenAPI tools,甚至其他 catalog。Agent 发现资源后,再用对应的原生协议连接。

这和 MCP Registry 的区别在于范围:MCP Registry 主要围绕 MCP Server 元数据;ARD 试图发现所有 Agentic resources。你可以把 ARD 看成”能力目录协议”,它不替代 MCP/A2A/OpenAPI,而是在调用之前回答:

  • 这个组织公开了哪些 Agent 能力?
  • 发布方是谁,域名是否可信?
  • 这些能力应该用 MCP、A2A、OpenAPI 还是别的协议调用?

4. ANP:更远的开放 Agent 网络设想

ANP(Agent Network Protocol)目标更大,关注开放 Agent 网络里的身份、发现、消息、安全通信,甚至支付。在这张地图里,它更接近发现层和信任边界,不是工具调用协议。

六、业务层:Agent 开始花钱时,协议会变严肃

只要 Agent 不碰交易,很多系统还能靠用户确认和日志兜底。一旦 Agent 可以代表用户购物、下单、付款,责任链就必须清楚。

1. UCP:商品、库存、购物车、订单

UCP(Universal Commerce Protocol)覆盖的是完整商业流程:商品发现、库存、购物车、结账、订单、售后。Google 的 UCP 技术介绍也提到,它支持 REST、MCP、A2A 等多种绑定方式。

UCP 不是支付协议。它更像 Agent 和商家系统之间的商业语言。

一个购物 Agent 可能先用 UCP 做这些事:

{
  "capability": "search_products",
  "query": "适合剪 4K 视频的笔记本",
  "constraints": {
    "maxPrice": 2000,
    "currency": "USD",
    "delivery": "today"
  }
}

2. AP2:授权、凭证、收据、争议证据

AP2(Agent Payments Protocol)关心的是 Agent 参与支付时怎么证明授权和交易事实。Google Cloud 的介绍强调 mandates,也就是可验证、可签名的授权材料。

AP2 想回答的问题很具体:

  • 用户到底授权了什么?
  • Agent 有没有超出预算、时间、商品条件?
  • 商家看到的 checkout 和用户确认的是不是同一件事?
  • 支付凭证、收据、争议证据在哪里?
  • 人不在场的自动购买,约束条件怎么被验证?

UCP 和 AP2 的关系可以这样理解:

graph LR
    USER2["用户:帮我买一台电脑"] --> AGENT2["购物 Agent"]
    AGENT2 -->|"UCP: 搜索商品、查库存、建购物车"| MERCHANT["商家系统"]
    AGENT2 -->|"A2UI: 展示候选商品和确认卡片"| USER2
    USER2 -->|"确认预算和商品约束"| AGENT2
    AGENT2 -->|"AP2: mandate、支付凭证、收据"| PAY["支付网络"]
    AGENT2 -->|"UCP: 订单状态、售后"| MERCHANT

UCP 管”怎么买、买什么、订单怎么跑”;AP2 管”谁授权、怎么付款、争议时怎么证明”。涉及钱的 Agent,必须把这两件事分开。

七、观测层:任务出问题时怎么追(OTLP)

观测层不是 Agent 专属,但 Agent 一进生产,它就绕不开。

传统后端出问题,通常还能从接口状态码、日志和数据库记录里往回查。Agent 麻烦一点:它可能是模型选错工具、MCP Server 超时、检索拿错文档、A2A 子任务卡住,也可能是用户确认和支付授权之间断了。只看最后一句回答,很难知道错在哪里。

OpenTelemetry 是通用的可观测性框架,覆盖 traces、metrics、logs。OTLP 则定义这些遥测数据怎么从应用、collector 送到后端。在 Agent 系统里,可以把一次 agent.run 当成一条 trace,把模型调用、MCP 工具调用、检索、A2A 委托、支付授权都记成 span:

trace agent.run run_id=run_42
  span llm.call model=gpt-5.5
  span mcp.tool_call server=postgres tool=query_orders
  span retrieval.search source=knowledge_base
  span a2a.task target=research-agent
  span ap2.mandate.create

如果你关心 LLM/Agent 里的字段怎么命名,可以看 OpenTelemetry GenAI Semantic ConventionsOpenInference。它们不是传输协议,而是给模型调用、工具调用、检索、token、prompt 这些字段一套更统一的描述方式。

八、几种真实架构组合

前面的分层只是框架。落到工程里,通常会组合使用。

1. Coding Agent / IDE

graph LR
    IDE["Zed / VS Code / JetBrains"] -->|"ACP"| CA["Coding Agent"]
    CA -->|"加载"| S["Skills<br/>react-best-practices、deploy-to-vercel"]
    CA -->|"MCP"| HUB3["MCPHub / MCP Gateway"]
    HUB3 --> GH["GitHub MCP"]
    HUB3 --> FS["Filesystem MCP"]
    HUB3 --> CI["CI / Logs MCP"]

这套组合里,ACP 管编辑器体验,Skills 管工程经验,MCP 管外部工具。A2A 只有在 Coding Agent 要把任务交给另一个独立 Agent 时才需要,比如”把性能分析交给一个 observability Agent”。

2. 企业知识 Agent

graph LR
    FE2["员工前端"] -->|"AG-UI"| KA["知识 Agent"]
    KA -->|"加载"| KS["企业问答 Skill"]
    KA -->|"MCP"| HUB4["MCPHub / 企业 MCP Gateway"]
    HUB4 --> CF["Confluence"]
    HUB4 --> GD["Google Drive"]
    HUB4 --> PG["Postgres"]
    HUB4 --> API["内部 API"]
    DIR["内部 MCP Registry / ARD Catalog"] -.-> HUB4

这里关键是 MCP 和权限治理。知识 Agent 的价值来自读取内部资料、调用内部系统、生成可验证回答。AG-UI 负责让前端展示流式回答、检索来源、工具调用状态和用户确认。

不要一开始就拆成十个 Agent。先确认一个 Agent + MCP + Skills 是否够用。如果法务、财务、数据分析确实都有独立权限边界和任务生命周期,再加 A2A。

3. 多 Agent 自动化工作流

graph TB
    U3["用户"] -->|"AG-UI"| PA["规划 Agent"]
    PA -->|"A2A"| RA["研究 Agent"]
    PA -->|"A2A"| DA["数据分析 Agent"]
    PA -->|"A2A"| WA["写作 Agent"]
    PA -->|"A2A"| RV["审校 Agent"]
    RA -->|"MCP"| WEB["浏览器 / 搜索"]
    DA -->|"MCP"| DB["数据库"]
    WA -->|"Skills"| STYLE["写作风格 Skill"]
    RV -->|"MCP"| DOCS["文档库"]

这类系统很容易失控。A2A 可以帮你传任务和状态,但不会自动帮你设计组织结构。每个 Agent 都要有明确的输入、输出、退出条件和权限边界。

4. Agent 购物 / 支付

graph LR
    UI["购物前端"] -->|"AG-UI"| SHOP["购物 Agent"]
    SHOP -->|"UCP"| MERCHANT2["商家 / 商品 / 库存 / 订单"]
    SHOP -->|"A2UI"| UI
    SHOP -->|"AP2"| PAYMENT["支付授权 / 凭证 / 收据"]

UI 也很关键。用户应该看到商品、价格、配送、预算约束和支付确认,而不是只看到一句”我帮你买好了”。涉及钱的 Agent,授权边界必须成为界面的一部分。