核心协议规范

这是从实现者视角看的 A2A 核心协议关键约束。文中的 MUST / SHOULD / MAY 沿用 RFC 2119 的含义,条目与官方规范第 3、5 章一一对应。

三层模型

规范分为三层,上层不依赖下层的传输细节:

  1. 规范数据模型(Layer 1):以 Protocol Buffers 定义的 Task、Message、AgentCard、Part、Artifact 等对象,与具体协议无关;
  2. 抽象操作(Layer 2):所有 A2A 实现都必须支持的行为,例如发送消息、获取任务、取消任务,与如何暴露无关;
  3. 协议绑定(Layer 3):把抽象操作映射到具体协议——JSON-RPC、gRPC、HTTP+JSON/REST,也可以是自定义绑定。

a2a.proto 是所有协议对象与请求/响应消息的唯一权威定义;JSON Schema 等产物只是便于工具使用的派生物,SDK 与 Schema 应当由 proto 生成,而不是手工修改。

核心操作与绑定映射

三种绑定必须提供功能等价的行为。下表是官方给出的方法映射(HTTP 路径不含 /v1 前缀):

功能JSON-RPC 方法gRPC 方法HTTP+JSON 端点
发送消息SendMessageSendMessagePOST /message:send
发送流式消息SendStreamingMessageSendStreamingMessagePOST /message:stream
获取任务GetTaskGetTaskGET /tasks/{id}
列出任务ListTasksListTasksGET /tasks
取消任务CancelTaskCancelTaskPOST /tasks/{id}:cancel
订阅任务SubscribeToTaskSubscribeToTaskPOST /tasks/{id}:subscribe
创建推送通知配置CreateTaskPushNotificationConfigCreateTaskPushNotificationConfigPOST /tasks/{id}/pushNotificationConfigs
获取推送通知配置GetTaskPushNotificationConfigGetTaskPushNotificationConfigGET /tasks/{id}/pushNotificationConfigs/{configId}
列出推送通知配置ListTaskPushNotificationConfigsListTaskPushNotificationConfigsGET /tasks/{id}/pushNotificationConfigs
删除推送通知配置DeleteTaskPushNotificationConfigDeleteTaskPushNotificationConfigDELETE /tasks/{id}/pushNotificationConfigs/{configId}
获取扩展 Agent CardGetExtendedAgentCardGetExtendedAgentCardGET /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-RPCgRPCHTTP
TaskNotFoundError-32001NOT_FOUND404
TaskNotCancelableError-32002FAILED_PRECONDITION400
PushNotificationNotSupportedError-32003FAILED_PRECONDITION400
UnsupportedOperationError-32004FAILED_PRECONDITION400
ContentTypeNotSupportedError-32005INVALID_ARGUMENT400
InvalidAgentResponseError-32006INTERNAL500
ExtendedAgentCardNotConfiguredError-32007FAILED_PRECONDITION400
ExtensionSupportRequiredError-32008FAILED_PRECONDITION400
VersionNotSupportedError-32009FAILED_PRECONDITION400

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+json

JSON 与数据约定

  • 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 不保留它们。

相关页面

来源:A2A 官方规范