> ## 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 エージェントを持つ採用者のための段階的移行パス。棚卸しステップ、最低リスク優先のスワップ順、衝突モード（冪等性、アカウントモード、webhook 署名、ステートマシンドリフト）、ステップごとのロールバックプレイブック、適合性を通過する中間状態、移行しない場合。

このガイドは、フラグデイの書き直しなしに公式 SDK に移行したい **本番で動作する AdCP エージェント** を持つ採用者向けです。あなたのエージェントは実トラフィックを提供します。現在のスタックを構築しそれを守るエンジニアがいます。数週間の凍結を許容できません。パスは段階的です — 一度に 1 層をスワップし、各ステップ後に出荷し、進むにつれ再認証します。

グリーンフィールドなら、間違ったドキュメントにいます — [エージェントを構築する](/docs/building/by-layer/L4/build-an-agent) を参照。そもそも移行するか決めている段階なら、building 概要の [手書き再評価チェック](/docs/building#two-checks-before-you-start) を参照。

## 0. 今日所有するものを棚卸しする

何かをスワップする前に、手書きスタックが [AdCP スタック](/docs/building/cross-cutting/sdk-stack) の各層で何を提供するかを書き留めます。そのドキュメントの L0–L3 チェックリストをルーブリックとして使ってください。各行をマーク: *出荷済み* / *部分的* / *まだ*。

これが操作の順序を決めます。最低リスクのスワップは通常、今日 **最も少ない** カバレッジを持つ層です。なぜなら、調整する既存の動作が最も少ないからです。

## 1. コードを変える前に、まず仕様適合性に到達する

最も重要な単一のステップ:

1. エージェントに **mock-mode アカウント** を立てる。（live/sandbox/mock の区別がまだない場合、下の [Account-mode mismatch](#account-mode-mismatch) を参照 — まず境界にフラグを追加する。）
2. mock-mode トラフィックをリファレンスモックサーバーにルーティングする。
3. エージェントに対して AdCP ストーリーボードを実行する（[Conformance](/docs/building/verification/conformance) と [エージェントを検証する](/docs/building/verification/validate-your-agent) を参照）。
4. pass/fail レポートを読む。

失敗リストがあなたの移行バックログで、順序付けられています。「SDK が価値を追加すると思う」を「これが失敗するストーリーボードで、それぞれがどの L3 コンポーネントを指すか」に変換します。このステップなしでは、測定されたギャップの代わりにセールストークに基づいて SDK を買っています。

思ったより準拠していることを発見するかもしれません（その場合移行は予想より小さい）か、より少ない（その場合 SDK 採用の論拠が強まる）。どちらの結果も有用です。

## 2. 操作の順序（最低リスク優先）

推奨スワップ順:

1. **適合性テストサーフェス**（[`comply_test_controller`](/docs/building/by-layer/L3/comply-test-controller)）。純粋に加算的 — mock-mode トラフィックが今や SDK を通る。ライブトラフィックは触れられない。その場で仕様適合性認証を獲得。
2. **エラーコードカタログ**。エラーエンベロープ構築を SDK のエラービルダーで置き換える。リカバリー分類とコード優先度（例: `INVALID_STATE` より `NOT_CANCELLABLE`）が無料で来る。[Error handling](/docs/building/by-layer/L3/error-handling) を参照。
3. **冪等性キャッシュ**。最もリスクの高いスワップ — [Two idempotency caches in series](#two-idempotency-caches-in-series) を参照。仕様コントラクト: [Idempotency](/docs/building/by-layer/L1/security#idempotency)。
4. **非同期タスクストア + ディスパッチャー**。SDK の `task_id` + 終端アーティファクトコントラクトを採用。しばしばワーカーキューに触れる。[Task lifecycle](/docs/building/by-layer/L3/task-lifecycle) を参照。
5. **ステートマシン**、一度に 1 リソース。最も保守時間を費やす場所なら MediaBuy を最初に（[ライフサイクルリファレンス](/docs/media-buy/media-buys/lifecycle)）。各後にライフサイクルストーリーボードを再実行。
6. **Webhook 発出**（署名済み、リトライ済み、冪等）。1–5 と独立。並列化できる。[Webhooks](/docs/building/by-layer/L3/webhooks) を参照。
7. **RFC 9421 署名 + 検証**。上のすべてと独立。並列化できる。[Security implementation](/docs/building/by-layer/L1/security) を参照。
8. **認証 / アカウントストア**。最後。手書きの L2 はおそらく簡単には動かないビジネス決定をエンコードしている。

任意のステップで止められます。L2 なしで L3（ステップ 1–6）を採用するのは完全に有効なエンドポイントです — あなたの認証層はそれがすることを続け、SDK がプロトコルセマンティクスを引き継ぎます。[What you can leave hand-rolled](#5-what-you-can-leave-hand-rolled) を参照。

## 3. 注意すべき衝突モード

これらは、来るのが見えないと段階的移行を痛みにする「2 つのスタックが互いに戦う」失敗モードです。

### Two idempotency caches in series

既存のキャッシュは境界でリクエストをフィールドし、SDK のキャッシュはプロトコル境界でリクエストをフィールドします。症状: どのキャッシュが最初にヒットしたかに応じて同じ `idempotency_key` が異なるエンベロープを返す。クロスペイロード再利用が一方で検出され他方で検出されない。

**解決。** 1 つを選び、他を退役させる。通常あなたのを退役 — SDK のは `IDEMPOTENCY_CONFLICT` の *no-payload-echo* 不変条件（盗まれた鍵の read-oracle 脅威）と、仕様が義務付けるクロスペイロード衝突検出を強制します。ストレージバックエンド（Redis、Postgres）を保持する必要があるなら、SDK をフォークする代わりにカスタムバックエンドとして SDK のキャッシュコントラクトをそれに向けます。

### Account-mode mismatch

SDK は `live` / `sandbox` / `mock` アカウントを区別します（[Sandbox](/docs/media-buy/advanced-topics/sandbox) を参照）。手書きスタックが区別を欠く場合、mock-mode ストーリーボードがライブハンドラーにディスパッチする可能性があります。症状: ストーリーボードが本番状態を変異させる。適合性認証がディスパッチを拒否する。

**解決。** SDK の適合性コントローラーを採用する前に、境界にアカウントモードフラグを追加します。`comply_test_controller` は sandbox または mock でない任意のアカウントに対して実行するのを拒否します — その拒否はバグではなく機能です。

### Webhook signature ownership

両スタックがアウトバウンド webhook に署名しようとすると、受信者は 2 つの `Signature` ヘッダーを見ます（または一方が勝ち他方がプロキシによって黙って上書きされる）。どちらにせよ、署名は検証されません。

**解決。** 境界で 1 つの署名者を選ぶ。通常 SDK の、なぜなら公開鍵レジストリに対して鍵ローテーションを追跡し RFC 9421 正準化を正しく扱うからです。KMS 裏付けの鍵素材を保持し、それを使うよう SDK の署名プロバイダー抽象を設定します。

### State machine drift

手書きのステートマシンはおそらく SDK が拒否するエッジ（例: `active` をスキップする直接 `pending_creatives → completed`、または `NOT_CANCELLABLE` 対 `INVALID_STATE` 優先度を区別しない `active → canceled`）を持ちます。症状: 成功を期待した場所でライフサイクルストーリーボードが `INVALID_STATE` で失敗する。

**解決。** ステートマシンをスワップする *前に* エージェントに対してライフサイクルストーリーボードを実行します。エッジセットを仕様に調整 — 明白なバグを修正し、曖昧さについて仕様 issue を提出。次に SDK のステートマシンをスワップイン。それはあなたが手で収束させたものを強制します。

### Webhook delivery transport

キュー/ワーカースタックが今日 webhook を配信する場合、あなたのを退役させずに SDK のエミッターを配線すると二重配信します。症状: 受信者がわずかに異なる時刻に同じペイロードで重複する冪等性キーを見る。

**解決。** SDK はエンベロープを構築します。どう出荷するかはあなた次第です。組み込みの HTTP 配信を実行する代わりに既存のトランスポートに引き渡すよう SDK を設定 — それがシーム。

### Schema validation collisions

インバウンドペイロードを独自のスキーマバンドルに対して検証し、SDK がその境界で再び検証すると、重複作業（安価）か矛盾する判定（実際のバグ — あなたのバンドルが公開スキーマからドリフトした）のいずれかを得ます。

**解決。** SDK が入った後、ローカル検証器を退役させます。両方が実行される間、任意の不一致を SDK が間違っているのではなくあなたのバンドルが古いものとして扱います。

## 4. 適合性を通過する中間状態

各ステップ後、mock-mode ストーリーボードを再実行し再認証できます。適合性を主張するために移行を終える必要はありません — SDK の適合性スイートが強制する任意の切り取りラインでストーリーボードを通過するだけです。

| After step | What you have             | Conformance status                               |
| ---------- | ------------------------- | ------------------------------------------------ |
| 1          | 適合性コントローラー配線済み。エージェント変更なし | **仕様適合性**（mock-mode ストーリーボードが変更されていない L3 に対して実行） |
| 2          | + SDK エラーエンベロープ           | 同じ。より良いリカバリーセマンティクス                              |
| 3          | + SDK 冪等性                 | 同じ。クロスペイロード再利用でより厳格なセキュリティ                       |
| 4          | + SDK 非同期タスクコントラクト        | 同じ。一様なタスクライフサイクル                                 |
| 5          | + SDK ステートマシン             | 同じ。遷移検証はもはやあなたの問題でない                             |
| 6          | + SDK webhook エンベロープ      | 同じ。署名済み、リトライ済み、重複排除キー付き                          |
| 7          | + SDK 署名                  | **ライブ適合性**（そのストーリーボードセットが出荷されたとき）                |
| 8          | + SDK アカウントストア            | 完全な L4-on-SDK                                    |

各ステップ後に出荷します。本番トラフィックは維持されます。

### ステップごとのロールバック

スワップ順の各ステップは約 5 分以内で可逆であるべきです。一般的なパターン: 各スワップは、削除ではなく **手書きコンポーネントと SDK のものの間のフィーチャーフラグ付きスイッチ** です。アカウントごとのフラグの背後でスワップを出荷し、観測し、次にデフォルトを反転します。ロールバックは反対方向の同じフラグです。

スワップごとに計画すべきこと:

| Step              | Revert mechanism             | What state may have leaked                                                                                                     | First thing to verify on rollback                       |
| ----------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------- |
| 1. 適合性コントローラー     | mock-mode アカウントで SDK ルートを無効化 | なし — mock-mode は設計上 sandbox のみ                                                                                                 | モックストーリーボードが手書きの L3 に対してまだ通過                            |
| 2. エラーエンベロープ      | エラービルダーに戻す                   | スワップウィンドウのアウトバウンドエンベロープが SDK 形状のエラーコードを運ぶかも。古いコードでキーする下流コンシューマーがそれらをログしたかも                                                     | エラー監視ダッシュボードが再び正しいエンベロープ形状を読んでいる                        |
| 3. 冪等性キャッシュ       | あなたのキャッシュに戻す                 | **スワップウィンドウ中に両キャッシュがトラフィックを見た。** 同じ `idempotency_key` が今や両ストアに異なるエンベロープで存在するかも。ロールバック後、あなたのキャッシュが権威的。revert で SDK のキャッシュをフラッシュ | dual-cache ウィンドウからの `IDEMPOTENCY_CONFLICT` ストームなし       |
| 4. 非同期タスクコントラクト   | あなたのタスクストアに戻す                | SDK のコントラクト下で始まった未完了タスクが、ワーカーが期待するのと異なる終端アーティファクト形状を持つかも                                                                       | revert が着地する前にスワップウィンドウ中に作成されたタスクをドレインまたはアボート           |
| 5. ステートマシン        | あなたのステートマシンに戻す               | SDK が、あなたのマシンが受け入れた遷移を拒否したかも（またはその逆）。影響を受けるリソースは、あなたのコードが進める方法を知らない状態にある                                                       | ワンショット再照合クエリを実行: 「両マシンで合法な状態のリソースはあるか？ 一方でのみ合法な状態のものは？」 |
| 6. Webhook エンベロープ | あなたのエミッターに戻す                 | 受信者がスワップウィンドウ中に SDK 形状の webhook を得た。既に ack したかも。ロールバックで再発出しない                                                                  | 重複排除テーブルが古い/新しい `idempotency_key` 形状の両方を受け入れる（移行的）      |
| 7. RFC 9421 署名    | あなたの署名者に戻す                   | 受信者がウィンドウ中に SDK 署名の webhook/レスポンスを得た。その鍵レジストリはあなたの古い `keyid` をまだ解決しなければならない                                                    | あなたの古い `keyid` がまだ JWKS に公開されている                        |
| 8. アカウントストア       | あなたのストアに戻す                   | SDK のストア下でなされたアカウント解決決定が、あなたのストアと異なるテナントにトラフィックをルーティングしたかも                                                                     | 完全に revert する前にスワップウィンドウ中に解決されたアカウントで再照合を実行             |

### 午前 2 時の本番障害

スワップ N が午前 2 時に本番で失敗した場合、オンコールレシピ:

1. 影響を受けるアカウント（または影響範囲を分離できないならグローバルに）について、**アカウントごとのフラグを手書きコンポーネントに戻す**。これが出血を止めるのに必要な唯一のステップ。
2. そのステップの上の **漏洩行を確認する**。ほとんどのステップはどこかに残余状態を残す — 朝のデバッグがコールドスタートしないようそれが何かをメモする。
3. **インシデント中に適合性スイートを再実行しない。** それは mock-mode に対して実行される。本番障害は異なるシグナル。
4. **一般的な SDK ではなくスワップステップに対してインシデントを提出する。** 移行ガイドのスワップ順が調査の単位。SDK のカバレッジマトリクスはその下流。

**不可逆なスワップを計画しない。** ステップが flag-and-flip パターンに適合しない（例: 破壊的スキーマ移行）場合、スワップ順の一部としてではなく、別個の名前付きプロジェクトとして行います。

## 5. What you can leave hand-rolled

SDK は仕様が意見を持つ場所で意見を持ち、そうでない場所でプラグイン可能です。既存のインフラを諦める必要はありません:

* **署名プロバイダー。** KMS 統合を保持。SDK はカスタム署名者を受け入れる。
* **アカウントストア。** マルチテナントルーティングを保持。SDK のアカウントストアインターフェースがシーム。
* **冪等性バックエンド。** Redis / Postgres を保持。SDK のキャッシュコントラクトはプラグイン可能。
* **Webhook 配信トランスポート。** キューを保持。SDK はエンベロープを構築する。どう出荷するかはあなた次第。
* **スキーマ検証ライブラリ。** 望むなら検証器を保持。SDK はその境界で独自のを使い、あなたのではない。

手書きスタックがこれらに良い答えを持つなら、フォークではなく **設定** としてスワップインします。

## 6. 移行中のバージョニング

ジャグリングする 2 つのバージョン軸:

* **バイヤーの仕様バージョン。** 移行は、バイヤーバージョンでハンドラーをフォークするのをやめるため呼び出しごとの `adcpVersion` ピン留めを追加する絶好の瞬間。[Version Adaptation](/docs/building/cross-cutting/version-adaptation) を参照。
* **SDK バージョン。** 最終状態としてレガシーインポートパスに移行しない — それを *通じて* 移行する。レガシーサブパスは、残りが古いものに留まる間、新しいエントリポイントで一度に 1 つの専門分野を採用できるよう存在する。同じプロジェクトのグリーンフィールドコードは新しいフレームワークを直接使う。

### 実践例: 2 バイヤー、スワップ中盤

ステップ 3（冪等性）にいて、バイヤー A は AdCP 2.5、バイヤー B は AdCP 3.0。切り替えたアカウントについて SDK のコントローラー、エラーエンベロープ、冪等性キャッシュを採用済み。バイヤー A は SDK への飛行中、バイヤー B は SDK でグリーンフィールド。

インバウンド側: 各ピアの仕様バージョンを事前に識別（エージェントレジストリ、エージェントカード、または存在すれば `adcp_version` フィールドから）、エージェント / 呼び出しごとに `adcpVersion` をピン留め、SDK にワイヤー形状を適応させます。`@adcp/sdk` の例:

```ts theme={null}
import { ADCPMultiAgentClient } from '@adcp/sdk';

const buyerA = new ADCPMultiAgentClient([{
  id: 'buyer-a',
  agent_uri: 'https://buyer-a.example.com/mcp/',
  protocol: 'mcp',
  auth_token: process.env.BUYER_A_TOKEN,
  adcpVersion: 'v2.5',  // ← per-agent pin, no fork in handlers
}]);

const buyerB = new ADCPMultiAgentClient([{
  id: 'buyer-b',
  agent_uri: 'https://buyer-b.example.com/a2a',
  protocol: 'a2a',
  auth_token: process.env.BUYER_B_TOKEN,
  adcpVersion: '3.0', // ← canonical / current
}]);
```

アウトバウンド（サーバー）側、*あなたが* 何を受け入れるかを宣言:

```ts theme={null}
import { createAdcpServer } from '@adcp/sdk/server';

createAdcpServer({
  capabilities: {
    major_versions: [3],
    supported_versions: ['3.0'],
  },
  // …handlers, all on the canonical 3.0 shape;
  // 2.5 callers are translated by client-side adapters before they reach you.
});
```

ステップ 3 中盤で各バイヤーからの 1 呼び出しがどう見えるか:

|                | Buyer A (2.5 wire)         | Buyer B (3.0 wire)     |
| -------------- | -------------------------- | ---------------------- |
| **インバウンド形状**   | 2.5 `create_media_buy`     | 3.0 `create_media_buy` |
| **アダプターがすること** | 2.5 → 3.0 形状を変換            | パススルー                  |
| **ハンドラーが見るもの** | 3.0 型付きオブジェクト              | 3.0 型付きオブジェクト（同じ）      |
| **冪等性キャッシュ**   | SDK の（ステップ 3 にいる）          | SDK の                  |
| **エラーエンベロープ**  | SDK の、アウトバウンドで 2.5 に変換して戻す | SDK の                  |
| **アウトバウンド形状**  | 2.5（出る途中でアダプターが変換）         | 3.0                    |

1 つのハンドラーコードベース。2 つのワイヤーバージョン。両バイヤーが期待するエンベロープ形状を見る。ステップ 3 で `adcpVersion` ピン留めを採用するのは安価 — バージョン作業のほとんどはアダプターモジュールにあり、SDK が既に出荷しています。

フォールバック（ステップ 3 を手書きキャッシュにロールバック）しても、バイヤー A はまだ SDK の変換アダプターを通ります — バージョン機構と冪等性機構は独立です。ロールバックでハンドラーコードを再フォークしません。

## 7. 移行 *しない* とき

エージェントが少数の名前付きバイヤーに凍結されたワイヤーサーフェスを提供し、エンジニアがプロトコル保守にほぼゼロの時間を費やすなら、移行 ROI は低いです。妥当な保留:

* AdCP 2.5 にいて、どのバイヤーも 3.x を望まず、彼らが望んだら非推奨化する意志がある。
* （ステップ 1 からの）適合性ギャップが、SDK を採用せずにその場で修正するのに十分小さい。
* すべての層をエンドツーエンドで所有するハードな規制または運用上の理由がある。

それらのケースでは、とにかくステップ 1 を行う — 仕様適合性認証のため mock-mode をリファレンスモックサーバー経由でルーティング — し、AdCP 4.0 でまたはバイヤーミックスが動くとき移行問題を再訪します。

移行は、**保守負荷が実際で成長している** 採用者向けです。コストクレーム（[一から L0–L3 に約 3〜4 人月](/docs/building/cross-cutting/sdk-stack#why-sdks-matter-more-in-adcp-than-in-eg-http)）は、段階的に採用することで *買い戻している* ものです — しかしその保守負荷が実際に存在する場合のみ。

## 関連項目

* [AdCP スタック](/docs/building/cross-cutting/sdk-stack) — 層アーキテクチャリファレンス
* [どこから始めるか](/docs/building) — 決定ページ
* [Version Adaptation](/docs/building/cross-cutting/version-adaptation) — 3 メカニズムリファレンス
* [Conformance](/docs/building/verification/conformance) — ストーリーボードスイートがエージェントをどうグレードするか
* [エージェントを構築する](/docs/building/by-layer/L4/build-an-agent) — グリーンフィールドパス。L4-on-SDK の最終状態がどう見えるかのリファレンスとして有用
