4.3

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 history field should be left out.

With historyLength 1, the kit returns only the newest message of the review task:

GetTask with historyLength 1jsonFull log
  "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"
          }
        ]
      }
    ],
The JSON-RPC envelopes, the reply's ids, status, and artifacts, and the ids inside the message are cut.

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:

SDKhistoryLength unset0below 0
a2a-python 1.2.2all history in both operationsan empty history arrayInvalidParamsError
a2a-goall history in GetTask, the last 100 messages in ListTasksthe field is omittedthe field is omitted
a2a-javaall history in GetTask, none in ListTasksan empty listInvalidParamsError
a2a-jsall history in both operationsthe field is omittedomitted over JSON-RPC, HTTP 400 over REST
a2a-dotnetall history in both operationsan empty array in GetTask, no field in ListTasksInvalidParamsError over JSON-RPC
a2a-rsall history in both operationsan empty historyan 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 includeArtifacts is false, which is the default, the artifacts field must be left out completely.

The kit asks test-runner, which holds five tasks, for pageSize 2 and historyLength 0:

the first page of ListTasksjsonFull log
    "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": 5
Each task is cut to its id, state, and status timestamp, and the token is cut after its first 44 characters.

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

Fig. 4.5history regimes and list pagesstructure
History regimes and list pages Top: the stored history of review task e5c95b09, four messages from history[0] to history[3], plus the status message 2 findings, which is never part of history. With historyLength unset GetTask returns all four messages, with historyLength 1 only history[3], and with historyLength 0 no history field. Bottom: the five tasks on test-runner sorted by status timestamp, newest first. ListTasks with pageSize 2 returns f22ed7af and 8ae21dcb, then 728ba084 and d0c28826, and each page ends with an opaque cursor token for the next one. The fifth task, 3d8f7801, was not requested. Neither page carries artifacts or history. A third call filters on TASK_STATE_CANCELED with no historyLength and gets f22ed7af with its full history. A · HISTORY GetTask on the review task e5c95b09, held by code-reviewer historyLength unset 1 B · PAGES ListTasks on test-runner with pageSize 2 and historyLength 0 id state status.timestamp history[0] ROLE_USER Review this diff of payments-api. + refunds.diff history[1] ROLE_AGENT Which base branch should I compare this diff against? history[2] ROLE_USER main history[3] ROLE_AGENT Comparing the diff against main status.message 2 findings, returned every time, never in history history messages returned 4 1 historyLength 0, on task d0c28826 in 04-polling.http: the reply has no history field at all f22ed7af TASK_STATE_CANCELED 09:00:03.750 8ae21dcb TASK_STATE_FAILED 09:00:03.000 728ba084 TASK_STATE_COMPLETED 09:00:02.250 d0c28826 TASK_STATE_COMPLETED 09:00:01.500 3d8f7801 TASK_STATE_COMPLETED 09:00:00.750 page 1 returns cursor 1 page 2 returns cursor 2 not requested totalSize 5 on both pages, and no task carries artifacts or history filter on TASK_STATE_CANCELED, no historyLength: f22ed7af with its full history, token ""
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:

SDKTokenPage sizeLast page
a2a-python 1.2.2URL-safe base64 of a JSON cursor with the status timestamp and the task id50 by default, 1 to 100 or error -32602""
a2a-goURL-safe base64 of the update time and the task id50 by default, 1 to 100 or error -32600""
a2a-javaplain text, the status time in epoch milliseconds, a colon, and the task id50 by default, 1 to 100 or error -32602""
a2a-jsbase64 of the status timestamp, a bar, and the task id50 by default, 1 to 100 or error -32602""
a2a-dotneta decimal offset such as 5050 by default, and only JSON-RPC rejects a size outside 1 to 100""
a2a-rsa decimal offset over tasks sorted by id, against the order rule above50 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