The planner reads three cards and delegates three tasks: one completes at once, one after a question, and one after an operator approves. Lanes run top to bottom in the order of the planner log, and ids are shortened to 8 characters.
Every claim in this manual traces to a ranked source, and every request, response, and stream frame comes from a capture kit you can run yourself.
This manual explains the Agent2Agent protocol, A2A, at release 1.0.1, through one system: a planner that gives work to three agents it cannot see inside.
Who this manual is for
You have built an agent that calls tools or a model API, and you know HTTP and JSON. Now you want to give work to an agent that another team owns.
After the last part, you can:
- Read an agent card and say what the agent offers, how to reach it, and what it requires.
- Predict which state a task is in at any point of a run, and what a client can do next.
- Choose between a blocking call, polling, streaming, and push notifications for a given job.
- Read any A2A request, response, or stream frame line by line, in either JSON binding.
- Name the errors a client must handle and the rules a server can break without noticing.
The A2A lesson predates version 1.0, so where the two differ, follow this manual.
How it was made
The manual pins tag v1.0.1 of the A2A repository, commit 3303592. In requests and cards, that release is protocol version 1.0, because requests, responses, and Agent Cards should not carry a patch version number {{spec §3.6}}. The facts were also checked against the main branch at commit 679ab3a of 2026-10-05, where v1.0.1 was still the latest release.
Facts come from five sources, ranked by authority. When two of them disagree, the higher one wins and the text says so.
| Rank | Source | What the manual takes from it | Source key |
|---|---|---|---|
| 1 | specification/a2a.proto at v1.0.1 |
every object, field, enum value, and method | proto and a message or enum name |
| 2 | docs/specification.md at v1.0.1 |
every behavior rule, stated in our own words | spec and a section number |
| 3 | the project's documentation pages at v1.0.1 | the project's own framing, flagged where a page is out of date | docs and a page name |
| 4 | the reference SDK, a2a-python 1.2.2 | what a production implementation does where the specification is silent | sdk and a source file |
| 5 | the capture kit in capture/ |
every request, response, and stream frame the manual shows | the capture file name |
The proto, the specification, and the documentation pages are vendored unchanged in the repository.
The specification disagrees with itself or the proto on the HTTP verb for SubscribeToTask (conflict D1) and on whether a send waits (conflict D2). It also disagrees on when a stream closes (conflict D3) and on the name of the card's security field (conflict D6). The sources reference lists all forty conflicts with the section that discusses each.
The capture kit
The capture kit runs three remote agents and a recording client on your machine, with the Python standard library only and no network or keys.
| Agent | Port | What it does | What its runs show |
|---|---|---|---|
test-runner |
41241 | runs a test suite and streams the log | streaming, artifacts in chunks, polling, cancel, push notifications, both JSON bindings |
code-reviewer |
41242 | reviews a diff against a base branch | direct message replies, TASK_STATE_INPUT_REQUIRED, rejected content types, no push support |
deployer |
41243 | deploys a build to staging after an operator approves | bearer authentication, TASK_STATE_AUTH_REQUIRED with approval outside A2A, rejection, extended and signed cards |
A client walks through the real planner.
Seeded ids and a fixed clock make two runs byte-identical. The kit README lists where the kit differs from the reference SDK.
Conventions
Each section records its sources in the manual source, where the audit checks every quote and number. The sections do not show them. The sources reference lists them.
A listing copies lines from a capture file unchanged, and a … marks a cut that the note explains.
Field names and enum values are set in code type as they travel, such as messageId. Figures shorten task and context ids to 8 characters, so 728ba084-97eb-422b-b94b-b0fe9153ce2c appears as 728ba084.
Figures animate on the web, where a Replay button runs the steps again, and print and reduced motion show the final frame.
A first run
The kit needs Python 3 and four free ports on 127.0.0.1: 41241 to 41243 for the agents and 41250 for the webhook receiver. From the repository root, run it and check it:
cd manuals/a2a-101
python3 capture/run.py
python3 capture/run.py --checkOpen capture/out/02-message-reply.http first: a question to code-reviewer and a direct answer, with no task. Then open capture/out/05-streaming.http, where a request to test-runner opens a stream of nine data: lines:
POST /a2a/jsonrpc HTTP/1.1
Host: localhost:41241
Content-Type: application/json
A2A-Version: 1.0
Accept: text/event-stream
…
HTTP/1.1 200 OK
Content-Type: text/event-stream
data: {"jsonrpc": "2.0", "id": 1, "result": {"task": {"id": "728ba084-97eb-422b-b94b-b0fe9153ce2c", … "state": "TASK_STATE_SUBMITTED", …Original source
title: the start of a stream
source: capture/out/05-streaming.http
lang: http
note: The request body and the rest of the first frame are cut. Frames 2 to 9 follow it in the file.
---
POST /a2a/jsonrpc HTTP/1.1
Host: localhost:41241
Content-Type: application/json
A2A-Version: 1.0
Accept: text/event-stream
…
HTTP/1.1 200 OK
Content-Type: text/event-stream
data: {"jsonrpc": "2.0", "id": 1, "result": {"task": {"id": "728ba084-97eb-422b-b94b-b0fe9153ce2c", … "state": "TASK_STATE_SUBMITTED", …The first frame is the task itself, and one task, request by request reads all nine.
How the parts are ordered
Part 1 gives you the whole protocol. Parts 2 to 6 each take one layer, from the AgentCard to security and extensions, and Part 7 builds a client and a server:
| Part | What it covers |
|---|---|
| 1 · The Protocol on One Page | A2A standardizes how one agent finds another agent, gives it work, and follows that work, and it leaves the agent itself out of scope. |
| 2 · AgentCard | Before a client sends a message, the AgentCard tells it what the agent offers, where to reach it, and what it requires. |
| 3 · Data Model | Every A2A exchange is built from five objects: Message, Part, Artifact, Task, and the contextId that groups tasks. |
| 4 · Operations | Eleven operations create, read, cancel, and follow tasks, and each one has rules that a client must know before it calls. |
| 5 · Bindings | The same operations travel over JSON-RPC, HTTP+JSON, and gRPC, with two headers and one error model shared by all three. |
| 6 · Security and Extensions | The card declares how to authenticate and which extensions apply, and the specification lists what each side must check. |
| 7 · Implementing A2A | A client and a server follow the rules of the earlier parts, and the official test kit checks the server against them. |
| R · Reference | Operations by binding, objects and fields, task states, errors, a glossary, the sources, and the index of figures. |
Original source
Colour in figures
Each hue keeps one meaning in every figure:
| Colour | Meaning |
|---|---|
| violet | the client agent and what it sends |
| blue | remote agents, their cards, and the messages they send back |
| green | parts and artifacts: the content a task produces |
| amber | tasks, task states, and transitions |
| teal | the server's stored task records |
| indigo | streams, subscriptions, and push notifications |
| plum | the model or logic inside an agent, which A2A never shows |
| olive | tools and systems an agent calls on its own: CI, Git, MCP servers |
| rose | errors, failure, rejection, and cancellation |
| grey | the operator, the host, and anything outside the protocol |
Original source
Figure teaches seven of the eight arrow styles. It leaves out solid plum, because A2A never carries a model call.
Original source
id: fig-reading-a-sequence
kind: sequence
title: reading a sequence figure in this manual
claim: Each of the seven arrow styles marks one kind of exchange, and the label on each arrow is a real name from a run of the kit.
caption: Read each numbered row from the tail of the arrow to its head. The note under a label gives the style and its meaning. The rows come from 03-blocking-task.http, 05-streaming.http, 15-push.http, 19-planner.log, and 11-errors.http, and the task store is the kit's own store inside test-runner.Sources: spec §3.6, §3.7 (research/sources/specification.md); proto TaskState (research/sources/a2a.proto); docs life-of-a-task (research/sources/docs.md); sdk src/a2a/server/tasks/task_manager.py; manual.json; research/sources/README.md; research/brief-spec.md §12.2; research/brief-docs.md; research/sources/specification-main.md (main at 679ab3a); capture/README.md, capture/run.py, capture/agents.py, capture/a2a_ref.py, capture/planner.py; capture/out/02-message-reply.http, 03-blocking-task.http, 05-streaming.http, 11-errors.http, 15-push.http, 19-planner.log