A2A 是一个用于不同 Agent 之间通信与协作的开放协议。它要解决的问题是:一个 Agent 如何发现另一个 Agent、了解它的能力、向它提交任务、跟踪任务进度,并获取最终结果。
1. A2A 到底解决什么问题?
假设有两个 Agent:
- Agent A:负责接收用户需求、拆解任务和调度。
- Agent B:负责分析代码项目。
用户向 Agent A 提出需求:
帮我分析这个项目的架构。Agent A 不需要知道 Agent B 内部使用什么模型、什么框架,也不需要知道它内部有哪些工具。
它只需要通过 A2A:
- 找到 Agent B。
- 查看 Agent B 能做什么。
- 向 Agent B 发送任务。
- 获取 Agent B 的执行进度。
- 接收 Agent B 的最终结果。
整个过程:
用户 │ ▼Agent A │ │ 1. 发现 Agent B │ 2. 查看 Agent Card │ 3. 提交任务 │ 4. 获取任务进度 │ 5. 接收任务结果 ▼Agent B │ ▼执行任务 │ ▼返回结果核心思想:A2A 只规定 Agent 之间如何协作通信,不规定 Agent 内部如何执行任务。
2. Agent 如何发现另一个 Agent?
A2A 使用 Agent Card 描述一个 Agent。
可以把它理解为 Agent 对外公开的能力说明书。
2.1 Agent Card 是什么?
Agent Card 是一个 JSON 文档,通常包含:
| 字段 | 作用 |
|---|---|
| name | Agent 名称 |
| description | Agent 的介绍 |
| supportedInterfaces | 支持的通信接口、协议和版本 |
| capabilities | 支持的协议能力 |
| skills | Agent 能提供的具体技能 |
| securitySchemes | 支持的认证方式 |
| defaultInputModes | 默认支持的输入类型 |
| defaultOutputModes | 默认支持的输出类型 |
| version | Agent 自身的软件版本 |
例如:
{ "name": "Code Analysis Agent", "description": "负责代码分析和项目架构分析", "version": "1.0.0", "supportedInterfaces": [ { "url": "https://agent.example.com/rpc", "protocolBinding": "JSONRPC", "protocolVersion": "1.0" } ], "capabilities": { "streaming": true, "pushNotifications": true }, "defaultInputModes": [ "text/plain" ], "defaultOutputModes": [ "text/plain", "application/json" ], "skills": [ { "id": "code-analysis", "name": "代码分析", "description": "分析代码结构、依赖关系和项目架构", "tags": ["代码", "架构分析"], "examples": [ "分析这个项目的整体架构", "分析项目中的模块依赖" ] } ]}这里重点关注三个部分:
supportedInterfaces:如何连接?
告诉调用方 Agent B 的通信地址、使用什么协议绑定,以及支持哪个 A2A 协议版本。
capabilities:支持哪些协议功能?
例如:
- streaming:是否支持流式通信。
- pushNotifications:是否支持任务推送通知。
- extendedAgentCard:是否支持经过认证后获取扩展 Agent Card。
skills:具体能做什么?
例如代码分析、文件处理、数据分析等。
NOTESkills 是能力描述,不代表 Agent 一定能成功完成每个任务。
2.2 去哪里获取 Agent Card?
A2A 提供了标准发现地址:
GET /.well-known/agent-card.json例如:
curl https://agent.example.com/.well-known/agent-card.json除了 Well-Known URI,还可以通过:
- Agent 注册中心(Registry)。
- 服务目录(Catalog)。
- 预先配置的 Agent Card 地址。
获取 Agent Card 后,客户端就可以根据 Skills、协议版本、通信地址和认证要求决定是否调用这个 Agent。
3. A2A 的核心数据结构
理解 A2A,最重要的是掌握下面几个对象。
3.1 Message:消息
Message 表示 Agent 之间的一次消息交互。
主要字段:
| 字段 | 作用 |
|---|---|
| messageId | 消息唯一标识 |
| role | 消息发送角色 |
| parts | 消息内容 |
| contextId | 所属对话上下文 |
| taskId | 关联的任务 ID |
例如:
{ "messageId": "msg-001", "role": "ROLE_USER", "parts": [ { "text": "帮我分析这个项目的架构" } ]}role 通常表示:
ROLE_USER:用户侧发出的消息。ROLE_AGENT:Agent 发出的消息。
3.2 Part:消息内容片段
Part 是 Message 或 Artifact 内部最小的内容单元。
它可以承载:
- 文本。
- 文件。
- 图片。
- 结构化数据。
例如文本:
{ "text": "分析项目架构"}例如文件内容引用:
{ "file": { "name": "project.zip", "uri": "https://example.com/project.zip" }}Part 不只是文本,因此 A2A 可以支持不同模态的数据交换。
实际传输文件时,也可以根据规范使用内嵌字节数据,而不是必须提供 URL。
3.3 Task:任务
Task 是 A2A 中非常重要的对象。
Message 表示一次消息交互,而 Task 表示一个需要被跟踪的工作过程。
例如:
Agent A:帮我分析这个项目。
Agent B:收到,开始分析。
Agent B:正在分析依赖关系。
Agent B:分析完成。这整个过程可以对应一个 Task。
Task 主要包含:
| 字段 | 作用 |
|---|---|
| id | 任务唯一标识 |
| contextId | 所属上下文 |
| status | 当前任务状态 |
| history | 任务相关消息历史 |
| artifacts | 任务产生的结果 |
| metadata | 附加元数据 |
3.4 Artifact:任务产物
Artifact 表示 Agent 执行任务后产生的结果。
例如:
- 一份 Markdown 分析报告。
- 一张图片。
- 一个生成的文件。
- 一段结构化 JSON 数据。
示例:
{ "artifactId": "artifact-001", "name": "架构分析报告", "parts": [ { "text": "# 项目架构分析\n\n项目采用前后端分离架构..." } ]}这里要区分:
- Message:通信消息。
- Task:正在执行或已经执行的任务。
- Artifact:任务产生的结果。
3.5 Context:上下文
contextId 用于把相关的消息和任务关联起来。
例如:
context-001 │ ├── Task 001:分析项目架构 │ ├── Task 002:分析项目依赖 │ └── Task 003:根据分析结果生成报告它主要用于多轮交互中的上下文关联。
NOTE
contextId本身不是记忆系统,也不会自动把一个 Agent 的内部对话历史、模型上下文或私有数据共享给另一个 Agent。
4. 如何向另一个 Agent 提交任务?
理解完数据结构,就可以看实际调用。
假设 Agent A 想让 Agent B 分析项目架构。
4.1 第一步:找到通信地址
Agent A 从 Agent B 的 Agent Card 中获取:
{ "url": "https://agent.example.com/rpc", "protocolBinding": "JSONRPC", "protocolVersion": "1.0"}假设双方选择 JSON-RPC 2.0 绑定。
4.2 第二步:发送消息
在 A2A 1.0 中,JSON-RPC 方法使用 PascalCase 命名,例如 SendMessage。
请求:
POST /rpc HTTP/1.1Host: agent.example.comContent-Type: application/jsonA2A-Version: 1.0请求体:
{ "jsonrpc": "2.0", "id": 1, "method": "SendMessage", "params": { "message": { "messageId": "msg-001", "role": "ROLE_USER", "parts": [ { "text": "帮我分析这个项目的架构" } ] } }}这里:
| 内容 | 作用 |
|---|---|
| HTTP POST | 通过 HTTP 发送请求 |
| jsonrpc | 指定 JSON-RPC 2.0 |
| method | 指定调用 SendMessage |
| params | 传递 A2A 消息和配置 |
| id | JSON-RPC 请求标识 |
| A2A-Version | 指定 A2A 协议版本 |
4.3 第三步:Agent B 返回响应
Agent B 可能返回两种结果:
情况一:直接返回 Message
适合不需要持续跟踪的简单交互。
{ "jsonrpc": "2.0", "id": 1, "result": { "message": { "messageId": "msg-002", "role": "ROLE_AGENT", "parts": [ { "text": "你好,我可以帮你分析项目架构。" } ] } }}情况二:返回 Task
适合需要后台执行和跟踪进度的任务。
{ "jsonrpc": "2.0", "id": 1, "result": { "task": { "id": "task-001", "contextId": "context-001", "status": { "state": "TASK_STATE_WORKING" } } }}Agent A 拿到 task-001 后,就可以继续跟踪任务。
5. Task 的生命周期
Task 不只是一个任务 ID,它有自己的状态变化过程。
5.1 常见状态
| 状态 | 含义 |
|---|---|
| TASK_STATE_SUBMITTED | 任务已接收 |
| TASK_STATE_WORKING | 正在执行 |
| TASK_STATE_INPUT_REQUIRED | 需要调用方补充输入 |
| TASK_STATE_AUTH_REQUIRED | 需要完成认证 |
| TASK_STATE_COMPLETED | 任务成功完成 |
| TASK_STATE_FAILED | 任务执行失败 |
| TASK_STATE_CANCELED | 任务被取消 |
| TASK_STATE_REJECTED | 任务被拒绝 |
其中:
INPUT_REQUIRED:Agent 缺少必要信息,需要调用方补充。AUTH_REQUIRED:Agent 需要调用方完成认证或授权。COMPLETED、FAILED、CANCELED、REJECTED:终止状态。
5.2 状态流转示意
SUBMITTED │ ▼ WORKING │ ┌────────┼─────────┐ │ │ │ ▼ ▼ ▼ COMPLETED FAILED INPUT_REQUIRED │ ▼ WORKING
其他可能状态:AUTH_REQUIREDCANCELEDREJECTEDNOTE这只是帮助理解的简化示意,不代表每种状态之间都允许任意转换。
5.3 如何处理人工介入?
假设 Agent B 在分析项目时发现:
项目中存在多个配置文件,不确定应该分析哪个。它可以把任务状态设置为:
{ "state": "TASK_STATE_INPUT_REQUIRED", "message": { "role": "ROLE_AGENT", "parts": [ { "text": "请问需要分析 dev.yaml 还是 prod.yaml?" } ] }}Agent A 收到后,可以向用户询问。
用户回答后,Agent A 再通过 SendMessage 继续向 Agent B 提交消息,并关联原来的任务或上下文。
所以 A2A 提供了任务中断、等待输入和继续交互的协议基础。
但具体如何展示审批页面、如何验证用户权限,仍然由应用自身实现。
6. 如何获取任务进度?
A2A 提供三种主要方式:
- Polling:轮询。
- Streaming:流式通信。
- Push Notification:推送通知。
6.1 Polling:轮询
最简单的方式。
Agent A 提交任务后,拿到:
task-001然后定期查询任务。
A2A 1.0 的 JSON-RPC 方法:
GetTask请求:
{ "jsonrpc": "2.0", "id": 2, "method": "GetTask", "params": { "id": "task-001", "historyLength": 10 }}返回:
{ "jsonrpc": "2.0", "id": 2, "result": { "id": "task-001", "status": { "state": "TASK_STATE_WORKING" } }}Agent A 可以隔一段时间再次调用 GetTask。
直到返回:
{ "state": "TASK_STATE_COMPLETED"}优点:
- 实现简单。
- 不需要维持长连接。
- 适合低频任务状态查询。
缺点:
- 可能产生大量重复请求。
- 无法第一时间知道任务完成。
6.2 Streaming:流式通信
如果希望实时接收任务进度,可以使用流式通信。
A2A 1.0 的 JSON-RPC 方法:
SendStreamingMessage它相当于:
发送任务消息 + 建立流式事件连接。
客户端发送请求后,服务端通过 SSE 持续推送事件。
HTTP 响应:
HTTP/1.1 200 OKContent-Type: text/event-streamSSE 数据示意:
data: {"jsonrpc":"2.0","id":1,"result":{"taskStatusUpdate":{"status":{"state":"TASK_STATE_WORKING"}}}}
data: {"jsonrpc":"2.0","id":1,"result":{"taskArtifactUpdate":{"artifact":{"parts":[{"text":"正在分析项目依赖"}]}}}}
data: {"jsonrpc":"2.0","id":1,"result":{"taskStatusUpdate":{"status":{"state":"TASK_STATE_COMPLETED"}}}}这里需要理解:
- SSE 是一种服务器向客户端持续推送事件的机制。
- Agent B 可以在任务执行过程中多次推送事件。
- Agent A 不需要一直重复调用
GetTask。
如果任务已经创建,也可以使用:
SubscribeToTask订阅已有任务的更新。
适合:
- 实时任务进度展示。
- Agent 聊天界面。
- 多 Agent 协作过程的实时监控。
前提是 Agent Card 声明支持:
{ "capabilities": { "streaming": true }}6.3 Push Notification:Webhook 推送
如果任务可能执行几分钟、几小时,甚至更久,客户端不一定适合一直维持 SSE 连接。
这时可以使用 Push Notification。
它的工作方式是:
Agent A Agent B │ │ │ 1. 提交任务 │ ├──────────────────────────────►│ │ │ │ 2. 提供 Webhook 地址 │ │ │ │ │ │ 执行任务 │ │ │ 3. 任务状态发生变化 │ │◄──────────────────────────────┤ │ HTTP POST │ │ │ ▼ │接收通知 │ │ │ ▼ │查询最终任务结果 │例如,Agent A 提供:
https://agent-a.example.com/webhook/a2aAgent B 在任务发生状态变化时,向这个地址发送 HTTP POST。
A2A 1.0 的 JSON-RPC 配置方法包括:
CreateTaskPushNotificationConfigGetTaskPushNotificationConfigListTaskPushNotificationConfigsDeleteTaskPushNotificationConfig配置示意:
{ "taskId": "task-001", "pushNotificationConfig": { "url": "https://agent-a.example.com/webhook/a2a", "token": "your-webhook-token" }}实际使用时,具体字段结构应按照所使用版本的 TaskPushNotificationConfig 定义填写。
Agent A 需要实现一个 HTTP 接收接口:
POST /webhook/a2a收到通知后:
- 验证通知来源和身份。
- 读取任务 ID 和事件内容。
- 更新本地任务状态。
- 必要时调用
GetTask获取完整任务信息。 - 对重复通知进行幂等处理。
NOTEWebhook 是 Agent B 主动向 Agent A 发起 HTTP 请求,不是 Agent A 不断去查询 Agent B。
6.4 三种方式对比
| 方式 | 通信方式 | 适用场景 |
|---|---|---|
| Polling | 客户端定期查询 | 简单任务、低频查询 |
| Streaming | SSE 持续推送 | 实时进度、交互界面 |
| Push Notification | Webhook 主动通知 | 长时间任务、异步服务 |
7. A2A 还有哪些常用操作?
除了提交消息和获取任务,还有一些常用操作。
| JSON-RPC 1.0 方法名 | 用途 |
|---|---|
| SendMessage | 发送消息、创建或继续任务 |
| SendStreamingMessage | 发送消息并接收流式事件 |
| GetTask | 查询任务 |
| ListTasks | 查询任务列表 |
| CancelTask | 取消任务 |
| SubscribeToTask | 订阅已有任务的事件 |
| CreateTaskPushNotificationConfig | 创建推送配置 |
| GetTaskPushNotificationConfig | 查询推送配置 |
| ListTaskPushNotificationConfigs | 查询推送配置列表 |
| DeleteTaskPushNotificationConfig | 删除推送配置 |
| GetExtendedAgentCard | 获取认证后的扩展 Agent Card |
注意:上表列出的是 A2A 1.0 JSON-RPC 绑定的方法名。
如果你看到旧文章使用:
message/sendmessage/streamtasks/gettasks/canceltasks/resubscribe这些是 A2A 0.3 及更早版本中常见的命名。
A2A 1.0 对 JSON-RPC 方法名进行了调整,例如:
message/send ↓SendMessage
message/stream ↓SendStreamingMessage
tasks/get ↓GetTask
tasks/cancel ↓CancelTaskWARNING看 A2A 资料时一定要注意版本,不能把 0.3 和 1.0 的调用方式混在一起。
8. A2A 使用什么通信协议?
A2A 定义了统一的交互模型,同时支持不同的协议绑定。
常见的有:
8.1 JSON-RPC 2.0
通过 HTTP(S) 发送 JSON-RPC 请求。
例如:
POST /rpcContent-Type: application/json请求体中使用:
{ "jsonrpc": "2.0", "id": 1, "method": "SendMessage", "params": {}}优点:
- JSON 格式,容易调试。
- 对语言和框架要求较低。
- 适合常见 Agent 服务之间的通信。
8.2 gRPC
使用 Protocol Buffers 定义服务和数据结构,通过 gRPC 调用远程 Agent。
例如:
rpc SendMessage(SendMessageRequest) returns (SendMessageResponse);适合已有 gRPC 基础设施、需要强类型接口的服务。
8.3 HTTP+JSON / REST
通过 HTTP 方法和资源路径调用。
例如:
POST /message:send查询任务:
GET /tasks/task-001取消任务:
POST /tasks/task-001:cancel8.4 对比
| 绑定方式 | 通信形式 | 特点 |
|---|---|---|
| JSON-RPC | JSON-RPC 2.0 over HTTP(S) | 通过 method 调用 |
| gRPC | Protobuf + gRPC | 强类型、适合服务间通信 |
| HTTP+JSON | HTTP API | 使用 URL 和 HTTP 方法 |
它们只是不同的通信方式,背后遵循的 A2A 核心交互模型是一致的。
9. A2A 的安全机制
Agent 之间的通信不代表可以直接互相信任。
A2A 需要考虑:
- 身份认证。
- 权限控制。
- 通信加密。
- Agent Card 的可信性。
- Webhook 的身份验证。
Agent Card 可以声明支持的安全方案,例如:
{ "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer" } }, "securityRequirements": [ { "bearerAuth": [] } ]}客户端根据 Agent Card 声明的认证方式获取凭证,再调用对应接口。
实际请求可能携带:
Authorization: Bearer YOUR_ACCESS_TOKENNOTE需要注意:
- Agent Card 不应该直接保存或公开访问密钥。
- HTTPS 用于保护传输过程。
- Agent B 应验证 Agent A 是否有权调用相应能力。
- Webhook 应验证请求来源,防止伪造通知。
- Agent 之间不应该因为使用了 A2A 就默认互相信任。
10. A2A 与 MCP、ACP 有什么区别?
这三个协议都与 Agent 生态有关,但解决的问题不同。
| 对比 | A2A | MCP | ACP |
|---|---|---|---|
| 主要定位 | Agent 与 Agent 通信 | Agent 与工具、数据源交互 | Agent 与代码编辑器/开发工具协作 |
| 通信对象 | 远程 Agent | MCP Server 提供的能力 | Agent 与支持 ACP 的客户端 |
| 核心概念 | Agent Card、Message、Task、Artifact | Tool、Resource、Prompt | Session、Message、Content、Permission |
| 主要作用 | 委派任务、协作、跟踪结果 | 调用工具、读取资源 | 统一 Agent 与开发环境之间的交互 |
| 典型场景 | 一个 Agent 把任务交给另一个 Agent | Agent 调用数据库、文件系统等 | IDE 连接不同的代码 Agent |
10.1 MCP 举例
Agent 想读取数据库:
Agent │ ▼MCP Client │ ▼MCP Server │ ▼DatabaseMCP Server 向 Agent 提供工具:
query_database(sql)Agent 调用工具获取数据。
10.2 A2A 举例
Agent A 想让 Agent B 分析项目:
Agent A │ ▼A2A Client │ ▼A2A Server │ ▼Agent BAgent A 提交任务,Agent B 执行并返回结果。
10.3 ACP 举例
IDE 想连接不同的代码 Agent:
IDE │ ▼ACP Client │ ▼ACP Server │ ▼Coding AgentIDE 可以通过 ACP 统一与支持 ACP 的 Agent 进行会话交互。
10.4 三者可以一起使用吗?
可以。
例如一个代码开发系统:
用户 │ ▼ Agent A / \ / \ A2A MCP / \ ▼ ▼ Agent B MCP Server 代码分析 文件系统 │ │ ▼ ▼ 分析项目 读取文件
IDE 还可以通过 ACP 与代码 Agent 建立会话。这里:
- A2A:负责 Agent 之间委派任务。
- MCP:负责 Agent 使用外部工具和数据。
- ACP:负责 IDE 与代码 Agent 之间的会话交互。
11. 最后总结:完整调用流程
把前面所有内容串起来,A2A 的一次典型任务交互就是:
1. 发现 Agent GET /.well-known/agent-card.json │ ▼2. 读取 Agent Card 查看 Skills、Capabilities、接口地址、认证方式 │ ▼3. 建立通信 根据 supportedInterfaces 选择协议绑定 │ ▼4. 提交任务 SendMessage │ ▼5. 获取 Task taskId + contextId │ ▼6. 跟踪任务 ├── GetTask(轮询) ├── SendStreamingMessage / SubscribeToTask(流式) └── Push Notification(Webhook) │ ▼7. 处理任务状态 WORKING / INPUT_REQUIRED / AUTH_REQUIRED ... │ ▼8. 获取最终结果 Task.artifacts │ ▼9. 交付结果 Agent A 返回给用户关键概念记忆
| 概念 | 记忆方式 |
|---|---|
| Agent Card | Agent 的说明书 |
| Skills | Agent 能做什么 |
| Capabilities | Agent 支持哪些协议功能 |
| Message | Agent 之间发送的消息 |
| Part | 消息或产物中的内容片段 |
| Task | 一项可跟踪的任务 |
| Artifact | 任务最终产生的结果 |
| Context | 关联多轮交互的上下文 |
| Polling | 主动定期查询 |
| Streaming | 保持连接接收实时事件 |
| Webhook | 对方主动向我发送通知 |
一句话理解 A2A:
A2A 让不同框架、不同厂商、不同运行环境中的 Agent,可以通过统一的协议发现彼此、交换消息、委派任务、跟踪执行过程,并交付任务结果。