GetTask and ListTasks
GetTask and ListTasks are your recovery path, and both follow exact rules about which parts of a task they leave out.
The planner's stream to deployer drops. A webhook says a test run has finished. The planner restarts with nothing but task ids in its log. In each case the next step is the same: ask the agent for the task it has stored.
When you finish this section, you can fetch the history you need, page through an agent's tasks, and explain a missing field.
GetTask returns the stored task
GetTask takes the task id and an optional historyLength. It returns the Task as the server holds it: status, artifacts, and history.
An id you are not allowed to see gets TaskNotFoundError, so a not-found answer never proves that a task is gone.
historyLength
History: the messages a task has kept, apart from the current status message. The historyLength parameter sets how many a response carries, with the same meaning in every operation:
- Unset: no limit. The server returns its default amount of history, which the implementation decides and which can be all of it.
- A number above zero: at most that many recent messages from the history of the task.
- Zero: no history, and the
historyfield should be left out.
With historyLength 1, the kit returns only the newest message of the review task:
"method": "GetTask",
"params": {
"id": "e5c95b09-6d4b-4b3b-8693-91e81472d12f",
"historyLength": 1
}
…
"history": [
{
"messageId": "8f9ee658-e185-409a-9294-8d4d97ef77bb",
…
"role": "ROLE_AGENT",
"parts": [
{
"text": "Comparing the diff against main"
}
]
}
],That message is not the newest thing the agent said. The final status message, "2 findings", stays in status.message. In the kit and the reference SDK, a status message joins history only when a newer one replaces it. Read history and status.message together.
The server can also apply a lower limit, and the history does not have to keep every message. The unset case is implementation-defined, and the SDKs also read 0 and a negative value in different ways:
| SDK | historyLength unset | 0 | below 0 |
|---|---|---|---|
| a2a-python 1.2.2 | all history in both operations | an empty history array | InvalidParamsError |
| a2a-go | all history in GetTask, the last 100 messages in ListTasks | the field is omitted | the field is omitted |
| a2a-java | all history in GetTask, none in ListTasks | an empty list | InvalidParamsError |
| a2a-js | all history in both operations | the field is omitted | omitted over JSON-RPC, HTTP 400 over REST |
| a2a-dotnet | all history in both operations | an empty array in GetTask, no field in ListTasks | InvalidParamsError over JSON-RPC |
| a2a-rs | all history in both operations | an empty history | an empty history |
ListTasks returns pages, newest first
ListTasks filters by contextId, status, and statusTimestampAfter, and shapes the page with pageSize, pageToken, historyLength, and includeArtifacts. It returns only the tasks that the authenticated client can see, under four rules:
- Size: without
pageSize, a page holds at most 50 tasks, and the maximum is 100. - Order: tasks must come sorted by their status timestamp, newest update first.
- Token: the response must always contain
nextPageToken. On the last page it holds the empty string. - Artifacts: when
includeArtifactsis false, which is the default, theartifactsfield must be left out completely.
The kit asks test-runner, which holds five tasks, for pageSize 2 and historyLength 0:
"tasks": [
{
"id": "f22ed7af-848d-4f4d-8cd1-3204d1e1bbaf",
…
"state": "TASK_STATE_CANCELED",
…
"timestamp": "2026-10-06T09:00:03.750Z"
…
"id": "8ae21dcb-7449-4d90-82a6-ac01b20fd782",
…
"state": "TASK_STATE_FAILED",
…
"timestamp": "2026-10-06T09:00:03.000Z"
…
],
"nextPageToken": "eyJ0cyI6IjIwMjYtMTAtMDZUMDk6MDA6MDMuMDAwWiIs…",
"pageSize": 2,
"totalSize": 5The second page holds the completed runs 728ba084 and d0c28826. Neither page carries artifacts, although both completed runs stored a log and a summary. A third request filters on TASK_STATE_CANCELED and gets one task, a pageSize of 50, and an empty nextPageToken. Figure 4.5 draws the pages beside the history regimes.
GetTask trims history to the newest messages you ask for, and ListTasks returns newest-first pages that leave out artifacts until you ask for them. Top, the stored history of task e5c95b09 and what each historyLength returns. Bottom, the five tasks on test-runner in list order, grouped into the pages the kit requested. Ids are shortened to 8 characters.The specification requires cursor-based pagination and gives the token no format, so each SDK makes its own:
| SDK | Token | Page size | Last page |
|---|---|---|---|
| a2a-python 1.2.2 | URL-safe base64 of a JSON cursor with the status timestamp and the task id | 50 by default, 1 to 100 or error -32602 | "" |
| a2a-go | URL-safe base64 of the update time and the task id | 50 by default, 1 to 100 or error -32600 | "" |
| a2a-java | plain text, the status time in epoch milliseconds, a colon, and the task id | 50 by default, 1 to 100 or error -32602 | "" |
| a2a-js | base64 of the status timestamp, a bar, and the task id | 50 by default, 1 to 100 or error -32602 | "" |
| a2a-dotnet | a decimal offset such as 50 | 50 by default, and only JSON-RPC rejects a size outside 1 to 100 | "" |
| a2a-rs | a decimal offset over tasks sorted by id, against the order rule above | 50 by default, and a size above 100 is cut to 100 | "" |
Send every parameter
The third request sends no historyLength and gets the full history, as the reference SDK would. With 0, the SDK returns an empty history array where the specification asks for no field. So treat a missing history and an empty one alike.
Pass back exactly the token you were given. The migration guide calls these fields cursor, limit, and nextCursor, names the proto does not define (conflict D12).
The bound of statusTimestampAfter is inclusive: the result holds only tasks whose status timestamp is at or after this value. To fetch only what changed, send the newest status timestamp you have seen, and skip the boundary task you already hold.
A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10