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:| Status | Meaning | Your Action |
|---|---|---|
submitted | Task queued, blocked on external dependency | Configure webhook, show “queued” indicator |
working | Agent actively processing (>30s) | Wait for result — out-of-band progress signal, not a polling trigger |
input-required | Needs information from you | Read message field, prompt user, send follow-up |
completed | Successfully finished | Process data, show success message |
canceled | User/system canceled task | Show cancellation notice, clean up |
failed | Error occurred | Show error from message, handle gracefully |
rejected | Agent rejected the request | Show rejection reason, don’t retry |
auth-required | Authentication needed | Prompt for auth, retry with credentials |
unknown | Indeterminate state | Log for debugging, may need manual intervention |
Response Structure
Every AdCP response uses a flat structure where task-specific fields are at the top level: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 isinput-required, the message tells you what’s needed:
Approval Flow
Human approval at the task layer is modelled asinput-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.
Operations Over 30 Seconds
Operations that take longer than 30 seconds return eitherworking 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.
submitted operations:
- All transports: Use push notifications (recommended) or poll the AdCP task with
get_task_status/ legacytasks/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 pollworking: Agent actively processing (>30s) — wait for result, no polling neededinput-required: Need user input, continue conversationcompleted: Success, process resultsfailed: 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
Uselist_tasks (or legacy tasks/list in 3.x) to recover from lost state:
Best Practices
- Always check status first - Don’t assume success
- Handle all statuses - Include a default case for unknown states
- Preserve context_id - Required for conversation continuity
- Use task_id for tracking - Especially for long-running operations
- Implement timeouts - Don’t wait forever
- 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