Cheat sheets

A2A Protocol

Discover an agent, send it work, follow the task, read its errors. Pinned to A2A 1.0.1.

  • Concepts and terms
  • Tasks and commands
  • Annotated code
  • Diagrams
  • Defaults and numbers
  • Troubleshooting
  • Questions and tips

Source

Tasks over JSON-RPC#

TaskCode
Discover an agentGET /.well-known/agent-card.json
Send and wait"method": "SendMessage"
Send and return at once"configuration": {"returnImmediately": true}
Poll a task"method": "GetTask", "params": {"id": "<task id>", "historyLength": 0}
Stream a task"method": "SendStreamingMessage" with Accept: text/event-stream
Reattach to a stream"method": "SubscribeToTask", "params": {"id": "<task id>"}
Answer a question"message": {"contextId": "<ctx>", "taskId": "<task id>", ...}
Register a webhook"taskPushNotificationConfig": {"url": "<url>", "token": "<token>"}

From a2a-101 capture: 01-agent-cards.http, a2a-101 capture: 03-blocking-task.http, a2a-101 capture: 04-polling.http, a2a-101 capture: 05-streaming.http, a2a-101 capture: 06-input-required.http, a2a-101 capture: 10-cancel.http, a2a-101 capture: 14-resubscribe.http, a2a-101 capture: 15-push.http

One SendMessage request#

POST /a2a/jsonrpc HTTP/1.1the JSONRPC url from the card
Host: localhost:41241
Content-Type: application/json
A2A-Version: 1.0required on every request
{"jsonrpc": "2.0", "id": 1, "method": "SendMessage",
"params": {
"message": {"messageId": "<uuid>",the client mints it
"role": "ROLE_USER",
"parts": [{"text": "<request>"}]},
"configuration": {"returnImmediately": true}}}omit to block

From a2a-101 capture: 04-polling.http, a2a-101 §5.4, a2a-101 §1.2, a2a-101 §4.1

HTTP+JSON routes#

CommandWhat it does
POST /message:sendSendMessage
POST /message:streamSendStreamingMessage, a stream of StreamResponse
GET /tasks/{id=*}GetTask. historyLength goes in the query
GET /tasksListTasks
POST /tasks/{id=*}:cancelCancelTask
POST /tasks/{id=*}:subscribeSubscribeToTask. Accept GET too
POST /tasks/{task_id=*}/pushNotificationConfigsCreateTaskPushNotificationConfig
GET /extendedAgentCardGetExtendedAgentCard

From a2a-101 §R1, a2a-101 capture: 16-rest-binding.http

Capture kit and conformance#

python3 run.pythree agents and a client, writes out/
python3 run.py --checkcapture again and compare
git clone --filter=blob:none https://github.com/a2aproject/a2a-tck.git
cd a2a-tck
git checkout 1.0.0.alpha2the TCK tag the manual ran
uv venv && source .venv/bin/activate
uv pip install -e .
./run_tck.py --sut-host http://localhost:9999reads the card, tests each binding

From a2a-101 capture: README.md, a2a-101 §7.3

The capture kit agents#

GETJSON-RPCJSON-RPCBearerpushapproveplanner.pyclient agentAgent cards/.well-known/agent-card.jsontest-runner:41241 stream, pushcode-reviewer:41242 input requireddeployer:41243 bearer, auth requiredWebhook:41250 /a2a-eventsOperatorapproves outside A2AGETJSON-RPCJSON-RPCBearerpushapproveplanner.pyclientagentAgentcards/.well-known/agent-card.jsontest-runner:41241stream,pushcode-reviewer:41242inputrequireddeployer:41243bearer,authrequiredWebhook:41250/a2a-eventsOperatorapprovesoutsideA2A

From a2a-101 capture: README.md, a2a-101 §2.2, a2a-101 §4.6, a2a-101 §7.1

Task states#

TASK_STATE_SUBMITTED
active. Wait, poll, or subscribe.
TASK_STATE_WORKING
active. As for a submitted task.
TASK_STATE_INPUT_REQUIRED
interrupted. Answer with the same taskId and contextId.
TASK_STATE_AUTH_REQUIRED
interrupted. Approval comes outside A2A. Subscribe or poll.
TASK_STATE_COMPLETED
terminal. Read the artifacts.
TASK_STATE_FAILED
terminal. Fix the input and start a new task.
TASK_STATE_CANCELED
terminal. Start a new task in the same context.
TASK_STATE_REJECTED
terminal. Stop and follow the status message.

From a2a-101 §R3

Tips#

  • Send A2A-Version: 1.0 on every request, with no patch number.
  • Set returnImmediately: true when you poll, subscribe, or wait for a webhook.
  • Take the task id and context id from the first frame.
  • Skip any operation whose capability flag is absent or false.
  • Answer a task the caller cannot access with TaskNotFoundError.
  • Process push notifications idempotently. Duplicates can arrive.

From a2a-101 §5.4, a2a-101 §4.1, a2a-101 §1.2, a2a-101 §2.2, a2a-101 §R4, a2a-101 §4.6

One streamed task#

1Clientreads the card and checks capabilities.streamingis true.2Clientposts SendStreamingMessage with a new messageIdand no taskId.3Serverframe 1 is the Task in TASK_STATE_SUBMITTED withnew ids.4Agenta statusUpdate moves the task toTASK_STATE_WORKING.5AgentartifactUpdate frames build test-log withappend, then lastChunk.6Agentthe last statusUpdate sets TASK_STATE_COMPLETED.7Servercloses the stream. The client confirms withGetTask.

From a2a-101 §1.2

Error codes#

CommandWhat it does
-32001 TaskNotFoundErrorHTTP 404, gRPC NOT_FOUND
-32002 TaskNotCancelableErrorHTTP 400, FAILED_PRECONDITION
-32003 PushNotificationNotSupportedErrorHTTP 400, FAILED_PRECONDITION
-32004 UnsupportedOperationErrorHTTP 400, FAILED_PRECONDITION
-32005 ContentTypeNotSupportedErrorHTTP 400, INVALID_ARGUMENT
-32009 VersionNotSupportedErrorHTTP 400, FAILED_PRECONDITION
-32601 MethodNotFoundErrorJSON-RPC only
-32602 InvalidParamsErrorHTTP 400, INVALID_ARGUMENT

From a2a-101 §R4

Defaults#

SettingDefaultNote
returnImmediatelyfalseA send waits for a terminal or interrupted state
historyLengthUnsetServer returns its default amount
includeArtifactsfalseListTasks omits artifacts
pageSize in ListTasks50The maximum is 100
Missing A2A-Version0.3A 1.0 server refuses it
JSON-RPC error status200 OKKit and SDK. The spec sets none
Push token headerX-A2A-Notification-TokenKit and SDK choice
Kit request timeout15 secondsThe spec sets none

From a2a-101 §4.1, a2a-101 §4.3, a2a-101 §5.4, a2a-101 §R4, a2a-101 §4.6, a2a-101 §7.1

Troubleshooting#

SymptomCauseFix
-32009 Protocol version not supportedNo A2A-Version header, read as 0.3Send A2A-Version: 1.0
-32601 Method not foundA 0.3 name such as message/sendUse SendMessage
-32602 Invalid parametersThe message has no messageIdMint a messageId per message
-32005 Content type not supportedAn image/png partSend a mode the card accepts
-32004 on a message or a subscribeThe task is terminalStart a new task
-32002 Task cannot be canceledThe task already endedRead it with GetTask
HTTP 401 on GetExtendedAgentCardNo bearer tokenSend Authorization: Bearer <token>
TCK JSON-RPC records fail with 404The TCK adds a trailing slash to urlPost to the exact url

From a2a-101 capture: 11-errors.http, a2a-101 capture: 10-cancel.http, a2a-101 capture: 18-extended-card.http, a2a-101 §5.4, a2a-101 §7.4, a2a-101 §R3, a2a-101 §7.3

Glossary#

Agent card
JSON that describes an agent, usually at /.well-known/agent-card.json.
Task
the unit of work a server creates for a message, with an id.
Context
a conversation that groups tasks and messages under one contextId.
Message
one turn, with a messageId, a role, and parts.
Part
smallest unit of content: text, raw, url, or data.
Artifact
an output of a task, made of parts. Long ones arrive in chunks.
Push notification
an HTTP POST of a StreamResponse to a client webhook.
Service parameter
a per-request key such as A2A-Version, sent as a header.

From a2a-101 §R5

Q&A#

What does a send return?
One task or one message. A message alone is a direct reply.
Does lastChunk end the task?
No. It closes one artifact only.
Why 200 OK on a JSON-RPC error?
The spec sets no status. The kit and the SDK send 200 OK.
Which interface does a client use?
The first supportedInterfaces entry that it speaks.
How did 0.3 blocking change?
returnImmediately replaced it, and a send now waits.

From a2a-101 §R1, a2a-101 §7.4, a2a-101 §1.2, a2a-101 §R4, a2a-101 §2.2