Message (for quick operations) or a Task (for longer-running work). Tasks have a defined lifecycle, can produce artifacts, and can be streamed in real time.
What is a task
A task represents work that an agent performs in response to a message. It has:- A unique prefixed UUIDv7 identifier (
task.0192f4c8-...) - A
contextIdlinking it to a context for conversation continuity - A
statuswith a current state and timestamp - A
historyarray of messages exchanged during the task - An
artifactsarray of outputs produced by the task metadataincluding token and credit accounting under$usage
The agent decides whether to respond with a
Task or a Message. Quick operations (short completions, classifications) often return a Message directly. Longer workflows return a Task that you monitor for completion.Task states
A task moves through the following states:TASK_STATE_REJECTED and TASK_STATE_AUTH_REQUIRED are only visible on the JSON-RPC binding. On the REST (HTTP+JSON) binding, both are mapped to TASK_STATE_FAILED with a descriptive status message.Terminal vs non-terminal states
Canceling a task in a terminal state returns
409 Conflict.
State transitions
A task transitions through states as follows:TASK_STATE_SUBMITTEDtoTASK_STATE_WORKING: The agent begins processing.TASK_STATE_SUBMITTEDtoTASK_STATE_REJECTED: The task was rejected before processing (insufficient credits or invalid configuration).TASK_STATE_SUBMITTEDtoTASK_STATE_AUTH_REQUIRED: An MCP connector requires authentication before the agent can proceed.TASK_STATE_WORKINGtoTASK_STATE_COMPLETED: The task finishes successfully.TASK_STATE_WORKINGtoTASK_STATE_FAILED: An error occurred during processing.TASK_STATE_WORKINGtoTASK_STATE_INPUT_REQUIRED: The agent paused and needs user input.TASK_STATE_WORKINGtoTASK_STATE_AUTH_REQUIRED: An MCP connector encountered an auth error during execution.TASK_STATE_AUTH_REQUIREDtoTASK_STATE_WORKING: Auth is resolved and the agent resumes.TASK_STATE_INPUT_REQUIREDtoTASK_STATE_WORKING: The user provides input and the agent resumes.- Any non-terminal state to
TASK_STATE_CANCELED: The client cancels the task viatasks/{id}:cancel.
A task in
TASK_STATE_INPUT_REQUIRED or TASK_STATE_AUTH_REQUIRED state is not terminated. Send a new message with the required input (for TASK_STATE_INPUT_REQUIRED) or resolve the connector authentication (for TASK_STATE_AUTH_REQUIRED) to resume processing. The SSE stream closes when either state is reached; you must send a new message or re-subscribe to continue receiving updates.Task history and messages
Thehistory array contains all messages exchanged during the task, oldest first. Each message has:
messageId: A prefixed UUIDv7 (e.g.msg.0192f4c8-...)role: EitherROLE_USER(sent by the client) orROLE_AGENT(sent by the agent)parts: An ordered list of content parts (text, file, or data)metadata: Free-form metadata, including Corti’s$timestampfor timing
configuration.historyLength on the message send request.
Artifacts
Artifacts are the tangible outputs a task produces. Each artifact has:artifactId: A prefixed UUIDv7 (e.g.art.0192f4c8-...)name: An optional human-readable nameparts: Content parts containing the artifact data
Inline citations
When the orchestrator answers using data it retrieved from connectors, the answer artifact’s text part carries citation metadata that links each claim to its source data part. The text partmetadata contains a citations array of entries, each with data_part_id (the GID of the cited part), offset (character offset into the joined artifact text), and locator (a JSON Pointer or line range).
Each cited data part is a sibling part in the same artifact, carrying its GID in metadata.dataPartId. Resolve a citation by joining data_part_id to the part whose metadata.dataPartId matches.
Inline citations are produced by the orchestrator only. Connector (expert) sub-answers do not embed citation markers; their outputs are data parts that the orchestrator then cites or passes through.
Streaming events
When you stream a message viamessage:stream or subscribe to an existing task via tasks/{id}:subscribe, the server sends Server-Sent Events (SSE). Each event carries an A2AStreamResponse with exactly one of the following fields:
Token-by-token streaming
As the model generates its answer, the answer text streams as a sequence ofartifactUpdate events (one text fragment per event) rather than as status updates. The first delta sets append to false (the artifact is being created); each subsequent delta sets append to true. A closing event with lastChunk: true consolidates the deltas into a single canonical text part (append: false = replace).
lastChunk closes one artifact, not the run. A run may emit several lastChunk: true artifacts, for example an intermediate-thinking narration followed by the final answer. The run ends on the closing statusUpdate with a terminal state (TASK_STATE_COMPLETED, TASK_STATE_FAILED, TASK_STATE_CANCELED, TASK_STATE_REJECTED), or an interrupted state (TASK_STATE_INPUT_REQUIRED, TASK_STATE_AUTH_REQUIRED) that also closes the stream.
On the v1.0 (A2A 1.0) surface, a
TASK_STATE_COMPLETED statusUpdate carries no answer message. The answer is the completion artifact whose lastChunk: true event preceded the terminal status. The statusUpdate carries usage and credit metadata in metadata.TASK_STATE_INPUT_REQUIRED or TASK_STATE_FAILED, the streamed narration is closed as an intermediate-thinking artifact (with artifact.metadata.type: "intermediate-thinking") before the terminal status. Do not render it as the final answer.
See Stream responses for the full delta event format, append/lastChunk semantics, and client best practices.
SSE event format
Each SSE frame follows the W3C SSE wire format:Example SSE event
For a streamed answer, the server emits oneartifactUpdate per token delta, then a closing lastChunk event with the consolidated text, then the terminal statusUpdate:
lastChunk: true event as shown in the streaming guide.
Resumption with Last-Event-ID
The intended resumption mechanism is to send theLast-Event-ID header with the most recent event ID you received. The server will replay events from that point forward once implemented.
This will work with both message:stream and tasks/{id}:subscribe. See Stream responses for implementation details.
Task metadata and usage
Each task carriesmetadata with Corti’s first-party keys prefixed with $. The $usage object provides token and credit accounting:
Next steps
- Learn how to send a message and handle task or message responses
- Learn how to stream responses via SSE
- Read about contexts to understand how tasks are grouped