A2A JSON-RPC binding
One A2A operation carries every AAP skill: SendMessage. The automotive request lives in params.message.parts[0].data; the response returns in result.message.parts[0].data.
This is AAP's required A2A transport. MCP and PAP OpenAPI are separate native interfaces to the same payloads. The older A2A HTTP+JSON binding remains removed.
Endpoint and method
Use the Agent Card's supportedInterfaces[] entry with protocolBinding: "JSONRPC" and protocolVersion: "1.0". Send HTTPS POST with JSON-RPC jsonrpc: "2.0", a request id, method SendMessage, and an A2A Message in params.message. If the selected interface declares tenant, echo it in params.tenant.
Clients MUST include configuration.acceptedOutputModes with the expected AAP response media type. Modes are alternatives: an unsupported choice does not invalidate a supported one.
| Wire field | Required form |
|---|---|
| Request/response role | ROLE_USER / ROLE_AGENT |
| Message and Part kind | ProtoJSON member discriminator; no kind field |
messageId | Nonempty, unique for each message; response differs from request |
Server contextId | Nonempty; preserve a valid interaction context or create one |
| First part | Matching typed AAP data and vendor mediaType |
JSON-RPC result | SendMessageResponse: { "message": <Message> } |
An initial client request may omit contextId. A server response may not. AAP uses direct response Messages; it does not create a Task or require an Artifact.
Only advertise A2A capabilities that work. When an unsupported operation is called, use its standard A2A error:
| Operation | Error | JSON-RPC |
|---|---|---|
| Streaming or task subscription without streaming support | UnsupportedOperationError | -32004 |
| Push notification configuration without support | PushNotificationNotSupportedError | -32003 |
| Extended Agent Card without support | UnsupportedOperationError | -32004 |
| A task operation this server does not implement | UnsupportedOperationError | -32004 |
A server implementing additional A2A operations follows their upstream semantics, including task-not-found behavior. AAP clients MUST NOT depend on that optional surface.
Request headers
A2A service parameters travel as HTTP headers on JSON-RPC requests:
POST /a2a HTTP/1.1
Host: demo-toyota.example.com
Content-Type: application/json
A2A-Version: 1.0
A2A-Extensions: https://autoagentprotocol.org/extensions/aap/v3.0
The selected Agent Card's authorization requirements also apply. Portable A2A clients should send both headers as shown. AAP makes them optional on a contract-pinned endpoint: its URL and configuration already select one A2A 1.0 interface and one exact AAP contract.
- If
A2A-Versionis absent, the ingress MUST use the endpoint's configured1.0. A supplied unsupported value returnsVersionNotSupportedError(-32009) before skill execution. An explicitly empty value retains A2A's0.3meaning and is rejected when unsupported. - If
A2A-Extensionsis absent, the ingress MUST select the endpoint's exact AAP URI. If supplied, its comma-separated list MUST contain that exact URI or returnExtensionSupportRequiredError(-32008). Unknown unrelated extensions are ignored; a different AAP version is not a match. - Apply these defaults before dispatch, and validate the full AAP envelope, payload, consent, authorization and tenant. An endpoint serving ambiguous contract versions cannot infer a selection. Query parameters do not override headers, and supplied values MUST NOT be silently replaced.
This is an explicit AAP compatibility extension to strict upstream A2A header handling. A request using these omissions is accepted by this AAP ingress; it is not a promise that an arbitrary A2A server accepts it. Normalize the inferred values before forwarding to a strict A2A implementation. The Agent Card still declares the automotive extension required: true, and clients still implement its complete semantics. Header omission never selects a different contract or grants permission.
Servers SHOULD echo activated extensions in the response A2A-Extensions header. An activation failure MUST name the exact URI and header in its message and standard ErrorInfo metadata; see recovery instructions.
A complete exchange
The request below uses only advertised search capabilities. The type and mediaType identify the same skill.
{
"jsonrpc": "2.0",
"id": "req_001",
"method": "SendMessage",
"params": {
"message": {
"messageId": "01HZ9F4M7C0X3K5RN8B3WJTW2P",
"role": "ROLE_USER",
"parts": [
{
"data": {
"type": "inventory.search.request",
"filters": {
"make": [
"Honda"
],
"status": [
"available"
],
"price_max": 35000
},
"pagination": {
"limit": 20
},
"sort": {
"field": "price",
"order": "asc"
}
},
"mediaType": "application/vnd.autoagent.inventory-search-request+json"
}
]
},
"configuration": {
"acceptedOutputModes": [
"application/vnd.autoagent.inventory-search-response+json"
]
}
}
}
Complete response: one matching vehicle
{
"jsonrpc": "2.0",
"id": "req_001",
"result": {
"message": {
"messageId": "response_001",
"contextId": "context_001",
"role": "ROLE_AGENT",
"parts": [
{
"data": {
"type": "inventory.search.response",
"data": {
"total": 1,
"limit": 20,
"next_cursor": null,
"applied_filters": {
"make": [
"Honda"
],
"status": [
"available"
],
"price_max": 35000
},
"sort": {
"field": "price",
"order": "asc"
},
"vehicles": [
{
"vehicle_id": "vehicle_001",
"make": "Honda",
"model": "CR-V",
"year": 2024,
"condition": "used",
"status": "available",
"price": 32995,
"updated_at": "2026-10-24T14:00:00Z"
}
]
}
},
"mediaType": "application/vnd.autoagent.inventory-search-response+json"
}
]
}
}
}
All five skills use this envelope. The complete request and response fixtures, skill schemas and generated OpenAPI provide copyable machine-readable forms.
Error mapping (A2A Section 9.5)
A failed skill returns a JSON-RPC error. error.data is an array of standard ProtoJSON Any detail objects, led by google.rpc.ErrorInfo. The typed AAP error appears in a google.protobuf.Struct object's value. Never place a bare AAP object directly in error.data.
Complete validation error with all detected field problems
{
"jsonrpc": "2.0",
"id": "req-3",
"error": {
"code": -32602,
"message": "Invalid params: filters.year_min must be an integer",
"data": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "SCHEMA_VALIDATION_FAILED",
"domain": "autoagentprotocol.org",
"metadata": {
"code": "SCHEMA_VALIDATION_FAILED",
"error_id": "err_01HZ9EXAMPLE",
"retryable": "false",
"created_at": "2026-04-30T10:15:30Z"
}
},
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "/filters/year_min",
"description": "type: must be an integer"
},
{
"field": "/filters/made_up",
"description": "additionalProperties: unknown filter key"
}
]
},
{
"@type": "type.googleapis.com/google.protobuf.Struct",
"value": {
"type": "aap.error",
"error_id": "err_01HZ9EXAMPLE",
"code": "SCHEMA_VALIDATION_FAILED",
"message": "request failed validation with 2 errors",
"retryable": false,
"details": {
"errors": [
{
"instanceLocation": "/filters/year_min",
"keyword": "type",
"error": "must be an integer"
},
{
"instanceLocation": "/filters/made_up",
"keyword": "additionalProperties",
"error": "unknown filter key"
}
]
},
"created_at": "2026-04-30T10:15:30Z"
}
}
]
}
}
AAP code | JSON-RPC code | Notes |
|---|---|---|
SCHEMA_VALIDATION_FAILED | -32602 | JSON-RPC "Invalid params". |
MISSING_REQUIRED_FIELD | -32602 | "Invalid params". |
INVALID_CONDITION | -32602 | "Invalid params" — a condition value is in the wrong vocabulary. |
UNSUPPORTED_SKILL | -32602 | Invalid AAP request parameter: the dealer does not implement the skill identified by the typed payload. The JSON-RPC method is still SendMessage. Reserve -32004 for A2A UnsupportedOperationError with A2A's required ErrorInfo reason and domain. |
UNSUPPORTED_FILTER | -32602 (Invalid params) | Filter or feature code is not supported here. |
UNSUPPORTED_SORT | -32602 (Invalid params) | Sort field is not advertised. |
INVALID_CURSOR | -32602 (Invalid params) | Cursor is invalid, expired or bound to another request. |
DEALER_NOT_FOUND | -32000 | No accessible seller for this dealer ID. |
VEHICLE_NOT_FOUND | -32000 | Application error. |
VEHICLE_UNAVAILABLE | -32000 | Application error. |
CONTACT_CONSENT_REQUIRED | -32000 | Application error. |
INVALID_CONSENT | -32000 | Application error. |
APPOINTMENT_TIME_UNAVAILABLE | -32000 | Application error. |
IDEMPOTENCY_CONFLICT | -32000 | Application error — an idempotency_key was reused with a different payload. |
RATE_LIMITED | -32000 | Generic JSON-RPC server error. NOT -32002: A2A §5.4 assigns that code to TaskNotCancelableError, which both reference SDKs decode as a terminal task-lifecycle failure rather than a retryable throttle. |
INTERNAL_ERROR | -32603 | JSON-RPC "Internal error". |
Validation responses MUST include every detectable field problem in details.errors[], with instanceLocation, keyword and a safe error message. A2A protocol/authentication failures remain distinct from automotive skill failures. See errors and retries for extraction, recovery and throttling.