协议绑定详解

绑定负责把抽象的 A2A 操作映射到具体协议。方法映射表、错误码表和版本协商规则对所有绑定通用,已在核心协议规范 中给出;下文只讲每种绑定各自特有的部分,对应官方规范第 9 至 11 章与第 14 章。所有绑定必须提供功能等价的行为,数据模型始终以 a2a.proto 为准。

JSON-RPCgRPCHTTP+JSON/REST
协议JSON-RPC 2.0 over HTTP(S)gRPC over HTTP/2 + TLSHTTP(S) + JSON 载荷
序列化application/jsonProtocol Buffers v3application/a2a+json(应当)
服务参数HTTP 请求头gRPC metadataHTTP 请求头
流式传输Server-Sent Events服务端流式 RPCServer-Sent Events
错误载体JSON-RPC error 对象google.rpc.StatusJSON 形式的 google.rpc.Status

JSON-RPC 绑定

  • 协议:JSON-RPC 2.0 over HTTP(S),请求与响应使用 Content-Type: application/json;
  • 方法名:PascalCase,与 gRPC 的约定一致(如 SendMessage、GetTask);
  • 流式:Server-Sent Events(text/event-stream)。

服务参数

JSON-RPC 运行在 HTTP(S) 之上,A2A 服务参数必须以标准 HTTP 请求头字段传输。名称不区分大小写;同一参数的多个值(如 A2A-Extensions)应当用逗号分隔,放在同一个请求头字段中。

POST /rpc HTTP/1.1
Host: agent.example.com
Content-Type: application/json
Authorization: Bearer token
A2A-Version: 1.0
A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "SendMessage",
  "params": { /* SendMessageRequest */ }
}

方法

每个请求必须遵循 JSON-RPC 2.0 格式:jsonrpc、id、method、params。各方法的 params 是 a2a.proto 中对应的请求消息:

方法paramsresult
SendMessageSendMessageRequestSendMessageResponse:包含 task 或 message 之一
SendStreamingMessageSendMessageRequestSSE 流;每个事件是一个 JSON-RPC 响应,其 result 为 StreamResponse
GetTask{"id": "task-uuid", "historyLength": 10}Task
ListTaskscontextId、status、pageSize、pageToken 等过滤参数ListTasksResponse
CancelTask{"id": "task-uuid"}Task
SubscribeToTask{"id": "task-uuid"}与 SendStreamingMessage 格式相同的 SSE 流;任务处于终态时返回 UnsupportedOperationError
四个推送通知配置方法创建 / 获取 / 列出 / 删除请求与核心规范中对应操作相同
GetExtendedAgentCard无AgentCard

每个流式事件是一行 SSE data:,内容是一个完整的 JSON-RPC 响应:

data: {"jsonrpc": "2.0", "id": 1, "result": { /* StreamResponse object */ }}

错误

JSON-RPC 错误使用标准的 JSON-RPC 2.0 error 对象:error.code 为数字错误码,error.message 为人类可读的消息,error.data 是详情对象的数组。data 中的每个对象必须包含 @type 键(ProtoJSON 的 Any 表示);实现应当使用 google.rpc.ErrorInfo、google.rpc.BadRequest 等通用类型。

错误码名称标准消息
-32700JSONParseErrorInvalid JSON payload
-32600InvalidRequestErrorRequest payload validation error
-32601MethodNotFoundErrorMethod not found
-32602InvalidParamsErrorInvalid parameters
-32603InternalErrorInternal error

A2A 专有错误使用 -32001 至 -32099 范围,完整映射见核心协议规范 。一个 A2A 专有错误响应:

{
  "jsonrpc": "2.0",
  "id": 2,
  "error": {
    "code": -32001,
    "message": "Task not found",
    "data": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "TASK_NOT_FOUND",
        "domain": "a2a-protocol.org",
        "metadata": {
          "taskId": "nonexistent-task-id",
          "timestamp": "2025-11-09T10:30:00.000Z"
        }
      }
    ]
  }
}

参数校验错误在 data 中使用 google.rpc.BadRequest:

{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32602,
    "message": "Invalid parameters",
    "data": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "message.parts",
            "description": "At least one part is required"
          }
        ]
      }
    ]
  }
}

gRPC 绑定

  • 协议:gRPC over HTTP/2 + TLS;
  • 定义:使用 specification/a2a.proto 中规范性的 Protocol Buffers(版本 3)定义,并实现 A2AService 服务。gRPC 绑定遵循 API 指南 ,以简化 gRPC 到 HTTP 的映射;
  • 方法:与核心映射表中相同的 11 个操作,每个对应一个 RPC。各 RPC 的请求与响应消息都定义在 a2a.proto 中;DeleteTaskPushNotificationConfig 返回 google.protobuf.Empty。

服务参数

服务参数必须以 gRPC metadata(请求头)传输。gRPC 会把 metadata 键转换为小写,因此 A2A-Version 到达时是 a2a-version。同一参数的多个值应当用逗号分隔,放在同一个 metadata 条目中。实现必须从 metadata 中提取 A2A 服务参数,服务端应当校验 A2A-Version 等必需参数。

// Go example using gRPC metadata
md := metadata.Pairs(
    "authorization", "Bearer token",
    "a2a-version", "1.0",
    "a2a-extensions", "https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1",
)
ctx := metadata.NewOutgoingContext(context.Background(), md)

// Make the RPC call with the context containing metadata
response, err := client.SendMessage(ctx, request)

错误

错误使用标准的 gRPC 状态结构 google.rpc.Status:status.code 为 gRPC 状态码,status.message 为人类可读的消息,status.details 是重复的 google.protobuf.Any。对于 A2A 专有错误,实现必须在 status.details 中包含一个 google.rpc.ErrorInfo:reason 为去掉 Error 后缀的 UPPER_SNAKE_CASE 错误名,domain 为 "a2a-protocol.org",metadata 是可选的附加上下文映射。

// A2A-specific task not found error
status {
  code: NOT_FOUND
  message: "Task with ID 'task-123' not found"
  details: [
    {
      type: "type.googleapis.com/google.rpc.ErrorInfo"
      reason: "TASK_NOT_FOUND"
      domain: "a2a-protocol.org"
      metadata: {
        task_id: "task-123"
        timestamp: "2025-11-09T10:30:00Z"
      }
    }
  ]
}

流式传输

流式使用服务端流式 RPC(SendStreamingMessage、SubscribeToTask)。流中的元素是 StreamResponse,它是各种可能事件的联合体:task、message、status_update 或 artifact_update。

HTTP+JSON/REST 绑定

  • 协议:HTTP(S) + JSON 载荷,使用资源式 URL 和标准 HTTP 动词(URL 模式见核心映射表);
  • Content-Type:请求与响应应当使用 application/a2a+json;
  • 流式:Server-Sent Events。

服务参数

与 JSON-RPC 一样,服务参数必须以标准 HTTP 请求头字段传输(名称不区分大小写,多个值用逗号分隔放在同一字段中):

POST /message:send HTTP/1.1
Host: agent.example.com
Content-Type: application/a2a+json
Authorization: Bearer token
A2A-Version: 1.0
A2A-Extensions: https://example.com/extensions/geolocation/v1,https://standards.org/extensions/citations/v1

{
  "message": {
    "role": "ROLE_USER",
    "parts": [{"text": "Find restaurants near me"}]
  }
}

请求与响应格式

请求和响应都是结构上等价于 Protocol Buffer 定义的 JSON 对象。一个 SendMessage 请求与响应:

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

{
  "message": {
    "messageId": "uuid",
    "role": "ROLE_USER",
    "parts": [{"text": "Hello"}]
  },
  "configuration": {
    "acceptedOutputModes": ["text/plain"]
  }
}
HTTP/1.1 200 OK
Content-Type: application/a2a+json

{
  "task": {
    "id": "task-uuid",
    "contextId": "context-uuid",
    "status": {
      "state": "TASK_STATE_COMPLETED"
    }
  }
}

查询参数

GET 和 DELETE 没有请求体,其请求参数必须通过路径参数或查询参数传递。查询参数名必须使用 camelCase,与 proto 字段的 JSON 序列化一致:

Protobuf 字段查询参数
context_idcontextId
page_sizepageSize
page_tokenpageToken
task_idtaskId
GET /tasks?contextId=uuid&status=TASK_STATE_WORKING&pageSize=50&pageToken=cursor
GET /tasks/{id}?historyLength=10

类型处理:字符串原样传递;布尔值用小写的 true / false;数字用十进制字符串;枚举用其字符串名(如 status=TASK_STATE_WORKING);时间戳用 ISO 8601 字符串;重复字段可以重复参数名,也可以用逗号分隔的值。查询参数不支持嵌套对象,需要嵌套对象的操作必须使用带请求体的 POST。参数值必须按 RFC 3986 做 URL 编码。

错误

HTTP 错误响应使用 google.rpc.Status 的 JSON 表示:HTTP 状态码与 error.code 表示错误码,error.message 为消息,error.details 是对象数组,每个对象都带 @type 键。由于多个 A2A 错误会映射到同一个 HTTP 状态码(例如 TaskNotCancelableError 与 PushNotificationNotSupportedError 都映射为 400),A2A 专有错误必须包含一个 google.rpc.ErrorInfo,其中 reason 为去掉 Error 后缀的 UPPER_SNAKE_CASE 名称,domain 为 "a2a-protocol.org"。taskId、timestamp 等附加上下文可以放在 metadata 中:

HTTP/1.1 404 Not Found
Content-Type: application/a2a+json

{
  "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",
        "metadata": {
          "taskId": "task-123",
          "timestamp": "2025-11-09T10:30:00.000Z"
        }
      }
    ]
  }
}

流式传输

POST /message:stream 与 POST /tasks/{id}:subscribe 以 Content-Type: text/event-stream 响应,每个事件的 data 字段是一个 StreamResponse 的 JSON 序列化:

HTTP/1.1 200 OK
Content-Type: text/event-stream

data: { /* StreamResponse object */ }

data: { /* StreamResponse object */ }

流是简单的线性有序序列:先是一个 Task(或单条 Message),然后是零个或多个状态或产出物更新事件,直到任务进入终态或中断状态,此时流关闭。实现应当避免事件重排,并且可以在关闭前重发一次最终的 Task 快照。

注册标识符

规范还为基于 HTTP 的绑定所使用的标识符给出了注册模板,用于向 IANA 提交:

类别标识符说明
媒体类型application/a2a+json面向 HTTP+JSON/REST 绑定;UTF-8 编码的 JSON 文本;文件扩展名 .a2a.json
HTTP 请求头A2A-Version客户端使用的协议版本,格式为 Major.Minor(如 1.0);不支持的版本返回 VersionNotSupportedError
HTTP 请求头A2A-Extensions客户端希望在本次请求中使用的扩展 URI,逗号分隔
Well-Known URI/.well-known/agent-card.json返回 AgentCard 对象,见智能体发现与 Agent Card

application/a2a+json 的安全考量,在 JSON 格式通用的考量(RFC 8259 第 12 节)之外还包括:

  • 处理之前,内容必须按 A2A 协议 Schema 校验,用户提供的内容必须经过净化以防注入攻击;
  • A2A 消息中的文件引用必须经过校验以防范 SSRF;
  • 必须按认证、授权与安全考量 的要求执行认证与授权;
  • 任务历史与产出物中的敏感信息必须按适用的数据保护法规加以保护。

Well-Known URI 的安全考量:Agent Card 不应包含敏感凭据或内部实现细节;实现应当通过 HTTPS 提供;卡片可以使用 JWS 签名,客户端在签名存在时应当验证;通过已认证端点获取的扩展 Agent Card 必须执行恰当的访问控制。

相关页面

来源:A2A 官方规范