1.1

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).

Fig. 1.1the A2A stack for test-runnerlayers
The A2A stack for test-runner The planner, a client agent with a card cache and an interface choice, sits on top. Below it are the three protocol layers A2A defines for test-runner at localhost:41241: bindings with the paths /.well-known/agent-card.json, /a2a/jsonrpc and /a2a/rest, the operations, and the data model. Under a dashed line sits what test-runner builds itself: an HTTP router, a request handler, a task store and an event broadcast, and below them the opaque agent logic, where a real agent would also keep a model and tools. CLIENT AGENT you build it A2A PROTOCOL card and bindings operations data model A2A defines it TEST-RUNNER · LOCALHOST:41241 server agent logic its owner builds it planner card cache: agents by skill id interface: JSONRPC, version 1.0 /.well-known/agent-card.json the card, a plain GET GET the card /a2a/jsonrpc JSONRPC 1.0 /a2a/rest HTTP+JSON 1.0 POST SendMessage SendMessage · SendStreamingMessage · GetTask ListTasks · CancelTask · SubscribeToTask 4 push config operations · GetExtendedAgentCard AgentCard · Task · TaskStatus · Message · Part Artifact · TaskStatusUpdateEvent · TaskArtifactUpdateEvent HTTP router Handler routes 3 paths request handler Agent.send creates the task task store Agent.tasks in memory broadcast Agent.broadcast SSE and webhooks run_tests() agents.py model not in the kit Git, container not in the kit
A2A defines the card, the bindings, the operations, and the objects, while test-runner's server parts and agent logic below the dashed line belong to its owner. Read from the planner down. Above the dashed line sit the three layers of spec §1.3 with test-runner's real paths from the captured agent cards. Below it are the kit's own parts, and dashed boxes mark what a production agent adds.

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.

Fig. 1.2what A2A guarantees and what the host buildscomparison
What A2A guarantees and what the host builds Two columns of six rows. Left, what the A2A specification guarantees: a card at a known path, declared security schemes with credentials in HTTP headers, task ids and states where a finished task never changes, ordered events per stream with at least one attempt per webhook, tasks readable with GetTask while the server keeps them, and four kinds of part with media types. Right, in grey, what the host builds: which agents to trust, issuing credentials, what an approval allows, exactly-once effects, its own task records and retention, and what content to believe. A · THE PROTOCOL GUARANTEES B · THE HOST BUILDS a card at a known path /.well-known/agent-card.json which agents to trust registries, allowlists, signing keys declared security schemes credentials travel in HTTP headers issuing the credentials tokens, OAuth, an operator channel task ids and states a finished task never changes what an approval allows authorization policy and audit ordered events per stream at least one attempt per webhook exactly-once effects dedupe and idempotent handlers GetTask while it is kept no retention period is set your own task records retention, history, purge four kinds of part each with a media type what to believe validation, injection checks
A2A fixes the messages, states, and events between agents, while trust, discovery, retention, and exactly-once effects stay with the host. Read across each row, one row per step. The left box is what the specification guarantees, and the grey box beside it is what you build. No capture: the rows come from spec §1, §3.3.1, §3.4.1, §3.7, §4.3.3, §7, §8.2, and §13.1.

The specification also contradicts itself in ten places that change your code, listed below and settled in the sources reference.

ConflictWhat disagrees
D1the HTTP verb for SubscribeToTask
D2whether a plain SendMessage waits
D3whether a stream closes at an interrupted state
D4 and D5the names of the push configuration objects
D6the name of the card's security field
D11deprecated OAuth flows
D12the page field names of ListTasks
D13the HTTP+JSON error body
D36the error for another client's task

A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10