Skip to main content
このドキュメントは、A2A プロトコルで送信される AdCP レスポンスの 標準構造 を定義します。

A2A ワイヤーフォーマット

以下の例は A2A 1.0 ワイヤーフォーマットを使用します。Part は kind 判別子を持たず(コンテンツタイプはどのフィールドが設定されているか — textdataurlraw — で暗黙的に決まる)、ロールは ROLE_USER / ROLE_AGENT、タスク状態は TASK_STATE_*(ProtoJSON 正準形)です。v0.3 との対比は A2A ガイドを参照してください。 AdCP のトップレベル統合 status フィールド(@adcp/sdk が返す)は、引き続き小文字の短縮形("completed""failed""working""input-required""submitted")を使用します。これは status.state 上の AdCP の抽象化であり、A2A ワイヤー値ではありません。 v0.3 サーバーの場合、同じ DataPart は { "kind": "data", "data": {...} } になり、状態は小文字になります。抽出クライアントは互換期間中に両方の形状を受け入れます。

必須構造

最終レスポンス(status: “completed”)

A2A 上の AdCP レスポンスは必ず以下を満たす必要があります:
  • タスクのペイロードを含む DataPart(非 null の data フィールドを持つ Part)を少なくとも 1 つ含めます
  • 複数アーティファクトではなく、1 つのアーティファクトに複数パートを入れる
  • DataPart が複数ある場合は最後のものを正とします
  • AdCP ペイロードをフレームワーク固有オブジェクトでラップしない({ response: {...} } など禁止)
Recommended pattern:
  • TextParttext フィールドを持つ Part): 人間向けサマリー — 推奨(任意)
  • DataPartdata フィールドを持つ Part): 構造化された AdCP レスポンスペイロード — 必須
  • FileParturl または raw フィールドを持つ Part): 任意のファイル参照(プレビュー、レポート)
複数アーティファクト: 本質的に異なる成果物(例: クリエイティブと別個のトラフィッキングレポート)がある場合のみ。AdCP では稀であり、基本は 1 アーティファクト内に複数パートを推奨。

中間レスポンス(working, submitted, input-required, auth-required)

中間ステータス更新は TaskStatusUpdateEvent として配信され、任意の進捗/チャレンジデータは(artifacts ではなく)status.message.parts[] に含まれます。アーティファクトはタスクライフサイクル中に蓄積され、タスクが終端状態に達すると最終成果物として読まれます。
SSE 経由またはプッシュ通知として配信される場合、このイベントは A2A 1.0 の StreamResponse oneof でラップされます: { "statusUpdate": { … } }。非ストリーミングレスポンス(例: tasks/get)は素のオブジェクトを配信します。クライアントは status.state を読む前にアンラップします — A2A レスポンス抽出を参照してください。 中間レスポンスの特徴:
  • TextPart はステータス表示のため推奨
  • DataPart は任意だが、提供する場合は AdCP スキーマに準拠
  • 中間ステータス用スキーマ(*-async-response-working.json*-async-response-input-required.json など)は策定中で変わる可能性あり
  • スキーマ進化を踏まえ、中間データの扱いを緩やかにする選択も可能
最終ステータスになった場合completedfailedcanceledrejected)、完全な AdCP タスクレスポンスが Task オブジェクトで配信され、DataPart は .artifacts[0].parts[] に入ります。

フレームワークのラッパー(禁止)

重要: DataPart の内容はフレームワーク固有オブジェクトでラップせず、AdCP レスポンスペイロードを直接含める必要があります。
理由:
  • スキーマ検証が破綻する(クライアントは products がルートにあると期待)
  • 不要なネストが増える
  • プロトコル非依存設計に反する(ラッパーがフレームワーク依存)
  • クライアントでのデータ抽出が複雑化
実装がラッパーを追加している場合、クライアントサイドで回避するのではなく、フレームワーク層のバグとして修正すべきです。

クライアントの標準的な扱い

このセクションでは、クライアントが A2A プロトコルレスポンスから AdCP レスポンスを抽出する方法を正確に定義します。

クイックリファレンス

ポイント:
  • 最終ステータスTask オブジェクトを用い、データは .artifacts に格納。サーバーに構造化ペイロードがない場合(例: JSON-RPC パースエラー、タスク前の認証失敗)、status.message.parts にテキストメッセージのみを置くことがある — クライアントはその場所にフォールバックする。
  • 中間ステータスTaskStatusUpdateEvent を用い、status.message.parts[] に任意データ。
  • ストリーム/Webhook 配信 はペイロードを A2A 1.0 の StreamResponse oneof({ task }{ statusUpdate }{ artifactUpdate }{ message })でラップする。クライアントはフィールドを読む前にアンラップする。
  • いずれのステータスもデータがある場合は AdCP スキーマを使用。
  • 中間ステータスのスキーマは策定中で変わる可能性あり。

ルール1: ステータスに応じた処理

クライアントは、正しいデータ抽出場所を決定するため、正規化されたステータスで分岐しなければなりません。ここで参照する status は AdCP の統合小文字値(例: "completed")です。status.state の生の A2A ワイヤー値は 1.0 では TASK_STATE_COMPLETED、v0.3 では completed です。比較する前に正規化してください — A2A レスポンス抽出を参照してください。
重要:
  • 中間ステータス: TaskStatusUpdateEventstatus.message.parts[] から抽出
  • 最終ステータス: Task オブジェクト → .artifacts[0].parts[] から抽出。アーティファクトが空の場合は status.message.parts[] にフォールバック

Rule 2: Data Extraction Helpers

Extract data from the appropriate location based on webhook type:
これらの検出器は両方のワイヤーフォーマットで動作します。1.0 の DataPart は data が設定されている(kind なし)、v0.3 の DataPart は kind: "data"data が設定されている — どちらも p.data != null を満たします。

ルール3: スキーマ検証

すべての AdCP レスポンスはスキーマを用いますが、検証方法はステータスによって異なります:
スキーマ進化の注意: 中間ステータスのスキーマ(*-async-response-working.json など)は策定中です。安定するまでは緩やかな扱いにする選択も可能です。

完全な例

Task と TaskStatusUpdateEvent の両方を正しく扱う統合例:

Last Data Part Authority パターン

Test Cases

✅ Correct Behavior

❌ Incorrect Behavior (Common Mistakes)

エラーハンドリング

タスクレベルのエラー(部分失敗)

タスクは実行されたが完全には完了しなかった場合。status: "completed" の DataPart に errors 配列を入れます:
errors 配列を使う場面:
  • プラットフォーム認可の問題(PLATFORM_UNAUTHORIZED
  • データが部分的にしかない場合
  • データの一部でバリデーション問題がある場合

プロトコルレベルのエラー(致命的)

タスクが実行できなかった場合。status: "failed" とメッセージを返します:
status: failed を使う場面:
  • 認証失敗(無効/期限切れトークン)
  • リクエスト不正(JSON 破損、必須フィールド欠落)
  • リソース不在(未知の taskId、期限切れ context)
  • システムエラー(DB 不調、内部サービス障害)

エラーの所在: 決定ルール

配置は、サーバーが何を持っているか、どの状態にあるかで選択されます: 目安: サーバーが構造化エラーデータを持つ場合、それを DataPart としてアーティファクトに入れる。status.message は、タスクアーティファクトが一度も生成されなかったケース(JSON-RPC パースエラー、認証ハンドシェイク失敗、不正リクエスト、詳細のないユーザー起因キャンセル)向けのフリーテキストフォールバックだ。A2A 1.0 §3.7 もこれを補強する: 「メッセージはタスク出力の配信に使うべきではない。結果はアーティファクトで返すべきである。」 rejected vs failed サーバーがタスクの試行を拒否する場合(作業開始前のポリシー/ティア/検証チェック)は rejected を使う。作業が開始されて致命的なエラーに遭遇した場合は failed を使う。どちらもアーティファクトに adcp_error を運ぶ — 状態は障害がいつ発生したかを区別し、それが呼び出し元側で異なるリトライと UX 挙動を駆動する。 キャンセル起源はセラー帰属ではなくクライアントで照合される。 status.state: "canceled"(または TASK_STATE_CANCELED)は、キャンセルがユーザー起因かシステム起因かを呼び出し元に伝えない — セラーは、実際にはユーザー起因だったキャンセルについて、バイヤーの帳簿やリトライロジックを誤らせるために adcp_error をアーティファクトに置くこともできる。クライアントはキャンセル起源をローカルで照合しなければなりません(MUST): この taskId について未処理の tasks/cancel リクエストがある場合、ペイロードに関わらずキャンセルをユーザー起因として扱い、セラーが付加した adcp_error を無視します。クライアントは、セラーが送った adcp_error.recovery ヒントを根拠にユーザー起因のキャンセルをリトライしてはなりません(MUST NOT)。

ステータスマッピング

AdCP は A2A の TaskState enum をそのまま使用します:

Webhook ペイロード

非同期処理(status: "submitted")では Webhook でも同じアーティファクト構造を返します:
AdCP データは同じ Last DataPart パターンで抽出します。Webhook 認証、リトライパターン、セキュリティWebhooks を参照してください。

レスポンス内の File Part

クリエイティブ系の操作ではファイル参照を含む場合があります:
File Part の用途: プレビュー URL、生成済みアセット、トラフィッキングレポート。AdCP レスポンスの生データには使わず、必ず DataPart を使用。

リトライと冪等性

TaskId による重複排除

A2A の taskId はリトライ検出に使えます。エージェントは次を行うべきです:
  • taskId が完了済みオペレーションと一致する場合(TTL 内)、キャッシュレスポンスを返す
  • 進行中のオペレーションに対する重複 taskId 送信は拒否します

Implementation Checklist

When implementing A2A responses for AdCP: Final Responses (status: “completed” or “failed”) - Use Task object:
  • Always include status field from TaskState enum
  • Use .artifacts array with at least one DataPart containing AdCP response payload
  • Include TextPart with human-readable message (recommended for UX)
  • Use single artifact with multiple parts (not multiple artifacts)
  • Use last DataPart as authoritative if multiple exist
  • Never nest AdCP data in custom wrappers (no { response: {...} } objects)
  • DataPart content MUST match AdCP schemas (validate against [task]-response.json)
Interim Responses (status: “working”, “submitted”, “input-required”) - Use TaskStatusUpdateEvent:
  • Use status.message.parts[] for optional data (not .artifacts)
  • TextPart is recommended for human-readable status updates
  • DataPart is optional but follows AdCP schemas when provided ([task]-async-response-[status].json)
  • Interim schemas are work-in-progress - clients may handle more loosely
  • Include progress indicators when applicable (percentage, current_step, ETA)
Error Handling:
  • Use status: "failed" for protocol errors only (auth, invalid params, system errors)
  • Use errors array for task failures (platform auth, partial data) with status: "completed"
General:
  • Include taskId and contextId for tracking
  • Follow discriminated union patterns for task responses (check schemas)
  • Use correct payload type: Task for final states, TaskStatusUpdateEvent for interim
  • Support taskId-based deduplication for retry detection

See Also