> ## 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 エージェントの呼び出し

> すべての AdCP バイヤーが従わなければならないワイヤーレベルの不変条件: idempotency_key リプレイ、account の oneOf バリアント、非同期 status:'submitted' ポーリング、adcp_error.issues[] からのエラーリカバリー。

# AdCP エージェントの呼び出し

このページは正準なバイヤー側のワイヤーコントラクトです: どの単一タスクスキーマにもきれいに収まらないが、あなたが行うすべての変更呼び出しに適用されるルール。バイヤー（DSP、プランニングツール、エージェンティッククライアント）を構築し、AdCP のセールス、クリエイティブ、シグナル、ガバナンス、SI、ブランドエージェントを呼び出すなら、これを一度読んでください。

このコンテンツのエージェント向けバージョンは [`skills/call-adcp-agent/SKILL.md`](https://github.com/adcontextprotocol/adcp/blob/main/skills/call-adcp-agent/SKILL.md) にあります — SDK がコーディングエージェントに出荷できるよう [プロトコル tarball](/docs/building/by-layer/L0/schemas#one-shot-protocol-bundle) にバンドルされています。

## Discovery chain

任意の新しいエージェントとの最初の接触では、これらを順にたどります:

1. **Agent card**（A2A）または **`tools/list`**（MCP）: ツール*名*を返す。AdCP MCP サーバーは `tools/list` でツールごとのパラメータースキーマをもはや公開しません — すべてのツールは `{type: 'object', properties: {}}` を示す。そこから形状を推論しようとしないでください。
2. **`get_adcp_capabilities`**: サポートするプロトコル、AdCP メジャーバージョン、機能フラグを返す。このエージェントが*どの*ツールをサポートするかを教えますが、それらをどう呼ぶかは教えません。[`get_adcp_capabilities`](/docs/protocol/get_adcp_capabilities) を参照。
3. **`get_schema(tool_name)`** *（エージェントがそれを公開するとき — 標準化保留中、[#3057](https://github.com/adcontextprotocol/adcp/issues/3057) を参照）*: 特定のツールのリクエスト/レスポンスの JSON Schema を返す。
4. **バンドルされたスキーマ**（オフライン、権威的）: すべての公開された AdCP バージョンは、すべてのツールの JSON Schema を Sigstore 経由で署名して出荷します。パスは SDK によって異なります — 仕様リポジトリソースは `dist/schemas/<version>/bundled/` を使い、`@adcp/sdk` は `npm run sync-schemas` の後にそれらを `schemas/cache/<version>/bundled/` に置き、Python と Go の SDK は独自の慣例を使います。パスをハードコードせず、SDK のローダーに見つけさせてください。いったん見つかれば、各スキーマは `<protocol>/<tool>-{request,response}.json` にあります。

## Idempotency: replay vs. new operation

すべての変更ツールは `idempotency_key`（UUID）を必要とします。

* **リトライで同じキー** → サーバーは**同じレスポンス**をバイト単位でリプレイする。トランスポートレベルのリトライ（タイムアウト、5xx、切断された接続）にこれを使う。
* **新しいキー** → ボディにかかわらず**新しい操作**。前回の試行が失敗したという理由で新しい UUID を生成することは、素朴な呼び出し元が重複したメディアバイを作る最も一般的な方法です。
* **同じキー、異なる正準ボディ** → `IDEMPOTENCY_CONFLICT`。セラーは拒否しなければならない（MUST）（[security.mdx#冪等性](/docs/building/by-layer/L1/security#冪等性) のルール 5） — 2 番目のボディを黙って適用せず、最初のレスポンスを黙ってリプレイしないでください。
* **最初のリクエストがまだ実行中に同じキー** → `IDEMPOTENCY_IN_FLIGHT`（[security.mdx#冪等性](/docs/building/by-layer/L1/security#冪等性) のルール 9）。セラーはブロックする代わりに `error.details.retry_after` 付きでこのコードを返してもよい（MAY）。**同じキー**で待って再試行する — このコードで新しいキーを鋳造すると、安全なリトライが二重実行レースになります。

非同期フローでは、リプレイされたレスポンスは**同じ `task_id`** を運ぶため、フォークするのではなく同じタスクに対してポーリングが続きます。

`idempotency_key` は次で必須です: `create_media_buy`、`update_media_buy`、`sync_creatives`、`sync_audiences`、`sync_accounts`、`sync_catalogs`、`sync_event_sources`、`sync_plans`、`sync_governance`、`activate_signal`、`acquire_rights`、`log_event`、`report_usage`、`provide_performance_feedback`、`report_plan_outcome`、`create_property_list`、`update_property_list`、`delete_property_list`、`create_collection_list`、`update_collection_list`、`delete_collection_list`、`create_content_standards`、`update_content_standards`、`calibrate_content`、`si_initiate_session`、`si_send_message`。

キーの欠落 → `issues` に `/idempotency_key` を伴う `adcp_error.code: 'VALIDATION_ERROR'`。

## `account` is `oneOf` — pick exactly one variant

`account` は判別共用体です。`create_media_buy` と `update_media_buy` では 2 つのバリアント:

```json theme={null}
// variant 0: セラー割り当て id による（list_accounts または帯域外オンボーディングから。
// バイヤー宣言セラーは sync_accounts の account_id を内部ハンドルとしてエコーすることもある）
"account": { "account_id": "seller_assigned_id" }

// variant 1: 自然キーによる（brand + operator、任意の sandbox）
//   brand.domain — バイヤーのブランドドメイン（例: 広告主のウェブサイト）
//   operator     — ブランドに代わって動作するバイヤー側のエンティティ
"account": { "brand": { "domain": "acme.com" }, "operator": "pinnacle-media.com" }
```

**バリアントをまたいで必須フィールドをマージしないでください。** 各バリアントの `additionalProperties: false` は、`{account_id, brand}` が**両方**で失敗することを意味します。

タスクスキーマが `account` を必須とするとき、SDK が認証済み認証情報で利用可能な唯一のアカウントを自動選択していても、明示的な `AccountRef` を送ってください。隠れた認証情報由来のデフォルト化はプロトコルモデルではありません。タスクが `account` を任意とマークするとき、省略はそのタスクが文書化したセマンティクスのみを持ちます。

他のツール（例: `sync_creatives`）はスーパーセットを受け入れることがあります — 常に特定のツールのスキーマを確認してください。

## Async responses: `status: 'submitted'` means queued

変更ツールは 3 つの形状の 1 つを返せます:

```json theme={null}
// 成功（同期）: 作業は完了
{ "media_buy_id": "mb_123", "packages": [...], "confirmed_at": "..." }

// Submitted（非同期）: 作業はキューイングされた
{ "status": "submitted", "task_id": "tk_abc", "message": "Awaiting IO signature" }

// エラー: 修正せずにリトライしない
{ "errors": [{ "code": "PRODUCT_NOT_FOUND", "message": "..." }] }
```

AdCP タスク状態は**アプリケーション層**のコントラクトです。MCP と A2A は AdCP レスポンスをラップ、ストリーム、またはトランスポートできますが、それらのネイティブなタスクメカニズムは AdCP の `task_id`、ステータス値、webhook ペイロード、ポーリング/再照合サーフェスを置き換えません。トランスポートタスクは、ペイロードがまだ `status: 'submitted'` と言う AdCP レスポンスを配信した後に完了できます。

`status: 'submitted'` を見たとき、作業は完了して**いません**。3.x では、返された `task_id` を使ってレガシー AdCP `tasks/get` サーフェス経由でポーリングします。セラーは衝突しない `get_task_status` エイリアスもアドバタイズしてもよく（MAY）、呼び出し元はそれがディスカバリーに現れたときそのエイリアスを使ってもよい（MAY）。両方の AdCP ポーリング名は、マルチアカウント認証情報用の任意の `account` スコープを含め、同じ snake\_case ペイロード形状を使います。どちらの AdCP ポーリング形状も、トランスポート独自のタスクワイヤー形状を使うトランスポートネイティブの MCP/A2A `tasks/get` と混同しないでください。

ポーリング時に `include_result: true` を渡すと、ステータスが `completed` に遷移したときにセラーが完了ペイロードを含めます:

```json theme={null}
// tasks/get リクエスト（任意の get_task_status エイリアスと同じペイロード）
{
  "task_id": "task_456",
  "include_result": true,
  "account": {
    "brand": { "domain": "acmeoutdoor.example" },
    "operator": "pinnacle-agency.example",
    "sandbox": true
  }
}

// tasks/get レスポンス — completed
{
  "task_id": "task_456",
  "task_type": "create_media_buy",
  "protocol": "media-buy",
  "status": "completed",
  "completed_at": "2025-01-22T10:30:00Z",
  "result": {
    "media_buy_id": "mb_12345",
    "packages": [{ "package_id": "pkg_001" }]
  }
}
```

`result` フィールドは、完了タスクのプッシュ通知 webhook の `result` フィールドと同じペイロード構造を使います — ポーリングと webhook の両方を設定するバイヤーは、どちらの経路でも同じデータ形状を受け取ります。

## Error recovery — read `issues[]`

すべての検証失敗は、次のような形状のエンベロープを生成します:

```json theme={null}
{
  "adcp_error": {
    "code": "VALIDATION_ERROR",
    "recovery": "correctable",
    "field": "/first/offending/pointer",
    "issues": [
      {
        "pointer": "/account",
        "keyword": "oneOf",
        "message": "must match exactly one schema in oneOf",
        "variants": [
          { "index": 0, "required": ["account_id"],        "properties": ["account_id"] },
          { "index": 1, "required": ["brand", "operator"], "properties": ["brand", "operator", "sandbox"] }
        ]
      },
      { "pointer": "/brand/domain", "keyword": "required", "message": "must have required property 'domain'" }
    ]
  }
}
```

* `issues[].pointer` — 問題のあるフィールドへの RFC 6901 JSON Pointer
* `issues[].keyword` — Ajv キーワード（`required`、`type`、`oneOf`、`anyOf`、`additionalProperties`、`format`、`enum`）
* `issues[].variants` — `keyword` が `oneOf` または `anyOf` のとき、各エントリが 1 つのバリアントの `required` + 宣言された `properties` をリストする

**`oneOf` 失敗については、`variants[]` から 1 つのバリアントを選び、その `required` フィールドのみを送ってください。** これは、フィールドが共用体だと知らなかったときの最速のリカバリーパスです。

`recovery` 値:

* `correctable` — バイヤー側の修正。`issues[]` を読み、ポインターをパッチし、再送する
* `transient` — **同じ** `idempotency_key` でリトライする
* `terminal` — 人間の対応が必要（アカウント停止、支払い必要）。リトライしない

## Common shape pitfalls

| Symptom                                                  | What it means                          | Fix                                                                |
| -------------------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------ |
| `variants[]` を伴う `keyword: 'oneOf'`                      | 判別共用体 — 複数のバリアントからフィールドを送ったか、どれも送らなかった | `variants[]` から 1 つのバリアントを選ぶ。その `required` フィールドのみを送る。             |
| 同じポインターで 2〜3 個の `additionalProperties` エラー               | `oneOf` バリアントをマージした                    | 1 つのバリアントに落とす。「完全性のため」に「余分な」フィールドを保持しない。                           |
| `keyword: 'required'`、`pointer: '/idempotency_key'`      | 変更ツール、UUID なし                          | 論理操作ごとに新しい UUID を生成。リトライで再利用。                                      |
| `/budget` で `keyword: 'type'` または `additionalProperties` | `{amount, currency}` を送った              | `budget` は数値。通貨は `pricing_option_id` によって暗示される。                    |
| `/format_id` で `additionalProperties`（文字列を渡した）           | `"format_id": "video_..."` を送った        | `format_id` は `{agent_url, id}` — 常にオブジェクト。                        |
| `/destinations/*/type` で `keyword: 'enum'`               | 捏造した destination タイプ                   | `'platform'`（`platform` 付き）または `'agent'`（`agent_url` 付き）を使う。       |
| レスポンスが `status: 'submitted'` と `task_id` を運ぶ             | 非同期 — 作業はキューイングされ、完了して**いない**          | レガシー `tasks/get`、またはセラーがエイリアスをアドバタイズするとき `get_task_status` でポーリング。 |

## Transport notes

* **MCP**: `{ name: 'tool_name', arguments: {...} }` を伴う `tools/call`。型付きレスポンスは `structuredContent` を読む。
* **A2A**: `{ skill: 'tool_name', input: {...} }` の形状の `DataPart` を伴う `message/send`。型付きレスポンスは `task.artifacts[0].parts[0].data` にある。

両トランスポートは冪等性、エラー形状、スキーマ強制、ハンドラーセマンティクスを共有します。ある呼び出しが一方で機能するなら、同等の呼び出しは他方でも機能します。

よくある罠: **A2A の `Task.state: 'completed'` は AdCP の完了と同じではありません。** A2A タスク状態はトランスポート呼び出しのライフサイクルを記述します。AdCP レベルの完了はアーティファクトのペイロード（`structuredContent.status` または `data.status`）にあります。`completed` の A2A タスクでも `submitted` の AdCP レスポンスを運べます。

## Related

* タスクごとのリクエスト/レスポンス形状: プロトコル固有のリファレンス（`/docs/media-buy/`、`/docs/creative/`、`/docs/signals/` など）を参照。
* [プロトコルアーキテクチャ](/docs/protocol/architecture) — プロトコルドメインがどう組み合わさるか。
* [必須タスク](/docs/protocol/required-tasks) — 専門分野を主張するためにエージェントが実装しなければならないタスク。
* [`get_adcp_capabilities`](/docs/protocol/get_adcp_capabilities) — 任意の新しいエージェントに対する最初の呼び出し。
* [Schemas](/docs/building/by-layer/L0/schemas) — SDK がプロトコル tarball（現在 `skills/` をバンドル）をどう消費するか。
* [Build a caller](/docs/building/by-layer/L4/build-a-caller) — 呼び出し元側のビルド形式ガイド: インストール、呼び出し、レスポンス処理、レポート取り込み。
