Skip to main content
非規範的。 このページは補完的なハーネスパターンを説明するもので、コンプライアンス階層ではありません。このレシピはストーリーボードランナー(エージェントを検証する)の上に構築されます — ストーリーボードやステージング統合テストを置き換えるものではなく、認定ゲートでもありません。ここで説明するモックフィクスチャの規約(/_lookup/<resource>/_debug/traffic)は @adcp/sdk のリファレンス実装です。代替 SDK 実装は分岐しうる。プロトコルコントラクトではなくハーネス規約として扱ってください。
外部プラットフォーム(DSP、SSP、リテールデータウェアハウス、クリエイティブサーバー、シグナルマーケットプレイス)をラップするほとんどの AdCP エージェントは、ストーリーボードだけでは検出できないファサードバグを出荷します: ハンドラーは、実際にアップストリームと統合することなく形状的に有効な AdCP レスポンスを返します。このページのレシピはそのギャップを プレステージングゲート として閉じます — 安価、高速、CI で実行され、コードがステージングテナントに到達する前にファサードとコントラクトドリフトを表面化します。 エージェントがアップストリームをラップしない場合 — 例えば自身のデータを所有する純粋な意思決定サービス — ストーリーボードランナー単独で十分です。エージェントを検証する を参照してください。

4 ステップのレシピ

ステップ 3 は AdCP ワイヤーバグ(レスポンス形状、エラーコード、冪等性、欠けている必須フィールド)を捕捉します。ステップ 4 は 統合ギャップ を捕捉します — アップストリームの主要エンドポイントを行使することなく形状的に有効な AdCP レスポンスを返すハンドラー。両方のシグナルが重要で、片方だけでは不完全です。
上に示した mock-server CLI は @adcp/sdk(TypeScript)で出荷されます。CI が別の言語で動く場合、最もシンプルなパターンは TS CLI をサイドカーとして実行することです(例: GitHub Actions の Docker サービスコンテナ、または別の Node プロセス) — テスト対象のエージェントはネイティブ言語のままで、モック + ストーリーボードランナーだけが TS です。自身の mock-server を出荷する Python や Go SDK は下記の規約を再実装することになります。それが到達するまでは、TS CLI がリファレンスです。

なぜトラフィックカウンターか

ストーリーボードは AdCP ワイヤーコントラクトをチェックします: レスポンスはスキーマに一致したか、エージェントは正しいツールをアドバタイズしたか、コンテキストはエコーしたか。それらはワイヤーの 背後 で何が起きたかをアサートしません。このリポジトリの CLAUDE.md ガイダンスは直截に述べています: ストーリーボードはアサーションであり、真実ではない。 形状のみの検証の下では正しく見えるがアップストリームを完全にスキップするアダプターは、これまでに一度ならずステージングに出荷されています。よくある形:
  • 入力が非仕様分岐に一致しないとき、ハンドラーがアップストリーム呼び出しの前に短絡する(例: sync_audiences の空 members[] → 形状的に有効な空レスポンスを返し、決して POST しない)。
  • OAuth クライアントは配線されているがどのハンドラーからも呼ばれない。ツリーシェイキングは void fetchUpstreamToken; リテラルで無効化されている。
  • アップストリームの必須フィールドスキーマを満たすため合成プレースホルダーデータが注入され、実データの形状不一致を隠す。
アップストリーム上のトラフィックカウンターは、最初の 2 ケースを無条件に捕捉し、ストーリーボードが該当するペイロードの多様性を行使する場合に 3 番目のケースを捕捉します。これを CI に プレステージングゲート として配置してください: 安価、決定的、既存のステージングテストを置き換えるのではなく補完します。

利用可能なもの

リファレンス TS 実装(@adcp/sdk)は、異なるアップストリーム表面形状をカバーする 4 つの mock-server 専門分野を出荷します。これらは網羅的ではありません — 代表的な認証/テナンシー/ペイロードパターンを行使するために存在し、他の専門分野は最も近い一致を再利用します。 認証の形とテナンシーパターンは現実的です。アダプターが受け取る具体的なアカウントフィールド名(例: account.advertiseraccount.operator)は、AdCP リクエストをアップストリームテナントにバインドするための SDK 規約であり、規範的な AdCP 用語ではありません。正準マッピングについては @adcp/sdk ソースを参照してください。 各モックは以下を公開します:
  • アップストリームのドメインエンドポイント — 実プラットフォームの公開コントラクトに一致するよう形作られている。
  • GET /_lookup/<resource>?<adcp_field>=<value> — AdCP 側の識別子からアップストリームテナント ID へのランタイム解決。ハーネス規約。
  • GET /_debug/traffic<METHOD> <route-template> でキーされたヒットカウンター、認証なし、ハーネス専用。ハーネス規約。 ストーリーボード実行後に読み、各主要ルートが少なくとも 1 回ヒットしたことをアサートする。
各モックの OpenAPI 仕様は SDK パッケージの一部として出荷されます。アダプターを特定のシードデータではなく仕様に対して参照してください — シードは変動し、コントラクトの一部ではありません。

CI 統合

GitHub Actions ジョブのリファレンス形状、言語非依存:
しきい値ガイダンス。 最小限有用なアサーションは主要ルートごとに ≥ 1 です — それはハンドラーがアップストリームに到達したことを証明します。より強いアサーション(ルートごとのカウント、個別ペイロード検証)はストーリーボードのペイロード期待をエンコードする必要があり、プレステージングゲートでは保守負担に値しません。ストーリーボードが 3 つのオーディエンスアップロードを行使する場合、custom_audience/upload へ 3 ヒットを期待してください。そうでない場合、引くべきレバーはストーリーボードのペイロードカバレッジであって、ゲートのしきい値ではありません。 複数の専門分野を主張するエージェントについては、専門分野ごとに CI ジョブを並列で 1 つ実行してください。各ジョブは自身の mock-server ポートペア(エージェント + アップストリーム)を得ます。ジョブは独立しています。

反復ループ

現実的には最初の実行では両方のゲートを通過しないでしょう。よくある形とデバッグ方法:
  • ストーリーボードが passing だが N エンドポイントでトラフィックゲートが失敗 — 典型的なファサード。それらのルートのハンドラーは短絡したか、ストーリーボードの入力によって行使されなかった。
  • カスケードスキップを伴うストーリーボード partial — 早期ステップ(get_productsget_signals)が、ランナーが状態を抽出するフィールドを欠いた形状的に有効なレスポンスを返した。下流ステップは unresolved context variables でスキップする。早期ステップのレスポンス形状を修正すればほとんどのカスケードスキップはクリアされる。
  • 単一ステップでストーリーボード failing + トラフィックゲートはクリーン — 通常は 1 行の形状バグ(誤ったフィールド名、欠けている必須フィールド、ステータス不一致)。ステップごとの details が JSON ポインターでフィールドを名指す。
  • トラフィックゲートが空(どこでも 0 ヒット)+ エージェントが起動しているように見える — エージェントのブートがポートでリッスンした後に回復可能なエラーをスローした。エージェントの stderr を確認する。
最速のデバッグループ: npx @adcp/sdk@latest storyboard step <agent> <storyboard_id> <step_id> を使って失敗ステップを分離する。カスケードをスキップし、単一のツール呼び出しを実行し、サブ秒のフィードバック。分離したステップが通過するまで完全なストーリーボードを実行しないでください — 反復ごとに数分節約できます。

制限

これらのゲートが何を捕捉し何を捕捉しないかについて、チームに正直であってください:

ストーリーボードの制限

  • ストーリーボードはペイロードの多様性をアンダーカバーする。 ストーリーボードステップは、実際のアダプターが決して行使されない空入力で形状を通過するかもしれない — 重要なバリアントで。adcontextprotocol/adcp#3785 で追跡。

ランナー / ツーリングの注意点

  • ストーリーボードは黙ってカスケードスキップする — 早期ステップのレスポンスが形状的に有効だがランナーが状態を抽出するフィールドを欠くとき。表示されるエラーは 下流 ステップにあり、早期ステップではありません — “failed” の前に “skipped” ステップを調査してください。adcontextprotocol/adcp#3796(ランナー側)で追跡。
  • モックシードデータがストーリーボードフィクスチャ入力に一致しないかもしれない。 _lookup/<resource> で 404 が見えたら、ストーリーボードのペイロードはモックがシードしない ID を参照しているかもしれません。モックのシードを広げるか、コンプライアンステストコントローラー 経由でランタイムにシナリオ状態をシードしてください。

トラフィックゲートの制限

  • 必要だが十分ではない。 ハンドラーは合成プレースホルダーデータでアップストリームを呼び、なおヒットカウントアサーションを満たしうる。規制されたチャネル(オーディエンスアップロード、コンバージョントラッキング、署名付きリクエスト)のエージェントについては、本番前に実アップストリームのペイロード検証に対する追加の統合テストが依然として必要です。
  • 冪等性リプレイはトラフィックカウンターで行使されない。 idempotency_key を無視しアップストリーム書き込みを二重化するファサードはヒットカウントゲートを通過します。プラットフォームが at-most-once セマンティクスを持つ場合、ストーリーボードの冪等性リプレイシナリオ + 別のカウンターチェック(同じ idempotency_key → 同じヒットカウント)を使ってください。
  • アウトバウンド webhook 配信はアップストリームトラフィックカウンターで行使されない。 トラフィックカウンターはエージェントが呼び 込む アップストリーム上に存在します。エージェント → バイヤー webhook の署名/配信は、ストーリーボードランナーの --webhook-receiver フラグで別途グレードされます。webhook を発行するアダプターには両方のゲートが適用されます。

次は何か