核心协议规范
这是从实现者视角看的 A2A 核心协议关键约束。文中的 MUST / SHOULD / MAY 沿用 RFC 2119 的含义,条目与官方规范第 3、5 章一一对应。
三层模型
规范分为三层,上层不依赖下层的传输细节:
- 规范数据模型(Layer 1):以 Protocol Buffers 定义的
Task、Message、AgentCard、Part、Artifact等对象,与具体协议无关; - 抽象操作(Layer 2):所有 A2A 实现都必须支持的行为,例如发送消息、获取任务、取消任务,与如何暴露无关;
- 协议绑定(Layer 3):把抽象操作映射到具体协议——JSON-RPC、gRPC、HTTP+JSON/REST,也可以是自定义绑定。
a2a.proto
是所有协议对象与请求/响应消息的唯一权威定义;JSON Schema 等产物只是便于工具使用的派生物,SDK 与 Schema 应当由 proto 生成,而不是手工修改。
核心操作与绑定映射
三种绑定必须提供功能等价的行为。下表是官方给出的方法映射(HTTP 路径不含 /v1 前缀):
| 功能 | JSON-RPC 方法 | gRPC 方法 | HTTP+JSON 端点 |
|---|---|---|---|
| 发送消息 | SendMessage | SendMessage | POST /message:send |
| 发送流式消息 | SendStreamingMessage | SendStreamingMessage | POST /message:stream |
| 获取任务 | GetTask | GetTask | GET /tasks/{id} |
| 列出任务 | ListTasks | ListTasks | GET /tasks |
| 取消任务 | CancelTask | CancelTask | POST /tasks/{id}:cancel |
| 订阅任务 | SubscribeToTask | SubscribeToTask | POST /tasks/{id}:subscribe |
| 创建推送通知配置 | CreateTaskPushNotificationConfig | CreateTaskPushNotificationConfig | POST /tasks/{id}/pushNotificationConfigs |
| 获取推送通知配置 | GetTaskPushNotificationConfig | GetTaskPushNotificationConfig | GET /tasks/{id}/pushNotificationConfigs/{configId} |
| 列出推送通知配置 | ListTaskPushNotificationConfigs | ListTaskPushNotificationConfigs | GET /tasks/{id}/pushNotificationConfigs |
| 删除推送通知配置 | DeleteTaskPushNotificationConfig | DeleteTaskPushNotificationConfig | DELETE /tasks/{id}/pushNotificationConfigs/{configId} |
| 获取扩展 Agent Card | GetExtendedAgentCard | GetExtendedAgentCard | GET /extendedAgentCard |
三种绑定的要点:
- JSON-RPC:JSON-RPC 2.0 over HTTP(S),请求与响应使用
Content-Type: application/json,方法名为 PascalCase,流式使用 Server-Sent Events(text/event-stream); - gRPC:gRPC over HTTP/2 + TLS,使用 Protocol Buffers v3,需要实现
A2AService; - HTTP+JSON/REST:资源式 URL 加标准 HTTP 动词,请求与响应应当使用
application/a2a+json,流式同样使用 SSE。
同时支持多种绑定的智能体,必须在 Agent Card 中声明全部绑定,并保证功能、行为、错误处理与认证方式的一致;客户端可以选择其中任意一种,并应当实现回退逻辑。自定义绑定的规则见自定义协议绑定 。
关键操作的行为
SendMessage 与 SendStreamingMessage
- 智能体可以创建一个
Task异步处理消息,也可以直接返回一条Message(简单交互无需任务跟踪); - 流式:若返回
Message,流中恰好包含这一条消息后立即关闭;若返回Task,流以该Task开头,后跟零个或多个TaskStatusUpdateEvent/TaskArtifactUpdateEvent,并在任务进入终态时关闭; - 阻塞与非阻塞:
SendMessageConfiguration.return_immediately默认为false,此时操作必须等到任务进入终态(COMPLETED、FAILED、CANCELED、REJECTED)或中断状态(INPUT_REQUIRED、AUTH_REQUIRED)才返回;设为true则创建任务后立即返回,由调用方通过GetTask、SubscribeToTask或推送通知跟进。该字段对直接返回Message、对流式操作都无影响; - 向已处于终态的任务发送消息,返回
UnsupportedOperationError。
GetTask、ListTasks 与 historyLength
historyLength未设置表示不限制(由服务端决定默认量);0表示不返回历史(history字段应省略);大于0表示最多返回最近这么多条消息;ListTasks使用游标分页(pageToken/nextPageToken),按状态时间戳降序返回,只返回当前客户端可见的任务;pageSize未设置时最多 50 条,范围 1–100;includeArtifacts默认false,此时响应里的每个任务必须完全省略artifacts字段;nextPageToken必须始终存在,没有更多结果时为空字符串。
SubscribeToTask
- 仅适用于未进入终态的任务,终态任务返回
UnsupportedOperationError; - 流的第一个事件必须是任务当前状态的
Task对象,避免GetTask与订阅之间的信息丢失; - 同一任务可以同时存在多个流:事件必须以生成顺序广播给所有活跃的流,关闭其中一个流不影响其他流,任务的生命周期独立于任何单个流。
CancelTask
请求取消一个进行中的任务,但不保证成功。任务不可取消时返回 TaskNotCancelableError。取消操作是幂等的,重复取消可能返回 TaskNotFoundError(任务已取消并被清除)。
GetExtendedAgentCard
仅当公开 Agent Card 声明 capabilities.extendedAgentCard: true 时可用,客户端必须使用公开卡片声明的认证方案完成认证。拿到扩展卡片后,客户端应当在认证会话期间(或卡片版本变化前)用它替换缓存的公开卡片。
多轮交互:contextId 与 taskId
- contextId 把相关的
Task和Message逻辑上分组。智能体生成新的contextId时必须在响应中返回;无法接受客户端提供的contextId时必须报错,且不得为响应另行生成;客户端不应自行生成contextId,除非清楚服务端如何处理,服务端生成的值应视为不透明; - taskId 始终由服务端生成。客户端消息中带
taskId时,必须指向一个已存在的任务,否则返回TaskNotFoundError;不支持由客户端提供taskId来创建新任务; - 只提供
taskId时,智能体必须由任务推断contextId;contextId与taskId不匹配时必须拒绝; - 只提供
contextId(不带taskId)表示在已有会话上下文中开启新任务;需要补充输入时,客户端用同一个taskId与contextId发送新消息;referenceTaskIds用于显式引用相关任务。
消息与产出物的分工:Message 用于沟通(发起任务、澄清、状态说明、追加输入),任务结果应当通过 Artifact 返回;消息不是可靠投递机制,客户端不应依赖它传递关键信息。
更新送达方式
| 方式 | 适用场景 | 前提 |
|---|---|---|
轮询(GetTask) | 简单集成、更新不频繁、受限网络 | 所有绑定都支持 |
流式(SendStreamingMessage、SubscribeToTask) | 交互式应用、实时进度 | capabilities.streaming 为 true |
| 推送通知(Webhook) | 服务端到服务端、长时间任务 | capabilities.pushNotifications 为 true;无论使用哪种绑定,Webhook 都使用 HTTP POST 与 HTTP 绑定定义的 JSON 载荷 |
事件必须按生成顺序送达,不得重排。更详细的讨论见流式传输与异步操作 。
能力校验
智能体声明的可选能力是约束,不是建议:
pushNotifications为false或缺失时,推送通知配置的 4 个操作必须返回PushNotificationNotSupportedError;streaming为false或缺失时,SendStreamingMessage与SubscribeToTask必须返回UnsupportedOperationError;extendedAgentCard为false或缺失时,GetExtendedAgentCard必须返回UnsupportedOperationError;声明支持但未配置扩展卡片时,返回ExtendedAgentCardNotConfiguredError;- 服务端要求使用标记为
required: true的扩展,而客户端未声明支持时,返回ExtensionSupportRequiredError。
客户端应当先检查 Agent Card,再使用依赖可选能力的操作。
错误与错误码
服务端必须对认证、授权、校验、资源、系统等类别返回恰当的错误,并应当给出可操作的信息。授权错误与资源错误不得泄露客户端无权访问的资源是否存在。A2A 定义了 9 个专有错误,并在三种绑定中有规范映射(含触发条件、ErrorInfo.reason 与按操作的对照,见A2A 错误码速查
):
| A2A 错误 | JSON-RPC | gRPC | HTTP |
|---|---|---|---|
TaskNotFoundError | -32001 | NOT_FOUND | 404 |
TaskNotCancelableError | -32002 | FAILED_PRECONDITION | 400 |
PushNotificationNotSupportedError | -32003 | FAILED_PRECONDITION | 400 |
UnsupportedOperationError | -32004 | FAILED_PRECONDITION | 400 |
ContentTypeNotSupportedError | -32005 | INVALID_ARGUMENT | 400 |
InvalidAgentResponseError | -32006 | INTERNAL | 500 |
ExtendedAgentCardNotConfiguredError | -32007 | FAILED_PRECONDITION | 400 |
ExtensionSupportRequiredError | -32008 | FAILED_PRECONDITION | 400 |
VersionNotSupportedError | -32009 | FAILED_PRECONDITION | 400 |
HTTP 错误响应使用 google.rpc.Status 的 JSON 表示。由于多个 A2A 错误会映射到同一个 HTTP 状态码,A2A 专有错误必须在 error.details 中带一个 google.rpc.ErrorInfo:reason 为去掉 Error 后缀的 UPPER_SNAKE_CASE 名称(如 TASK_NOT_FOUND),domain 固定为 a2a-protocol.org。示例:
{
"error": {
"code": 404,
"status": "NOT_FOUND",
"message": "The specified task ID does not exist or is not accessible",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "TASK_NOT_FOUND",
"domain": "a2a-protocol.org"
}
]
}
}服务参数与版本协商
服务参数是随请求传递的横向上下文,键不区分大小写、值区分大小写,传输方式由绑定决定(HTTP 绑定用请求头,gRPC 用 metadata)。标准参数有两个:
| 名称 | 说明 |
|---|---|
A2A-Version | 客户端使用的协议版本;服务端不支持时返回 VersionNotSupportedError |
A2A-Extensions | 客户端希望在本次请求中使用的扩展 URI,逗号分隔 |
版本规则:
- 协议版本只用
Major.Minor(如1.0)标识;补丁版本不影响兼容性,不应出现在请求、响应与 Agent Card 中,也不参与版本协商; - 客户端必须在每个请求中发送
A2A-Version(也可以作为请求参数传递);0.3 客户端的空值按 0.3 处理; - 服务端必须按所请求版本的语义处理请求;接口不支持该版本时返回
VersionNotSupportedError;同一传输可以在相同或不同 URL 下暴露多个版本的接口; - 需要最新特性的客户端应当明确请求具体版本,避免自动回退到旧版本而悄悄丢失功能。
请求示例:
GET /tasks/task-123 HTTP/1.1
Host: agent.example.com
A2A-Version: 1.0
Authorization: Bearer <token>
Accept: application/a2a+jsonJSON 与数据约定
- JSON 字段一律使用 camelCase(proto 中为 snake_case,例如
context_id→contextId);枚举值按 ProtoJSON 序列化为 proto 中定义的字符串名(如TASK_STATE_INPUT_REQUIRED、ROLE_USER); - 时间戳使用 ISO 8601、UTC、以
Z结尾,应当带毫秒,例如2025-10-28T10:30:00.000Z; - 被标记为
REQUIRED的字段必须存在,实现应当忽略无法识别的字段以保持前向兼容; - 为什么采用 ProtoJSON:技术指导委员会(TSC)通过了 ADR-001 (2025-11-18),规定以 ProtoJSON 作为从 proto 定义序列化 JSON 的规范方式。该 ADR 记录了相应的代价:枚举值使用 SCREAMING_SNAKE_CASE(对早期 JSON 载荷是破坏性变更),并且无法对未知字段做往返保留,因为 ProtoJSON 不保留它们。
相关页面
- 数据结构 :核心协议涉及的对象与字段;
- 智能体发现与 Agent Card ;
- 认证、授权与安全考量 ;
- 协议绑定详解 :各绑定的服务参数、错误与流式传输;
- 常见交互流程与示例 :端到端的请求与响应示例;
- 任务的生命周期 ;
- v1.0 版本变化与迁移指南 。
来源:A2A 官方规范