Task states
Nine values describe a task, and whether the current one is active, interrupted, or terminal tells the client what it can do next.
The proto marks four states terminal and two interrupted. Neither it nor the prose gives a transition table, so the agent decides the order. A blocking SendMessage returns at a terminal or interrupted state. Task, TaskStatus, and TaskState classifies the values and collects the transitions the kit makes. Interrupted states and CancelTask and terminal states explain the client's next step.
| State | Class | Set by | The client does next |
|---|---|---|---|
| TASK_STATE_UNSPECIFIED | none | Nobody: the zero value | Treat it, and any unknown name, as an error. |
| TASK_STATE_SUBMITTED | active | The server, on creation | Wait, poll, or subscribe. |
| TASK_STATE_WORKING | active | The agent, while it works | As for a submitted task |
| TASK_STATE_INPUT_REQUIRED | interrupted | The agent, with a question | Answer with a new message that carries the same taskId and contextId. |
| TASK_STATE_AUTH_REQUIRED | interrupted | The agent, for an authorization | Pass the request to whoever approves it, outside A2A, and subscribe, register a webhook, or poll. |
| TASK_STATE_COMPLETED | terminal | The agent, when the work is done | Read the artifacts for the result. Follow up in a new task with referenceTaskIds. |
| TASK_STATE_FAILED | terminal | The agent, unable to do the work | Read the status message, fix the input, and start a new task. |
| TASK_STATE_CANCELED | terminal | The agent, after CancelTask | Start a new task in the same context. |
| TASK_STATE_REJECTED | terminal | The agent, refusing the task | Stop the loop, and follow the status message. |
Until a task ends, CancelTask asks the server to stop it, and success is not guaranteed. A terminal task never changes. A message on its taskId and SubscribeToTask fail with UnsupportedOperationError, and CancelTask fails with TaskNotCancelableError. GetTask still returns it while the server keeps it.
A stream must close when the task reaches a terminal state. At an interrupted state the sources disagree (conflict D3). The kit closes its stream at TASK_STATE_INPUT_REQUIRED and keeps it open through TASK_STATE_AUTH_REQUIRED, as the kit README lists. So after any close, call GetTask and act on the state it returns.
A2A protocol 1.0.1 · 3303592 · 2026-05-28 · Edition 2026.10