> ## Documentation Index
> Fetch the complete documentation index at: https://adcp-docs-ja.pier1.co.jp/llms.txt
> Use this file to discover all available pages before exploring further.

# タスクライフサイクル

> AdCP タスクライフサイクル: ステータス値（submitted、working、input-required、completed、failed）、状態遷移、レスポンス構造、すべてのオペレーションのポーリングパターン。

すべての AdCP レスポンスには `status` フィールドが含まれ、現在の状態と次に取るべき行動を示します。これはすべての AdCP 処理の基盤です。

## ステータス値

AdCP は [A2A プロトコルの 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   |

## レスポンス構造

AdCP レスポンスはタスク固有フィールドがトップレベルにある **フラット構造** です:

```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
}
```

## ステータス処理

### 基本パターン

```javascript theme={null}
function handleAdcpResponse(response) {
  switch (response.status) {
    case 'completed':
      // 成功 - データ処理（タスクフィールドはトップレベル）
      showSuccess(response.message);
      return processData(response);

    case 'input-required':
      // 追加情報が必要 - ユーザーに確認
      const userInput = await promptUser(response.message);
      return sendFollowUp(response.context_id, userInput);

    case 'working':
      // 進行中 - 進捗表示して待機
      showProgress(response.message);
      return pollForUpdates(response.context_id);

    case 'failed':
      // エラー - メッセージを表示し丁寧に処理
      showError(response.message);
      return handleError(response.errors);

    case 'auth-required':
      // 認証が必要
      const credentials = await getAuth();
      return retryWithAuth(credentials);

    default:
      // 想定外のステータス
      console.warn('Unknown status:', response.status);
      showMessage(response.message);
  }
}
```

### 確認フロー

ステータスが `input-required` のとき、必要な情報が message で示されます:

```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"]
}
```

**クライアントサイドの処理:**

```javascript theme={null}
if (response.status === 'input-required') {
  // message から必要項目を抽出
  const missingInfo = extractRequirements(response.message);

  // 必要項目に応じて質問
  const answers = await promptForInfo(missingInfo);

  // 同じ context_id で追送
  return sendMessage(response.context_id, answers);
}
```

### 承認フロー

人による承認は `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"
}
```

**クライアントサイドの処理:**

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

  // 承認結果を送信
  const decision = approved ? "Approved" : "Rejected";
  return sendMessage(response.context_id, decision);
}
```

### 長時間オペレーション

非同期オペレーションは `working` または `submitted` で開始し、進捗を返します:

```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"
}
```

**プロトコル別のポーリング:**

* **MCP**: context\_id を使ってポーリング
* **A2A**: SSE ストリームでリアルタイム更新を購読

## ステータスの流れ

タスクは予測可能な状態を経由して進行する:

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

* **`submitted`**: 実行待ち。Webhook を設定するかポーリング
* **`working`**: 処理中。高頻度でポーリング
* **`input-required`**: ユーザー入力が必要。会話を継続
* **`completed`**: 成功。結果を処理
* **`failed`**: エラー。適切に処理

## ポーリングパターン

### ステータス別ポーリング間隔

ステータスによってポーリング頻度を変えます:

```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);
}
```

### タイムアウト処理

オペレーション種別に応じて妥当なタイムアウトを設定します:

```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;
  }
}
```

## タスク再同期

`tasks/list` で失われた状態を復元します:

```javascript theme={null}
// 保留中のオペレーションを取得
const pending = await session.call('tasks/list', {
  filters: {
    statuses: ["submitted", "working", "input-required"]
  }
});

// ローカル状態と突き合わせ
const missingTasks = pending.tasks.filter(task =>
  !localState.hasTask(task.task_id)
);

// 未追跡タスクの監視を再開
for (const task of missingTasks) {
  startPolling(task.task_id);
}
```

## ベストプラクティス

1. **まず status を確認** - 成功前提にしません
2. **すべてのステータスを処理** - 未知の状態も default でカバー
3. **context\_id を保持** - 会話継続に必須
4. **task\_id で追跡** - 特に長時間オペレーションで重要
5. **タイムアウトを実装** - 無限に待たない
6. **ステータス遷移をログ** - デバッグと監査に有用

## 次のステップ

* **Async Operations**: 異なるオペレーション種別の扱いは [Async Operations](/docs/building/by-layer/L3/async-operations)
* **Webhooks**: プッシュ通知パターンは [Webhooks](/docs/building/by-layer/L3/webhooks)
* **Error Handling**: エラー分類と復旧は [Error Handling](/docs/building/by-layer/L3/error-handling)
