Tasks, messages, and artifacts

Lesson 3 of 5 in A2A and Agent Interop — Honestly Sized.

The Agent Card gets you an introduction. The Task is the actual contract.

A task is a stateful unit of work with a server-generated id, optionally grouped with related tasks by a contextId. That one design choice — the server owns the id and the state — is what separates A2A from a tool call. A tool call is a request whose result you await. A task is a record you can come back to: query it later, cancel it, subscribe to it, resume it after your own process restarts.

The core operations follow from that: SendMessage, SendStreamingMessage, GetTask, ListTasks, CancelTask, SubscribeToTask, plus CRUD for push-notification configuration.

A2A task lifecycle (spec 1.0 states)

  1. SUBMITTED

    The client sent work; the server minted a task id. Nothing has necessarily started yet.

  2. WORKING

    The remote agent is executing. Progress reaches you by polling, streaming, or webhook — your choice, constrained by its advertised capabilities.

  3. INPUT_REQUIRED

    Interrupted, not failed: the agent needs a clarification or a decision. Your client must be able to answer later — possibly after a restart.

  4. AUTH_REQUIRED

    The task needs a credential mid-flight. The spec defines an in-task authorization mechanism for exactly this.

  5. COMPLETED

    Terminal. Outputs are attached to the task as artifacts.

  6. FAILED

    Terminal. The agent tried and could not finish — distinct from refusing the work.

  7. CANCELED

    Terminal, via CancelTask. Long-running work needs a stop button, and this is it.

  8. REJECTED

    Terminal. The agent declined the task outright — out of scope, over policy, not permitted.

Inside a task, two different things travel — and conflating them is the most common A2A modelling mistake.

A Message is one communication turn, with a role of ROLE_USER or ROLE_AGENT, built from Parts that may be text, files, or structured data. Messages are for initiating work, asking clarifying questions, and status chatter. An Artifact is an output, attached to the task. The spec is explicit that messages “SHOULD NOT be used to deliver task outputs.”

The reason is operational, not aesthetic. Artifacts are addressable results attached to a durable record: fetchable later, referenceable by id, gradeable by your evals. A deliverable smuggled inside conversational text is only recoverable by parsing a transcript — which is precisely the brittleness structured outputs exist to eliminate.

Three things a task carries (A2A Specification 1.0)
ElementWhat it isUse it forDo not use it for

Message

One turn, role ROLE_USER or ROLE_AGENT, composed of Parts (text, file, data).

Kicking off the task, clarifying questions, answering an INPUT_REQUIRED interruption, human-readable status.

Shipping the deliverable — the spec says messages SHOULD NOT deliver task outputs.

Artifact

An output attached to the Task.

The actual results: the reviewed contract, the generated report, the reconciliation file.

Chatty progress narration; artifacts are results, not commentary.

Task state

The lifecycle enum — terminal, interrupted, or in progress.

Deciding what your orchestrator does next: wait, answer, retry, escalate, give up.

Inferring semantics from prose. Branch on the state, never on the wording of a status message.

Polling

Call GetTask (and ListTasks) on an interval. Always available, no server-side capability required, survives your process restarting. The cost is latency and wasted requests — but for a task that takes forty minutes, a thirty-second poll is not the bottleneck. Start here; it is the fallback everything else degrades to.

Streaming

SendStreamingMessage and SubscribeToTask, gated on capabilities.streaming. Best latency and the natural fit for interactive UIs. But a stream is a live connection: if your client dies mid-task, you need the polling path anyway to find out what happened. Treat streaming as an optimisation over a durable record, never as the record.

Push notifications

Webhooks, gated on capabilities.pushNotifications, configured through the push-notification config operations. The right choice for hour-long work where holding a connection is silly. It also drags in real webhook engineering: a reachable authenticated endpoint, replay and duplicate handling, and the assumption that any inbound payload is untrusted until you verify it.

Tool: Protocol Picker — Practise the vertical/horizontal call on your own integrations — tool, task, or neither — in the Protocol Picker.

Interactive checkpoint quiz (2 questions) — open this page in a browser to take it.