跳到主要内容

A2A(Agent2Agent)协议 — 架构与原理

30 秒导读: A2A 是一套开放协议,让不同公司、用不同框架、跑在不同服务器上的 AI agent 作为平等的“代理”互相通信——而不是把对方当成一个工具来调。它解决的核心问题是:A 公司的 agent 怎么发现 B 公司的 agent、看懂它会什么、把一个可能跑很久的任务安全地托付给它、并拿回结果——全程不需要 B 暴露自己的内部记忆、提示词或工具实现。


1. 这是什么(零基础也能懂)

一句话定义。 A2A 是“agent 之间打电话的通用语言”:一个 agent(客户端)能找到另一个 agent(服务端),读懂它的“名片”,然后给它发消息、让它干活、跟踪进度、取回成果。

它解决谁的什么问题。 设想一个场景:你做了一个“旅行规划 agent”,它自己不会订机票,但市面上有别家做的“订票 agent”。你希望你的 agent 能:

  1. 找到那个订票 agent 在哪、它支不支持你要的能力;
  2. 托付一句“帮我订一张去赫尔辛基的机票”,而不必关心对方内部用的是哪个大模型、调了哪些工具;
  3. 跟踪这个可能要跑几秒到几小时的任务,中途它若问“从哪个城市出发?”你还能回答;
  4. 安全地完成这一切——对方不需要把它的私有逻辑给你看,你也用标准的 Web 鉴权(OAuth、API key、mTLS)保护通道。

这正是 A2A 想标准化的东西。在它之前,每两个 agent 想协作都得现谈一套私有接口。

关键直觉:agent 是“黑盒”,不是“工具”。 这是 A2A 最重要的心智模型。被调用的远程 agent 对调用方是 opaque(不透明) 的——你看不到它的内存、提示词、工具。你只能通过协议规定的几个动作和它打交道。这跟“函数调用”式的工具协议(如 MCP)是两种取向:

MCP(Model Context Protocol)A2A(Agent2Agent)
把对方当成一个工具 / 资源(函数、API、数据源)一个对等的 agent(黑盒)
你需要知道它的输入 schema、输出 schema它会哪些“技能”、怎么连它
交互形态一次调用,拿结构化结果发消息 → 起任务 → 跟踪长跑 → 多轮协商
类比给机器人装一只(用某个能力)让两个机器人搭伙干活

两者互补:一个 A2A 服务端 agent 在内部很可能用 MCP 去调它自己的工具来完成你托付的任务(见 spec Appendix B,docs/specification.md:3598)。

用起来什么样。 最小的一次交互(REST 绑定),客户端 POST 一条消息,服务端直接返回一个已完成的任务,结果放在 artifact 里:

POST /message:send HTTP/1.1
Content-Type: application/a2a+json

{ "message": { "role": "ROLE_USER",
"parts": [{"text": "What is the weather today?"}],
"messageId": "msg-uuid" } }
{ "task": {
"id": "task-uuid", "contextId": "context-uuid",
"status": { "state": "TASK_STATE_COMPLETED" },
"artifacts": [{ "artifactId": "artifact-uuid", "name": "Weather Report",
"parts": [{"text": "Today will be sunny with a high of 75°F"}] }] } }

(两段都来自 spec 的 §6.1 示例,docs/specification.md:1308-1347。)

注意:这个仓库是“协议规范”,不是某个 SDK。 真相之源是一份 Protocol Buffers 定义 specification/a2a.proto,加上一份人读的规范 docs/specification.md。各语言 SDK(Python/Go/JS/Java/.NET/Rust)是另外的仓库(README.md:94-100)。本组文档讲的是协议本身:数据模型、操作语义、传输绑定。

2. 顶层全景(它大概怎么转)

A2A 里只有三个“角色”,围着一份“名片”和一个“任务”运转:

┌──────────┐ 1. 取 Agent Card(名片) ┌─────────────────────┐
│ User │ ────────────────────────────▶ │ A2A Server │
│ (人/服务)│ │ = Remote Agent │
└────┬─────┘ 2. SendMessage(发消息/起任务) │ (黑盒,不暴露内部) │
│ 代为 ────────────────────────────▶ │ │
▼ 行动 │ ┌───────────────┐ │
┌──────────┐ 3. 跟踪 Task: │ │ 内部:LLM/工具 │ │
│ A2A │ · 轮询 GetTask │ │ (可能用 MCP) │ │
│ Client │ ◀── · 流 SendStreamingMessage │ └───────────────┘ │
│(Client │ · push 通知到 webhook └─────────────────────┘
│ Agent) │ 4. 取回 Artifacts(成果)
└──────────┘

怎么读这张图: 左边 Client 代表 User 发起,右边 Server 是被托付的远程 agent;箭头 1→4 是一次协作的时间顺序。Server 内部对 Client 完全黑盒。

几个核心部件,一句话职责:

部件干什么在哪定义(proto)
Agent Cardagent 的“名片 / 自描述清单”:身份、能力、技能、端点、鉴权要求AgentCard,specification/a2a.proto:361
Task一个有状态、有生命周期的“工作单元”,核心动作单位Task,specification/a2a.proto:167
Message一来一回的一“轮”通信,带 role(user/agent)Message,specification/a2a.proto:260
Part消息/产物里的内容容器:文本 / 文件 / 结构化 JSONPart,specification/a2a.proto:224
Artifact任务产出的“成果物”(文档、图片、数据)Artifact,specification/a2a.proto:280
A2AService11 个 RPC:发消息、查/列/取消任务、push 配置、扩展名片service A2AService,specification/a2a.proto:19

主线走一遍(高层):

  1. 发现。 Client 先拿到 Server 的 Agent Card(常见做法:GET https://域名/.well-known/agent-card.json)。名片里写明端点 URL、支持哪些技能、要哪种鉴权。
  2. 发消息。 Client 调 SendMessage,把一条 Message(含若干 Part)发过去。
  3. 服务端二选一回应。 要么立刻回一条 Message(简单问答),要么起一个 Task 并返回它(需要长跑/有状态)。
  4. 跟踪 + 取回。 若是 Task,Client 用轮询 / SSE 流 / push 通知三种方式之一跟踪它的状态机,直到终态,然后从 Task.artifacts 取回成果。

3. 阅读地图(建议顺序)

本组文档按“由浅入深”拆成四章。建议顺序如下:

  1. 01 · 发现与 Agent Card —— 一切的起点。名片里有什么、客户端怎么找到它(well-known URI / 注册表 / 直配)、以及怎么用 JWS 签名让名片可验真。
  2. 02 · Task 生命周期 —— 协议的“心脏”。Task 的 8 态状态机、什么时候回 Message 什么时候回 Task、contextId 怎么把多个任务串成一次会话、任务为何不可变。
  3. 03 · 传输与绑定 —— A2A v1.0 的关键设计:一份 proto 是唯一真相,绑定到 JSON-RPC、gRPC、REST 三种传输,且必须功能等价。讲清楚 ProtoJSON、camelCase 约定、方法/错误码映射表。
  4. 04 · 流、异步与安全 —— 长跑任务怎么实时推送(SSE)、断线怎么用 push 通知 webhook 兜底、错误分类、以及企业级安全(SSRF 防护、回放攻击、鉴权)。

4. 巧妙之处(本组文档的“精华”预告)

  • proto 当唯一真相,而非 gRPC 专用文件。 v1.0 把 a2a.proto 从“gRPC 的实现细节”提升为所有绑定的规范源(docs/whats-new-v1.md 主题 1)。JSON 序列化遵循 ProtoJSON——这让三种传输天然语义一致。
  • “黑盒 agent”的强约束。 安全错误里明确要求“不得泄露客户端无权访问的资源是否存在”(docs/specification.md:514:527),把不透明性写进了协议而非靠实现自觉。
  • 任务不可变 + 同 context 多任务。 任务到终态就冻结,任何“改一改”都开新任务挂在同一个 contextId 下(docs/topics/life-of-a-task.md:82)——换来干净的输入→输出溯源和并行 follow-up。
  • 名片签名要先“规范化”。 签 Agent Card 前必须按 RFC 8785(JCS)规范化,并按 proto 的字段存在性语义决定哪些默认值字段要删——否则重建出来的名片对不上签名(docs/specification.md:2006-2056)。

5. 代码地图(导航索引)

主题文件符号 / 锚点
唯一真相:全部数据模型 + RPCspecification/a2a.protoservice A2AServicemessage Taskmessage AgentCard
人读规范(全文)docs/specification.md§3 操作语义、§5 绑定等价、§8 名片
核心概念速查docs/topics/key-concepts.md“Fundamental Communication Elements” 表
任务生命周期叙事docs/topics/life-of-a-task.md“Task Immutability”、“Parallel Follow-ups”
发现策略docs/topics/agent-discovery.md“Discovery Strategies”
流 / 异步docs/topics/streaming-and-async.md“Streaming with SSE”、“Push Notifications”
v1.0 变更全貌docs/whats-new-v1.md“Overview of Major Themes”
A2A vs MCPdocs/specification.mdAppendix B(:3598)