Skip to main content
Every AdCP response includes a status field that tells you exactly what state the operation is in and what action you should take next. This is the foundation for handling any AdCP operation. :::note Application-layer task state The status values and lifecycle described here are transport-independent AdCP application state. MCP and A2A task mechanisms may wrap, stream, or deliver an AdCP response, but they do not replace AdCP’s task_id, webhook payloads, or polling/reconciliation surfaces. For submitted operations, observe the AdCP task with push notifications or the AdCP polling surface. In 3.x, that polling surface is legacy tasks/get, with optional get_task_status when the seller advertises the alias. Transport-native MCP/A2A tasks/* methods use their own wire shapes and are separate from AdCP task polling. :::

Status Values

AdCP uses the same status values as the A2A protocol’s TaskState enum:
StatusMeaningYour Action
submittedTask queued, blocked on external dependencyConfigure webhook, show “queued” indicator
workingAgent actively processing (>30s)Wait for result — out-of-band progress signal, not a polling trigger
input-requiredNeeds information from youRead message field, prompt user, send follow-up
completedSuccessfully finishedProcess data, show success message
canceledUser/system canceled taskShow cancellation notice, clean up
failedError occurredShow error from message, handle gracefully
rejectedAgent rejected the requestShow rejection reason, don’t retry
auth-requiredAuthentication neededPrompt for auth, retry with credentials
unknownIndeterminate stateLog for debugging, may need manual intervention

Response Structure

Every AdCP response uses a flat structure where task-specific fields are at the top level:
:::warning Single status field required Agents MUST NOT emit the legacy task_status or response_status fields alongside status. The status field is the single authoritative task state. Agents emitting either alongside status are non-conformant. :::

Status Handling

Basic Pattern

Clarification Flow

When status is input-required, the message tells you what’s needed:
Client handling:

Approval Flow

Human approval at the task layer is modelled as input-required (when the buyer must respond, e.g. confirm a budget) or submitted (when the seller is waiting on an internal human, e.g. IO signing). These implement the Embedded Human Judgment principle that judgment cannot be delegated to software — when an action exceeds autonomous authority, the system halts for human review rather than proceeding.
pending_approval is an Account status, not a task status and not a MediaBuy status. It indicates the seller is reviewing an account (credit, contracts) before it can be used. Don’t reuse the name for task-level approval.
Client handling:

Operations Over 30 Seconds

Operations that take longer than 30 seconds return either working or submitted. These statuses mean different things:
  • working: The server is actively processing and will deliver the result when ready. No polling needed — the server sends progress out-of-band and the result arrives on the open connection.
  • submitted: The operation is blocked on an external dependency (human approval, publisher review). Configure a webhook or poll.
Handling for submitted operations:
  • All transports: Use push notifications (recommended) or poll the AdCP task with get_task_status / legacy tasks/get.
  • MCP/A2A transport tasks: Treat native task state as transport state. A native task can finish once it has delivered an AdCP payload that still says status: 'submitted'.

Status Progression

Tasks progress through predictable states:
  • submitted: Task queued, blocked on external dependency — configure webhook or poll
  • working: Agent actively processing (>30s) — wait for result, no polling needed
  • input-required: Need user input, continue conversation
  • completed: Success, process results
  • failed: Error, handle appropriately

Polling and Timeouts

Polling is for submitted only

Don’t poll for working — the server delivers the result on the open connection. Polling is a backup for submitted operations (webhooks are preferred). Send include_result: true to receive the terminal task payload on the polled response once the task reaches status: completed. The result object on the response carries the same shape the original task would have returned synchronously — for example, polling a create_media_buy task returns result: { media_buy_id, packages, status }. For failed tasks, read the existing error field instead. Webhooks remain the supported delivery mechanism (see Push Notifications); include_result is the typed polling alternative for buyers that prefer pull over push.

Timeout Configuration

Task Reconciliation

Use list_tasks (or legacy tasks/list in 3.x) to recover from lost state:

Best Practices

  1. Always check status first - Don’t assume success
  2. Handle all statuses - Include a default case for unknown states
  3. Preserve context_id - Required for conversation continuity
  4. Use task_id for tracking - Especially for long-running operations
  5. Implement timeouts - Don’t wait forever
  6. Log status transitions - Helps with debugging and auditing

Next Steps

  • Async Operations: See Async Operations for handling different operation types
  • Webhooks: See Webhooks for push notification patterns
  • Error Handling: See Error Handling for error categories and recovery