The A2A primer
The minimum vocabulary you need to read the rest of these docs. This page is deliberately narrow: for anything beyond it, see the official A2A specification.
Message and Parts
A Message is what a caller sends and an agent replies with. Its content is one or more typed Parts, not a single blob:
TextPart— plain text.DataPart— a JSON object, for structured input or output.FilePart— a file, by URI or inline bytes.
A message can carry several parts of different kinds at once — the part itself carries its type, so there is no separate content-type field to keep in sync with it.
Task and TaskState
Sending a message to an agent creates (or continues) a Task — A2A's unit of work. A task moves through a TaskState, and the states split into two sets:
- Terminal — the task will not change again:
COMPLETED,FAILED,CANCELED,REJECTED. - Interrupt — the task has paused and will resume once the caller supplies something:
INPUT_REQUIRED,AUTH_REQUIRED.
flowchart LR
Submitted --> Working
Working --> Completed
Working --> Failed
Working --> Canceled
Working --> InputRequired["Input Required"]
Working --> AuthRequired["Auth Required"]
InputRequired -->|caller responds| Working
AuthRequired -->|caller responds| Working
Both sets stop a stream, but they are not the same thing: a stream that ends on INPUT_REQUIRED is over and unfinished — not failed, not abandoned. A stream that ends on neither set is a different case again: a transport failure wearing the shape of a completed run, not a real outcome.
Artifact
An Artifact is a task's typed, named output — what the agent produced, as distinct from status.message, which is what the agent has to say about reaching that state. Like a Message, an artifact's content is a list of Parts, so a structured result is a real DataPart, not JSON packed into a string. An artifact keeps a stable artifact_id and a revision, so a later update to the same output is recognizable as a new revision rather than a second, unrelated result.
Agent Card
An Agent Card is how an agent describes itself: its name, the skills it offers, which protocol bindings it speaks, and where it can be reached — a JSON document at the well-known path /.well-known/agent-card.json.
On NovaOS, an agent pod does not serve its own card. Pods are never internet-reachable, so the platform's execution gateway publishes /.well-known/agent-card.json on the agent's behalf; AgentBuilder never adds a route for it. If you're building an agent, AgentBuilder.to_agent_card() produces the card content for whoever does the publishing — don't expect to see it served by your own process.
The JSON-RPC methods
Every A2A operation is a JSON-RPC 2.0 call to the agent's endpoint:
SendMessage— send a message, get back aTask(or, in the case the spec allows, a bare message).SendStreamingMessage— the same, but stream status and artifact updates as they happen.GetTask— fetch one authoritative snapshot of a task.SubscribeToTask— reconnect to a running task's stream; the first frame is always its current snapshot.ListTasks— enumerate an agent's tasks, a page at a time.CancelTask— ask the agent to stop a task; cancellation is a request, so read the state it answers with.CreateTaskPushNotificationConfig,GetTaskPushNotificationConfig,ListTaskPushNotificationConfigs,DeleteTaskPushNotificationConfig— register or manage a webhook for a task's status changes, instead of holding a stream open or polling.
Client wraps every one of these as a same-named method, in snake_case.
NovaOS metadata rides in DataParts
A2A itself has no field for "which skill should run" or "this task is paused on a human" — those are NovaOS conventions layered on top of the protocol, not new wire fields. Which skill runs travels as message.metadata["skillId"]; platform signals like a human-in-the-loop pause travel inside an ordinary DataPart, tagged as NovaOS's own in that part's metadata. A caller that only reads the base A2A shapes still gets a valid, conformant response — reading the NovaOS-specific fields is what unlocks the platform behavior built on top of it.