Thomas Piacentini
← Atelier

Chapitre

What A2A standardizes

Texte original · anglais

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 {{spec §1}}. 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 {{spec §1.3}}.

Data model: what the records are. Layer 1 defines them as Protocol Buffer messages {{spec §1.3}}, and the proto file is normative {{spec §1.4}}.

Operations: what a client can ask for. Layer 2 describes the eleven RPCs of A2AService {{proto A2AService}}, apart from the protocol that carries them {{spec §1.3}}.

Bindings: how the bytes travel. Layer 3 maps the operations onto JSON-RPC, gRPC, and HTTP+JSON {{spec §1.3}}.

A client first reads the AgentCard, usually at /.well-known/agent-card.json {{spec §8.2}}, with a plain GET that is none of the eleven operations. The card of test-runner lists /a2a/jsonrpc and /a2a/rest, and figure 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
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.
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.

Original SVG

Original source
id: fig-spec-layers
kind: layers
title: the A2A stack for test-runner
claim: 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.
caption: 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 {{spec §1.2}}, 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 {{spec §3.1.1}}. 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 {{spec §3.4.2}}, and the client mints only the messageId {{proto Message}}.

A task is in one of nine states: status.state holds one TaskState value {{proto TaskState}}, 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.

Original source
label: the end of a task
source: spec §3.1.1
---
A task in a terminal state takes no more messages. The terminal states are `TASK_STATE_COMPLETED`, `TASK_STATE_FAILED`, `TASK_STATE_CANCELED`, and `TASK_STATE_REJECTED`.

Artifacts carry results: a message should not carry the output of a task {{spec §3.7}}, 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 {{spec §3.5.2}}. A client that reconnects confirms the state with GetTask {{spec §3.7}}.

Credentials travel in HTTP headers: the client puts the credentials in the headers or metadata of the transport on every A2A request {{spec §7.3}}. 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 {{docs a2a-and-mcp}}. The 1.0 announcement puts it in short form: MCP works inside an agent, and A2A works between agents {{docs announcing-1.0}}. 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 {{docs agent-discovery}}. It issues no credentials, because the transport handles identity, not A2A itself {{spec §7}}. It sets no retention period, so a task id can be invalid, expired, or already completed and deleted {{spec §3.3.2}}. It promises no exactly-once effect, because Send Message operations are allowed to be idempotent but do not have to be {{spec §3.3.1}}. Also, a webhook gets at least one attempt {{spec §4.3.3}}. Figure pairs each guarantee with the host's job.

Fig. 1.2what A2A guarantees and what the host buildscomparison
A2A fixes the messages, states, and events between agents, while trust, discovery, retention, and exactly-once effects stay with the host.
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.

Original SVG

Original source
id: fig-guarantees
kind: comparison
title: what A2A guarantees and what the host builds
claim: A2A fixes the messages, states, and events between agents, while trust, discovery, retention, and exactly-once effects stay with the host.
caption: 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.

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
Original source
- Build your client against the operations and objects, and keep each binding in one module.
- Treat everything behind a remote agent's endpoint as private.
- Mint a fresh `messageId` for every message, read results from artifacts, and send credentials in HTTP headers.

Sources: spec §1, §1.2, §1.3, §1.4, §3.1.1, §3.3.1, §3.3.2, §3.4.1, §3.4.2, §3.5.2, §3.7, §4.3.3, §7, §7.3, §8.2, §13.1 (research/sources/specification.md); proto A2AService, Message, TaskState (research/sources/a2a.proto); docs a2a-and-mcp, announcing-1.0, agent-discovery (research/sources/docs.md); capture/a2a_ref.py, capture/planner.py; capture/out/01-agent-cards.http, 03-blocking-task.http, 10-cancel.http, 19-planner.http

Code et livrables 1
Ce que vous en retenez

Enregistré dans votre carnet sur cet appareil.

Sources et limites

Les repères de lecture sont déclaratifs. Les résultats de tests sont enregistrés séparément ; ils valent pour les cas exécutés.

AI Engineering from Scratch · 3f9715c · MIT

Télécharger ce fichier ↓