What A2A standardizes
A2A defines a data model, a set of operations, and three bindings for agents that cannot see inside each other, and leaves everything inside an agent to the implementation.
Your planner needs the unit tests of payments-api run at commit 9f3c2e1. The test-runner agent does that job on port 41241, in a container the platform team owns. You cannot import it as a function. You can only send it a request and read what comes back.
The specification describes such agents as independent AI agent systems whose insides can be hidden. When you finish this section, you can name the three layers, state the core rules, and say where A2A stops.
Three layers in the specification
The specification has three separate layers.
Data model: what the records are. Layer 1 defines them as Protocol Buffer messages, and the proto file is normative.
Operations: what a client can ask for. Layer 2 describes the eleven RPCs of A2AService, apart from the protocol that carries them.
Bindings: how the bytes travel. Layer 3 maps the operations onto JSON-RPC, gRPC, and HTTP+JSON.
A client first reads the AgentCard, usually at /.well-known/agent-card.json, with a plain GET that is none of the eleven operations. The card of test-runner lists /a2a/jsonrpc and /a2a/rest, and figure 1.1 stacks the layers behind them.
Below the dashed line, test-runner builds what the protocol leaves open: an HTTP router, a request handler, a task store, and an event broadcast. The §1.3 diagram lists a Get Agent Card operation that §3.1 never defines (conflict D25), and §1.4 misnames the proto path (conflict D15).
The core rules
An agent is opaque: agents work together without sharing their internal reasoning, plans, or tool code, so a client sees only what comes back.
The server chooses the reply: a message gets either a new Task or a direct Message in reply. The direct reply suits a simple exchange, and SendMessage shows both.
The server owns the task: a client cannot supply the taskId of a new task, and the client mints only the messageId.
A task is in one of nine states: status.state holds one TaskState value, four of them terminal and two interrupted. Task, TaskStatus, and TaskState lists all nine.
A terminal task does not change: no message moves it again, as CancelTask and terminal states shows.
Artifacts carry results: a message should not carry the output of a task, so the planner reads the test count from summary.json.
Events arrive in order: every implementation must deliver events in the order it created them. A client that reconnects confirms the state with GetTask.
Credentials travel in HTTP headers: the client puts the credentials in the headers or metadata of the transport on every A2A request. So the planner sends Authorization: Bearer to deployer with every request.
The boundary with MCP
MCP connects an agent to its tools and resources, and A2A connects agents to each other. The 1.0 announcement puts it in short form: MCP works inside an agent, and A2A works between agents. No card names a tool: the run-tests skill on the test-runner card describes the work and stops there. MCP fundamentals covers the other protocol.
What A2A leaves to the host
A2A defines no registry: the specification sets no standard API for curated registries. It issues no credentials, because the transport handles identity, not A2A itself. It sets no retention period, so a task id can be invalid, expired, or already completed and deleted. It promises no exactly-once effect, because Send Message operations are allowed to be idempotent but do not have to be. Also, a webhook gets at least one attempt. Figure 1.2 pairs each guarantee with the host's job.
The specification also contradicts itself in ten places that change your code, listed below and settled in the sources reference.
| Conflict | What disagrees |
|---|---|
| D1 | the HTTP verb for SubscribeToTask |
| D2 | whether a plain SendMessage waits |
| D3 | whether a stream closes at an interrupted state |
| D4 and D5 | the names of the push configuration objects |
| D6 | the name of the card's security field |
| D11 | deprecated OAuth flows |
| D12 | the page field names of ListTasks |
| D13 | the HTTP+JSON error body |
| D36 | the error for another client's task |
A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10