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-RPC | gRPC | HTTP+JSON/REST | |
|---|---|---|---|
| Protocol | JSON-RPC 2.0 over HTTP(S) | gRPC over HTTP/2 with TLS | HTTP(S) with JSON payloads |
| Serialization | application/json | Protocol Buffers v3 | application/a2a+json (SHOULD) |
| Service parameters | HTTP headers | gRPC metadata | HTTP headers |
| Streaming | Server-Sent Events | Server-streaming RPC | Server-Sent Events |
| Error carrier | JSON-RPC error object | google.rpc.Status | google.rpc.Status as JSON |
JSON-RPC binding
- Protocol: JSON-RPC 2.0 over HTTP(S), with
Content-Type: application/jsonfor 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:
| Method | params | result |
|---|---|---|
SendMessage | SendMessageRequest | SendMessageResponse: contains either task or message |
SendStreamingMessage | SendMessageRequest | An SSE stream; each event is a JSON-RPC response whose result is a StreamResponse |
GetTask | {"id": "task-uuid", "historyLength": 10} | Task |
ListTasks | contextId, status, pageSize, pageToken, and the other filters | ListTasksResponse |
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 methods | Create / Get / List / Delete requests | Same as the corresponding operations in the core specification |
GetExtendedAgentCard | None | AgentCard |
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.
| Code | Name | Standard message |
|---|---|---|
-32700 | JSONParseError | Invalid JSON payload |
-32600 | InvalidRequestError | Request payload validation error |
-32601 | MethodNotFoundError | Method not found |
-32602 | InvalidParamsError | Invalid parameters |
-32603 | InternalError | Internal 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 theA2AServiceservice. 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;DeleteTaskPushNotificationConfigreturnsgoogle.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+jsonSHOULD 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 field | Query parameter |
|---|---|
context_id | contextId |
page_size | pageSize |
page_token | pageToken |
task_id | taskId |
GET /tasks?contextId=uuid&status=TASK_STATE_WORKING&pageSize=50&pageToken=cursor
GET /tasks/{id}?historyLength=10Type 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:
| Kind | Identifier | Notes |
|---|---|---|
| Media type | application/a2a+json | Intended for the HTTP+JSON/REST binding; UTF-8 JSON text; file extension .a2a.json |
| HTTP header | A2A-Version | The protocol version the client uses, in the format Major.Minor (for example 1.0); an unsupported version returns VersionNotSupportedError |
| HTTP header | A2A-Extensions | A comma-separated list of the extension URIs the client wants to use for this request |
| Well-known URI | /.well-known/agent-card.json | Returns 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
- Core Protocol Specification : method mapping, error code table, version negotiation.
- Common Workflows and Examples : end-to-end request and response examples over the HTTP+JSON binding.
- Custom Protocol Bindings : the rules for adding a binding of your own.
Source: A2A official specification