The 30-second rule
Any AdCP task can return one of these statuses. The server chooses based on what it knows about the work involved:| Expected duration | Status | What the caller does |
|---|---|---|
| Under 30 seconds | completed / failed | Result is inline — done |
| Over 30 seconds, server actively processing | working | Out-of-band progress signal. Connection stays open, result arrives when ready. Caller just waits |
| Blocked on external dependency | submitted | Truly async — poll by task_id; push_notification_config can also deliver notifications when configured. Result may take hours or days |
| Blocked on human input | input-required | Caller provides the requested input to continue |
working is not async. It’s a progress signal the server sends out-of-band (via MCP status notifications or SSE) while it continues processing. The caller holds the connection and receives the result when it’s ready — no polling, no webhooks. Think of it as “this is taking a moment, but I’m on it.”
submitted is async. The operation is blocked on something outside the server’s control — publisher approval, human review, third-party processing. The caller can always poll the AdCP task status surface with task_id. A configured webhook is an additional notification channel for background workflows, not a replacement for polling.
:::tip Webhooks for submitted operations
Webhooks are recommended for background submitted operations — they work with any transport (MCP, A2A, REST) and handle operations that outlive a single session. For MCP/REST, the webhook channel is requested with push_notification_config on the task request. For A2A, it remains transport configuration at configuration.pushNotificationConfig, not a snake_case skill parameter. When a request includes a webhook channel and the server accepts the task by returning submitted, the server MUST deliver at least the terminal completion or failure notification to that channel. Intermediate progress notifications are optional unless another operation-specific contract requires them. If the server cannot honor the requested webhook channel, it MUST reject the request with a structured error instead of silently downgrading delivery. See Push Notifications.
Polling via the AdCP task polling surface is always valid for submitted tasks. In 3.x, that surface is legacy tasks/get, with optional get_task_status when the seller advertises the alias. See the polling pattern below.
Transport-native tasks are not the AdCP lifecycle. MCP Tasks or A2A task updates may carry or stream an AdCP response, but the durable task state is the AdCP payload: task_id, status, webhook payloads, and AdCP polling/reconciliation. See MCP Guide.
:::
Operation examples
Synchronous (instant)
| Operation | Description |
|---|---|
get_adcp_capabilities | Agent capability discovery |
list_creative_formats | Format catalog |
build_creative (library retrieval) | Resolving an existing creative_id |
May need human input
| Operation | Description |
|---|---|
get_products | When brief is vague or needs clarification |
create_media_buy | When approval is required |
build_creative (generation) | When creative direction or asset selection is needed |
May go async (submitted)
| Operation | Description |
|---|---|
create_media_buy | Publisher approval workflows |
update_media_buy | Manual seller review for budget, targeting, or creative changes |
get_products (brief / refine) | Bespoke curation that depends on upstream inventory queries or HITL review |
get_signals (brief) | Semantic signal discovery that depends on slow provider queries or review |
sync_creatives | Asset review and transcoding pipelines |
build_creative (with review) | Human creative review before finalizing |
sync_catalogs | Large feeds or feeds requiring content policy review |
activate_signal | Platform deployment pipelines |
get_products buying_mode: "wholesale" and get_signals discovery_mode: "wholesale" stay synchronous repair/reconciliation reads and report partial completion with incomplete[], not submitted.
Timeout Configuration
Set reasonable timeouts based on status:working uses a connection timeout (how long to hold open), not a poll interval. The server sends progress out-of-band and delivers the result on the same connection. submitted uses a polling or webhook delivery window; a 30-second poll interval is a reasonable default even when webhooks are configured as the primary notification path.
Human-in-the-Loop Workflows
Design Principles
- Optional by default - Approvals are configured per implementation
- Clear messaging - Users understand what they’re approving
- Timeout gracefully - Don’t block forever on human input
- Audit trail - Track who approved what when
Approval Patterns
Common Approval Triggers
- Budget thresholds: Campaigns over $100K
- New advertisers: First-time buyers
- Policy-sensitive content: Certain industries or topics
- Manual inventory: Premium placements requiring publisher approval
Progress Tracking
Progress Updates
Long-running operations may provide progress information:Displaying Progress
Protocol-Agnostic Patterns
These patterns work with both MCP and A2A.Product Discovery with Clarification
Campaign Creation with Approval
Polling for submitted Operations
Polling is always valid for submitted operations. A webhook may also deliver completion when configured, but callers can still reconcile through the task polling surface. Don’t poll for working — the server delivers the result on the open connection.
Asynchronous-First Design
Store State Persistently
Don’t rely on in-memory state for async operations:Handle Restarts Gracefully
Resume tracking after orchestrator restarts:Best Practices
- Design async first - Assume any operation could take time
- Persist state - Don’t rely on in-memory tracking
- Handle restarts - Resume tracking on startup
- Implement timeouts - Don’t wait forever
- Show progress - Keep users informed
- Support cancellation - Let users cancel long operations
- Audit trail - Log all status transitions
Next Steps
- Webhooks: See Webhooks for push notifications instead of polling
- Task Lifecycle: See Task Lifecycle for status handling details
- Orchestrator Design: See Orchestrator Design for production patterns