> ## 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.

# Task Lifecycle

> AdCP task lifecycle: status values (submitted, working, input-required, completed, failed), state transitions, response structure, and polling patterns for all operations.

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.

## Status Values

AdCP uses the same status values as the [A2A protocol's TaskState enum](https://a2a-protocol.org/dev/specification/#63-taskstate-enum):

| Status           | Meaning                    | Your Action                                       |
| ---------------- | -------------------------- | ------------------------------------------------- |
| `submitted`      | Task queued for execution  | Show "queued" indicator, wait for updates         |
| `working`        | Agent actively processing  | Show progress, poll frequently for updates        |
| `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:

```json theme={null}
{
  "status": "completed",           // Always present: what state we're in
  "message": "Found 5 products",   // Always present: human explanation
  "context_id": "ctx-123",         // Session continuity
  "context": {                     // Application-level context echoed back
    "ui": "buyer_dashboard"
  },
  "products": [...]                // Task-specific fields at top level
}
```

## Status Handling

### Basic Pattern

```javascript theme={null}
function handleAdcpResponse(response) {
  switch (response.status) {
    case 'completed':
      // Success - process the data (task fields are at top level)
      showSuccess(response.message);
      return processData(response);

    case 'input-required':
      // Need more info - prompt user
      const userInput = await promptUser(response.message);
      return sendFollowUp(response.context_id, userInput);

    case 'working':
      // In progress - show progress and wait
      showProgress(response.message);
      return pollForUpdates(response.context_id);

    case 'failed':
      // Error - show message and handle gracefully
      showError(response.message);
      return handleError(response.errors);

    case 'auth-required':
      // Authentication needed
      const credentials = await getAuth();
      return retryWithAuth(credentials);

    default:
      // Unexpected status
      console.warn('Unknown status:', response.status);
      showMessage(response.message);
  }
}
```

### Clarification Flow

When status is `input-required`, the message tells you what's needed:

```json theme={null}
{
  "status": "input-required",
  "message": "I need more information about your campaign. What's your budget and target audience?",
  "context_id": "ctx-123",
  "products": [],
  "suggestions": ["budget", "audience", "timing"]
}
```

**Client handling:**

```javascript theme={null}
if (response.status === 'input-required') {
  // Extract what's needed from the message
  const missingInfo = extractRequirements(response.message);

  // Prompt user with specific questions
  const answers = await promptForInfo(missingInfo);

  // Send follow-up with same context_id
  return sendMessage(response.context_id, answers);
}
```

### Approval Flow

Human approval is a special case of `input-required`:

```json theme={null}
{
  "status": "input-required",
  "message": "Media buy exceeds auto-approval limit ($100K). Please approve to proceed with campaign creation.",
  "context_id": "ctx-123",
  "approval_required": true,
  "amount": 150000,
  "reason": "exceeds_limit"
}
```

**Client handling:**

```javascript theme={null}
if (response.status === 'input-required' && response.approval_required) {
  // Show approval UI
  const approved = await showApprovalDialog(response.message, response);

  // Send approval decision
  const decision = approved ? "Approved" : "Rejected";
  return sendMessage(response.context_id, decision);
}
```

### Long-Running Operations

Async operations start with `working` or `submitted` and provide updates:

```json theme={null}
{
  "status": "working",
  "message": "Creating media buy. Validating inventory availability...",
  "context_id": "ctx-123",
  "task_id": "task-456",
  "progress": 25,
  "step": "inventory_validation"
}
```

**Protocol-specific polling:**

* **MCP**: Poll with context\_id for updates
* **A2A**: Subscribe to SSE stream for real-time updates

## Status Progression

Tasks progress through predictable states:

```
submitted → working → completed
    ↓          ↓         ↑
input-required → → → → →
    ↓
  failed
```

* **`submitted`**: Task queued for execution, provide webhook or poll
* **`working`**: Agent actively processing, poll frequently
* **`input-required`**: Need user input, continue conversation
* **`completed`**: Success, process results
* **`failed`**: Error, handle appropriately

## Polling Patterns

### Status-Based Polling Intervals

Different statuses require different polling frequencies:

```javascript theme={null}
const POLLING_INTERVALS = {
  working: 5000,      // 5 seconds - should complete within 120s
  submitted: 60000,   // 1 minute - long-running operations
  'input-required': null  // Don't poll - wait for user input
};

async function pollForUpdates(taskId, currentStatus) {
  const interval = POLLING_INTERVALS[currentStatus];
  if (!interval) return;

  await sleep(interval);

  const response = await adcp.call('tasks/get', {
    task_id: taskId,
    include_result: true
  });

  if (['completed', 'failed', 'canceled'].includes(response.status)) {
    return response;
  }

  return pollForUpdates(taskId, response.status);
}
```

### Timeout Handling

Set reasonable timeouts based on operation type:

```javascript theme={null}
const TIMEOUTS = {
  sync: 30_000,        // 30 seconds for immediate operations
  interactive: 300_000, // 5 minutes for human input
  working: 120_000,    // 2 minutes for working tasks
  submitted: 86_400_000 // 24 hours for submitted tasks
};

function setTimeoutForStatus(status) {
  switch (status) {
    case 'working': return TIMEOUTS.working;
    case 'submitted': return TIMEOUTS.submitted;
    case 'input-required': return TIMEOUTS.interactive;
    default: return TIMEOUTS.sync;
  }
}
```

## Task Reconciliation

Use `tasks/list` to recover from lost state:

```javascript theme={null}
// Find all pending operations
const pending = await session.call('tasks/list', {
  filters: {
    statuses: ["submitted", "working", "input-required"]
  }
});

// Reconcile with local state
const missingTasks = pending.tasks.filter(task =>
  !localState.hasTask(task.task_id)
);

// Resume tracking missing tasks
for (const task of missingTasks) {
  startPolling(task.task_id);
}
```

## 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](/dist/docs/3.0.0-rc.2/building/implementation/async-operations) for handling different operation types
* **Webhooks**: See [Webhooks](/dist/docs/3.0.0-rc.2/building/implementation/webhooks) for push notification patterns
* **Error Handling**: See [Error Handling](/dist/docs/3.0.0-rc.2/building/implementation/error-handling) for error categories and recovery
