Protocol Bindings in Detail

A binding maps the abstract A2A operations onto a concrete protocol. Core Protocol Specification has the method mapping table, the error code table, and the version negotiation rules shared by all bindings; this page covers what is specific to each binding, following chapters 9 to 11 and 14 of the official specification. Every binding MUST provide functionally equivalent behavior, and the data model is always the one defined in a2a.proto .

JSON-RPCgRPCHTTP+JSON/REST
ProtocolJSON-RPC 2.0 over HTTP(S)gRPC over HTTP/2 with TLSHTTP(S) with JSON payloads
Serializationapplication/jsonProtocol Buffers v3application/a2a+json (SHOULD)
Service parametersHTTP headersgRPC metadataHTTP headers
StreamingServer-Sent EventsServer-streaming RPCServer-Sent Events
Error carrierJSON-RPC error objectgoogle.rpc.Statusgoogle.rpc.Status as JSON

JSON-RPC binding

  • Protocol: JSON-RPC 2.0 over HTTP(S), with Content-Type: application/json for requests and responses.
  • Method names: PascalCase, matching the gRPC conventions (for example SendMessage, GetTask).
  • Streaming: Server-Sent Events (text/event-stream).

Service parameters

Because JSON-RPC runs over HTTP(S), A2A service parameters MUST be transmitted as standard HTTP request header fields. Names are case-insensitive, and multiple values for one parameter (such as A2A-Extensions) SHOULD be comma-separated in a single header field.

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 */ }
}

Methods

Every request MUST follow the JSON-RPC 2.0 format: jsonrpc, id, method, and params. The params of each method are the corresponding request message from a2a.proto:

Methodparamsresult
SendMessageSendMessageRequestSendMessageResponse: contains either task or message
SendStreamingMessageSendMessageRequestAn SSE stream; each event is a JSON-RPC response whose result is a StreamResponse
GetTask{"id": "task-uuid", "historyLength": 10}Task
ListTaskscontextId, status, pageSize, pageToken, and the other filtersListTasksResponse
CancelTask{"id": "task-uuid"}Task
SubscribeToTask{"id": "task-uuid"}An SSE stream in the same format as SendStreamingMessage; a task in a terminal state returns UnsupportedOperationError
The four push notification config methodsCreate / Get / List / Delete requestsSame as the corresponding operations in the core specification
GetExtendedAgentCardNoneAgentCard

Each streaming event is one SSE data: line carrying a complete JSON-RPC response:

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

Errors

JSON-RPC errors use the standard JSON-RPC 2.0 error object: error.code carries the numeric code, error.message the human-readable message, and error.data an array of detail objects. Every object in data MUST include an @type key (ProtoJSON Any representation); implementations SHOULD use well-known types such as google.rpc.ErrorInfo or google.rpc.BadRequest.

CodeNameStandard message
-32700JSONParseErrorInvalid JSON payload
-32600InvalidRequestErrorRequest payload validation error
-32601MethodNotFoundErrorMethod not found
-32602InvalidParamsErrorInvalid parameters
-32603InternalErrorInternal error

A2A-specific errors use the range -32001 to -32099; the complete mapping is in Core Protocol Specification . An A2A-specific error response:

{
  "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"
        }
      }
    ]
  }
}

A validation error uses google.rpc.BadRequest in data:

{
  "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 binding

  • Protocol: gRPC over HTTP/2 with TLS.
  • Definition: use the normative Protocol Buffers definition in specification/a2a.proto , version 3, and implement the A2AService service. The gRPC binding follows the API guidelines to simplify the gRPC-to-HTTP mapping.
  • Methods: the same 11 operations as in the core mapping table, one RPC each. The request and response messages of each RPC are defined in a2a.proto; DeleteTaskPushNotificationConfig returns google.protobuf.Empty.

Service parameters

Service parameters MUST be transmitted as gRPC metadata (headers). gRPC converts metadata keys to lowercase, so A2A-Version arrives as a2a-version. Multiple values for one parameter SHOULD be comma-separated in a single metadata entry. Implementations MUST extract the A2A service parameters from the metadata, and servers SHOULD validate the required ones such as 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)

Errors

Errors use the standard gRPC status structure with google.rpc.Status: status.code is the gRPC status code, status.message the human-readable message, and status.details a repeated google.protobuf.Any. For A2A-specific errors, implementations MUST include a google.rpc.ErrorInfo in status.details: reason is the error name in UPPER_SNAKE_CASE without the Error suffix, domain is "a2a-protocol.org", and metadata is an optional map of extra context.

// 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"
      }
    }
  ]
}

Streaming

Streaming uses server-streaming RPCs (SendStreamingMessage, SubscribeToTask). The stream element is StreamResponse, a union of the possible events: task, message, status_update, or artifact_update.

HTTP+JSON/REST binding

  • Protocol: HTTP(S) with JSON payloads, using resource-style URLs and standard HTTP verbs (the URL patterns are in the core mapping table).
  • Content-Type: application/a2a+json SHOULD be used for requests and responses.
  • Streaming: Server-Sent Events.

Service parameters

As with JSON-RPC, service parameters MUST be transmitted as standard HTTP request header fields (names are case-insensitive, multiple values comma-separated in one field):

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"}]
  }
}

Request and response format

Requests and responses are JSON objects structurally equivalent to the Protocol Buffer definitions. A SendMessage request and response:

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"
    }
  }
}

Query parameters

GET and DELETE carry no request body, so their request parameters MUST be sent as path or query parameters. Query parameter names MUST use camelCase, matching the JSON serialization of the proto fields:

Protobuf fieldQuery parameter
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

Type handling: strings are passed as is; booleans as lowercase true / false; numbers as decimal strings; enums as their string names (for example status=TASK_STATE_WORKING); timestamps as ISO 8601 strings; a repeated field MAY repeat the parameter name or use comma-separated values. Nested objects are not supported in query parameters, so operations that need them MUST use POST with a body. Values MUST be URL-encoded per RFC 3986.

Errors

HTTP error responses use the JSON representation of google.rpc.Status: the HTTP status code and error.code carry the code, error.message the message, and error.details an array of objects that each include an @type key. Because several A2A errors map to the same HTTP status (for example TaskNotCancelableError and PushNotificationNotSupportedError both map to 400), A2A-specific errors MUST include a google.rpc.ErrorInfo with reason (UPPER_SNAKE_CASE without the Error suffix) and domain set to "a2a-protocol.org". Extra context such as taskId and timestamp can go in 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"
        }
      }
    ]
  }
}

Streaming

POST /message:stream and POST /tasks/{id}:subscribe respond with Content-Type: text/event-stream, and the data field of each event is the JSON serialization of a StreamResponse:

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

data: { /* StreamResponse object */ }

data: { /* StreamResponse object */ }

The stream is a simple, linearly ordered sequence: first a Task (or a single Message), then zero or more status or artifact update events until the task reaches a terminal or interrupted state, at which point the stream closes. Implementations SHOULD avoid reordering events and MAY resend a final Task snapshot before closing.

Registered identifiers

The specification also gives registration templates, intended for submission to IANA, for the identifiers the HTTP-based bindings use:

KindIdentifierNotes
Media typeapplication/a2a+jsonIntended for the HTTP+JSON/REST binding; UTF-8 JSON text; file extension .a2a.json
HTTP headerA2A-VersionThe protocol version the client uses, in the format Major.Minor (for example 1.0); an unsupported version returns VersionNotSupportedError
HTTP headerA2A-ExtensionsA comma-separated list of the extension URIs the client wants to use for this request
Well-known URI/.well-known/agent-card.jsonReturns the AgentCard object; see Agent Discovery and the Agent Card

Security considerations for application/a2a+json, in addition to those common to JSON formats (RFC 8259, section 12):

  • content MUST be validated against the A2A protocol schema before processing, and user-provided content MUST be sanitized to prevent injection attacks;
  • file references in A2A messages MUST be validated to prevent SSRF;
  • authentication and authorization MUST be enforced as described in Authentication, Authorization, and Security Considerations ;
  • sensitive information in task history and artifacts MUST be protected according to applicable data protection regulations.

Security considerations for the well-known URI: the Agent Card SHOULD NOT contain sensitive credentials or internal implementation details; implementations SHOULD serve it over HTTPS; the card MAY be signed with JWS, and clients SHOULD verify the signature when present; and extended Agent Cards retrieved through authenticated endpoints MUST enforce appropriate access control.

Related pages

Source: A2A official specification