Documentation Index
Fetch the complete documentation index at: https://docs.adcontextprotocol.org/llms.txt
Use this file to discover all available pages before exploring further.
AdCP provides unified task management for tracking all async operations across media-buy and signals domains. This enables state reconciliation, progress monitoring, and webhook integration for long-running operations.
Overview
AdCP operations may complete immediately (~1 second), take processing time (~60 seconds), or require extended execution (minutes to days). Task management provides visibility and control over these async operations regardless of their domain or complexity.
Core Tasks:
tasks/list - List and filter async operations for state reconciliation
tasks/get - Poll specific tasks for status, progress, and results
Key Features:
- Cross-Domain Coverage: Works for both media-buy and signals operations
- State Reconciliation: Prevents lost or orphaned operations
- Webhook Integration: Optional push notifications for completion
- Progress Tracking: Real-time status updates for active operations
- Error Recovery: Detailed error information and retry guidance
Task Status Lifecycle
All AdCP operations follow a consistent status progression:
Status Definitions
| Status | Description | Duration | Client Action |
|---|
submitted | Queued for long-running execution | Hours to days | Poll periodically or wait for webhook |
working | Actively processing | < 120 seconds | Poll frequently (5-10s intervals) |
input-required | Paused, waiting for user input | Until input provided | Read message, provide clarification |
completed | Successfully finished | Final | Process results, stop polling |
failed | Failed due to error | Final | Handle error, potentially retry |
canceled | Canceled by user | Final | Clean up, stop polling |
rejected | Rejected before starting | Final | Review rejection reason |
auth-required | Needs authentication | Until auth provided | Provide credentials |
unknown | Indeterminate state | Variable | Check again or escalate |
Status Transitions
Immediate Completion: Simple operations may skip to completed without intermediate states.
Working vs Submitted: working indicates active processing with completion expected within 120 seconds, while submitted indicates queued execution that may take much longer.
tasks/list
List and filter async tasks across your account to enable state reconciliation and operation tracking.
Response Time: ~1 second (simple database lookup)
Request Schema: https://adcontextprotocol.org/schemas/v2/core/tasks-list-request.json
Response Schema: https://adcontextprotocol.org/schemas/v2/core/tasks-list-response.json
Request Parameters
| Parameter | Type | Required | Description |
|---|
filters | object | No | Filter criteria for querying tasks |
sort | object | No | Sorting parameters |
pagination | object | No | Pagination controls |
include_history | boolean | No | Include full conversation history for each task (default: false) |
Filtering Options
Status and Type Filtering
{
"filters": {
"status": "submitted",
"statuses": ["submitted", "working", "input-required"],
"task_type": "create_media_buy",
"task_types": ["create_media_buy", "activate_signal"]
}
}
Domain-Specific Filtering
{
"filters": {
"domain": "media-buy", // Filter by domain
"domains": ["media-buy", "signals"],
"task_types": [
"create_media_buy",
"update_media_buy",
"sync_creatives",
"activate_signal",
"get_signals"
]
}
}
Date and Context Filtering
{
"filters": {
"created_after": "2025-01-01T00:00:00Z",
"created_before": "2025-01-31T23:59:59Z",
"updated_after": "2025-01-20T00:00:00Z",
"context_contains": "nike_q1_2025",
"task_ids": ["task_456", "task_789"],
"has_webhook": true
}
}
Response Structure
{
"message": "Found 27 tasks matching your criteria. 15 are pending and may need attention.",
"context_id": "ctx-123",
"query_summary": {
"total_matching": 27,
"returned": 20,
"domain_breakdown": {
"media-buy": 18,
"signals": 9
},
"status_breakdown": {
"submitted": 12,
"working": 3,
"completed": 8,
"failed": 4
}
},
"tasks": [
{
"task_id": "task_456",
"task_type": "create_media_buy",
"domain": "media-buy",
"status": "submitted",
"created_at": "2025-01-22T10:00:00Z",
"updated_at": "2025-01-22T10:00:00Z",
"message": "Media buy requires manual approval for $150K campaign",
"has_webhook": true
},
{
"task_id": "task_789",
"task_type": "activate_signal",
"domain": "signals",
"status": "completed",
"created_at": "2025-01-22T09:45:00Z",
"completed_at": "2025-01-22T09:46:00Z",
"message": "Signal sent successfully to 3 endpoints",
"has_webhook": false
}
],
"pagination": {
"limit": 20,
"offset": 0,
"has_more": true,
"next_offset": 20
}
}
Common Use Cases
State Reconciliation
Find all pending operations across domains:
{
"filters": {
"statuses": ["submitted", "working", "input-required"]
},
"sort": {
"field": "created_at",
"direction": "asc"
}
}
Domain-Specific Monitoring
Track only media-buy operations:
{
"filters": {
"domain": "media-buy",
"statuses": ["submitted", "working"]
}
}
Operations Needing Attention
{
"filters": {
"statuses": ["input-required", "failed"],
"updated_before": "2025-01-20T00:00:00Z" // Old stuck tasks
}
}
Lost Connection Recovery
Recover from lost task submissions by examining conversation history:
{
"filters": {
"created_after": "2025-01-22T10:00:00Z"
},
"include_history": true
}
Then check history[0].data to see original requests and identify your lost task:
tasks.tasks.forEach(task => {
const originalRequest = task.history?.[0]?.data;
if (originalRequest?.buyer_ref === "nike_q1_2025") {
console.log(`Found my lost task: ${task.task_id}`);
}
});
tasks/get
Poll a specific task by ID to check status, progress, and retrieve results when complete.
Response Time: ~1 second (simple database lookup)
Request Schema: https://adcontextprotocol.org/schemas/v2/core/tasks-get-request.json
Response Schema: https://adcontextprotocol.org/schemas/v2/core/tasks-get-response.json
Request Parameters
| Parameter | Type | Required | Description |
|---|
task_id | string | Yes | Unique identifier of the task to retrieve |
include_history | boolean | No | Include full conversation history for this task (default: false) |
Response Structure
{
"message": "Media buy creation is 75% complete. Currently validating inventory availability.",
"context_id": "ctx-123",
"task_id": "task_456",
"task_type": "create_media_buy",
"domain": "media-buy",
"status": "working",
"created_at": "2025-01-22T10:00:00Z",
"updated_at": "2025-01-22T10:15:00Z",
}
{
"progress": {
"percentage": 75,
"current_step": "validating_inventory_availability",
"total_steps": 4,
"step_number": 3
}
}
Task with Conversation History
{
"status": "completed",
"completed_at": "2025-01-22T10:25:00Z",
"history": [
{
"timestamp": "2025-01-22T10:00:00Z",
"type": "request",
"data": {
"buyer_ref": "nike_q1_2025",
"brief": "Premium CTV inventory for Nike campaign"
}
},
{
"timestamp": "2025-01-22T10:25:00Z",
"type": "response",
"data": {
"media_buy_id": "mb_987654321",
"packages": [{ "package_id": "pkg_abc123" }]
}
}
]
}
Failed Task Errors
{
"status": "failed",
"completed_at": "2025-01-22T10:20:00Z",
"error": {
"code": "insufficient_inventory",
"message": "Requested targeting yielded 0 available impressions",
"details": {
"domain": "media-buy",
"operation": "create_media_buy",
"specific_context": {}
}
}
}
Polling Patterns
Basic Polling Loop
async function pollTask(taskId) {
while (true) {
const response = await session.call('tasks/get', {
task_id: taskId
});
switch (response.status) {
case 'completed':
return response; // Get full result from history if needed
case 'failed':
throw new Error(`Task failed: ${response.error.message}`);
case 'input-required':
const input = await promptUser(response.message);
// Continue conversation with same context_id
return await handleUserInput(response.context_id, input);
case 'working':
console.log(`Progress: ${response.progress?.percentage || 0}%`);
await sleep(5000); // Poll working tasks frequently
break;
case 'submitted':
console.log(`Task queued for long-running execution`);
await sleep(60000); // Poll submitted tasks less frequently
break;
}
}
}
Smart Polling with Domain Awareness
async function smartPollTask(taskId) {
let pollInterval = 2000;
const maxInterval = 60000;
while (true) {
const response = await session.call('tasks/get', { task_id: taskId });
if (['completed', 'failed', 'canceled'].includes(response.status)) {
return response;
}
// Adjust polling based on domain and status
if (response.status === 'working') {
pollInterval = response.domain === 'signals' ? 2000 : 5000;
} else if (response.status === 'submitted') {
pollInterval = response.domain === 'media-buy' ? 60000 : 30000;
}
await sleep(Math.min(pollInterval, maxInterval));
}
}
Protocol Integration
Task management works consistently across all AdCP protocols.
MCP Integration
// List tasks
const taskList = await session.call('tasks/list', {
filters: { statuses: ['submitted', 'working'] }
});
// Poll specific task
const taskStatus = await session.call('tasks/get', {
task_id: 'task_456'
});
A2A Integration
Natural Language
await a2a.send({
message: {
parts: [{
kind: "text",
text: "Show me all pending media buy tasks from the last week"
}]
}
});
Explicit Skill Invocation
await a2a.send({
message: {
parts: [{
kind: "data",
data: {
skill: "tasks/list",
parameters: {
filters: {
domain: "media-buy",
statuses: ["submitted", "working"],
created_after: "2025-01-15T00:00:00Z"
}
}
}
}]
}
});
Webhook Integration
For async operations, you can configure webhooks instead of polling. See Protocol Comparison - Push Notifications for protocol differences and Core Concepts - Webhook Reliability for implementation patterns.
Webhook trigger conditions:
Webhooks fire when the task type supports async, pushNotificationConfig is provided, and the task actually runs asynchronously (initial response is working or submitted).
Error Handling
Common Error Scenarios
- Task Not Found: Invalid task ID or access permissions
- Invalid Filters: Malformed filter criteria in tasks/list
- Pagination Errors: Invalid offset or limit values
- Permission Denied: Task exists but user lacks access
{
"status": "failed",
"message": "Task not found or access denied",
"context_id": "ctx-123",
"errors": [{
"code": "task_not_found",
"message": "No task found with ID 'task_456' for this account",
"field": "task_id"
}]
}
Best Practices
State Reconciliation
- Run
tasks/list with pending filters during application startup
- Check for old tasks that may be stuck in
submitted status
- Use domain filtering to focus on relevant operation types
- Include webhook status to understand notification expectations
- Use pagination for accounts with many operations
- Filter by date ranges to limit results to relevant periods
- Use
include_history: false by default to keep responses lightweight
- Implement exponential backoff for polling loops
Monitoring and Alerting
- Monitor
input-required tasks for user attention needs
- Alert on tasks stuck in
submitted status beyond expected duration
- Track
failed tasks for error reporting and system health
- Use domain breakdown to understand operation distribution
Integration Patterns
- Store task IDs with your application entities for later reference
- Use webhooks as primary notification mechanism, polling as backup
- Implement proper error handling for both webhook and polling failures
- Consider domain-specific polling intervals and timeout values