Task Status
When a user gives an agent something to do, the runtime creates a task — a stateful, persistent conversation whose lifecycle is defined in Task Context.
The Task Status is the task's externally consumable contract: what a compliant runtime reports about a task, read alongside the conversation's messages. It is deliberately narrow — an identity, a coarse status, and the outstanding notifications — and it is the polling surface: everything a consumer must be told about a task is raised through this object. A runtime is free to track whatever additional task information its implementation needs, but it MUST expose the contract defined here to be compliant with the Common Agent Specification.
Status Object
id: str # cryptographically random, unique within the deployment
agent: str # the agent processing this task
responsible_user: str
created_at: str # UTC ISO 8601
status:
phase: idle | processing | terminal
terminal_reason: completed | errored | restricted | null
revision: str # opaque change cursor
notifications: list[TaskNotification]
idle_expires_at: str | null
idMUST be a cryptographically random identifier, unique within the deployment.agentMUST be the name of the agent processing this task.responsible_userMUST be the human user responsible for this task: the human who created it, or — for a task created by an agent — the human responsible for that agent's task. A task has exactly one responsible user.created_atMUST be the UTC ISO 8601 timestamp of the task's creation.status.phaseandstatus.terminal_reasonfollow the lifecycle defined in Task Context: anidletask awaits its next input, aprocessingtask is busy, andterminal_reasonMUST benullfor any non-terminal task. A terminal task MUST NOT be mutated further.status.revisionMUST be an opaque string that changes whenever the status object or the task's messages change. Consumers compare revisions only for inequality — the value carries no ordering or content semantics.status.notificationslists the task's outstanding notifications, ordered bysinceascending. It MUST be empty when nothing requires the responsible user.status.idle_expires_at— when the runtime enforces an inactivity lifespan, this MUST be the UTC ISO 8601 time at which the runtime will complete the task if no further activity occurs, and MUST benullat terminal. When no inactivity lifespan applies it MUST benull.
Task Notifications
A Task Notification is an outstanding call to action for the task's responsible user: something only they can do before the task can proceed. Notifications are state, not an event log — a notification appears when raised, is carried on every poll while it is outstanding, and is removed when resolved.
Each notification serializes as:
kind: user_auth_required | review_required
since: str # UTC ISO 8601 — when the notification was raised
provider: str # user_auth_required only — the provider being connected
-
user_auth_required— the task is paused until the responsible user authorises a provider it acts through, as themselves (for example, a delegated sign-in). The notification MUST name theproviderbeing connected, and there MUST be one per authorisation, not one per blocked operation: a task may have several operations waiting on the same one, and they are a single call to action that granting it resolves together. How the authorisation is completed is implementation-defined.It is named for who must act. A host may equally be unable to proceed because the host is missing configuration — no credential for a provider, an application nobody has installed — and that is NOT this notification and not a notification at all: the responsible user cannot supply it, so it is visible only as
phase: processing(see 3). -
review_required— areview(user)middleware step awaits a decision and the reviewing user is the task's responsible user. A review addressed to anyone else is NOT a notification: routing it to its reviewer is the runtime's responsibility, and externally it is visible only asphase: processing. How the decision is made is implementation-defined. -
Nothing else is a notification. Any other reason a task is not progressing — internal waits, host-side configuration, capacity — is visible only as
phase: processing: the task is busy, and how is the host's business. -
Terminal outcomes and new output are deliberately not notifications:
terminal_reasonalready reports the former, and arevisionchange with the messages list already conveys the latter.
Polling
- A consumer follows a task by polling its status object. When
revisionchanges, refetch the messages and re-render the notifications; nothing else needs to be watched. - A runtime MAY additionally push change notifications to consumers. When it does, they carry this same status object — push delivery is an optimisation over polling, never a different contract.
Interaction
- Input. The responsible user continues the conversation by sending an input: a unified object containing a
messagekey (the conversational content aslist[ContentPart]) and optional parameter keys matching the agent'sparametersschema. Input is subject to the agent's input guardrails and middleware: it MUST clear them before it reaches the agent, and may be blocked or locked by them. Input MAY be sent at any time before terminal: a runtime MUST accept input received while the task isprocessing, queueing it without interrupting the turn in flight — queued input is processed in a subsequent turn. - Input is the only mutation this contract defines, and it belongs exclusively to the task's responsible user. Further lifecycle control — interrupting a turn in flight, completing the task — is host-side, governed by the implementation's authorisation model; consumers observe the effects through the status object (
phase,terminal_reason).