なぜ今エージェント操作のCI検証が必要なのか:単体テストと単発試行の限界
通常のAPI単体テストでは、個々のAPIの入出力を検証できます。一方、仕様が直接示しているのはモデルが文脈に応じてツールを選択することであり[1]、API単体テストではその選択まで保証できないという点は本文からの推論となるため、ツール選択の評価はAPI単体テストとは別に行う必要があります。
AIエージェントによるツール利用は、モデルが呼び出しを提案し、アプリケーションが実行結果を返し、それを受けてモデルが後続の思考や呼び出しを続けるという、複数回のやり取りで進みます。出典資料が直接示しているのはツール利用の往復とトレースの範囲であり[2]、そこから導くテスト設計上の推論として、単一のAPI応答を検査するだけでは後続の判断や最終回答を含むワークフロー全体を評価できないと考えられます。
OpenAIのエージェント評価ガイドでは、まず単一実行のトレースを使い、モデル呼び出し、ツール呼び出し、ガードレール、引き継ぎ(ハンドオフ)を含むワークフローを詳しく調べて、挙動の良否を把握する手順が案内されています[4, 5]。個別のトレースを使ったデバッグを経て挙動を理解した後は、プロンプト、モデル、ツールの変更による影響を比較し、継続的に評価する段階へ進みます。そのために、再利用可能なデータセットと評価実行へ移行することが推奨されています[3, 4, 5]。
後輩APIの単体テストが通っていて、手元のトレースで1回動いたなら問題ないようにも思えますが、なぜCIで継続評価する仕組みへ切り替える必要があるのでしょうか。
先輩単体テストは各APIが動くかを見ているだけで、文脈に応じたツールの選択や往復の連鎖までは確認できないよ。それに、たった1回のトレースで動いても、プロンプトやツールの微修正でエージェントの振る舞いが変わることがあるから、同じデータセットで継続して比較する仕組みが必要になるんだね。
後輩単一APIの動作確認と、エージェントが文脈に合わせて正しく操作を完結できるかの検証は、別個のテストレイヤーとして捉えるべきなんですね。
CATTの判定アーキテクチャ:エージェントの自己申告に依存しない状態検証
CATT(Consumer Agent Testing Tool)は、スクリプトシナリオやモデル駆動シナリオを実行し、アシスタントがMCPサーバ、MCPアプリ、Webサイト、HTTP APIをどのように利用するかを検証できるテストツールです[6]。
補足:テストオラクルとは
テスト対象の出力や振る舞いが正しいかどうかを、テスト対象とは独立して客観的に判断するための基準や仕組みです。
エージェントの検証では、CATTはエージェント自身の回答とは独立したテスト契約に基づいて成否を判定します。具体的には、サービス側のオラクルや、宣言された読み取りツールを使って実際の状態を確認します[7, 8]。シナリオで必須とされたサービス側の結果確認や回答チェックが通ることを合格の根拠とし、失敗、セットアップやテストハーネスのエラー、ブロック状態を明確に区別します[9]。そのため、エージェントが完了を自己申告しても、実際の状態確認が通らなければ操作成功とは判定されません[9]。
例えばCATTの検証例では、実行完了後にフィクスチャの非公開オラクルを照会し、「確定した予約が1件存在すること」や「重複請求が発生していないこと」を確認します。また、読み取りツールのget_bookingを使って予約ステータスを取得します[10]。さらに、最終回答に虚偽の主張が含まれていないか、合計金額や予約確認情報などの必須情報が正しく伝えられているかを個別に検査します[8, 10]。
また、MCP(Model Context Protocol)の仕様では、人間がツールの呼び出しを拒否できる設計(Human-in-the-loop)が推奨されています[11, 12]。CATTはこの仕様に対応しており、送信された各呼び出しが承認カード(approval card)と一致するか(approval.dispatches_match)、開示内容の拘束条件を満たすか(approval.disclosure_bound)を検証条件に設定できます[10, 12]。承認の要否や許可条件をモデルに委ねず、ホスト側のテスト条件として固定します。その上で、拒否されたケースや呼び出し内容が変更された場合の再承認チェックを実施し、承認済みの経路だけに偏ったテストによる見落としを防ぐ方法が推奨されています[11, 13]。
スクリプト駆動とモデル駆動:検証目的に応じた2つの実行経路
CATTは、検証の目的に応じて異なる実行方式を提供しています。CI環境では、スクリプト化したコネクタ例を実行し、サービス結果の回帰を安定して検出する経路が整備されています[14]。
スクリプト駆動の実行(scripted connector-run)では、記録済みの呼び出し列を毎回そのまま再生します。モデル推論を伴わないため、同一のAPIやMCP経路に対する回帰、サービス状態の遷移、承認条件との整合性を決定論的かつ高速に検証できます。一方、モデルが文脈から自律的にツール経路を選ぶ能力は測定しません[15, 17]。
モデル駆動の実行(model-driven connector-run)では、シナリオの許可リストに登録されたツール群をネイティブ関数としてエージェントに提示します。ホスト側が管理するメールアドレスなどの秘密値はスキーマから除外し、それ以外の引数はモデルが自律的に作成します。これにより、ツール選択の妥当性と引数生成の精度を直接評価できます[16, 17, 19]。
| 実行方式 | モデル推論の要否 | 主な検証対象 | 検証範囲の限界 |
|---|---|---|---|
| スクリプト駆動(scripted connector-run) | 不要 | 記録済み呼び出し列の再生、API/MCP経路の回帰、サービス状態、承認条件 | モデルによる自律的なツール選択や引数生成能力は測定しない[15, 17] |
| モデル駆動(model-driven connector-run) | 必要(有料推論) | 許可リスト内のツール選択、非公開値を除く引数生成の妥当性 | 推論コストが発生し、サーバー状態や再現条件の管理が必要[16, 17] |
| surface-run(MCP Apps向け) | 不要(事前定義選択) | 事前定義されたステップ(アクションメニュー)の進行 | 自由なツール探索やスキーマ理解、未加工結果の解釈は示さない[18, 19] |
| readiness check | 不要 | ツール一覧およびスキーマの定義確認 | ツール呼び出しを行わないため、実行時の引数検証や実挙動は証明しない[20, 21] |
MCP Apps向けの検証方式「surface-run」では、エージェントドライバーがシナリオにあらかじめ記述されたアクションメニュー(スクリプト化されたステップ)から選択します。そのため、サーバのツール一覧やスキーマ、未加工の実行結果をもとにした自由なツール探索やスキーマ理解を評価するものではありません[18, 19]。
ツールカタログの準備状況を調べる「readiness check」は、ツール一覧やスキーマ定義の確認に適していますが、ツール自体は呼び出しません。そのため、実行時の引数バリデーションやサービスの実行時挙動は保証せず、操作結果はサービス側のオラクルを伴うシナリオ実行で確認する必要があります[20, 21]。なお、HTTP APIをテスト対象とするレーンでは、マッピング定義に加えてループバック展開とプライベートコントロールアダプターが必要とされています[21]。
CI統合によって開発サイクルはどう変わるか:継続的な回帰検出とサービス契約の確立
CATTが提示するCI運用パターンでは、検証目的と実行コストに応じて多層的なパイプラインを構築します。プルリクエストの段階では、高速で決定論的なスクリプト呼び出しとreadiness reviewを実行します。一方、モデルAPIキーが必要で有料推論を伴うモデル駆動の試行は、夜間バッチやオンデマンド実行に分けて運用します[22]。
このCIパイプラインで回帰検知の中核を担うのが、「封印された実行記録(sealed run)」をdiffコマンドで比較する仕組みです。CATTは実行結果を封印された記録として保存し、ビルド間で比較してサービス結果の回帰を検出します。回帰を検知すると、終了コード1でプロセスを終了します[14, 23]。なお、パッケージソースの変更は実行ロック(run-lock)の変更とみなされるため、同一チェックアウトから作成した実行同士を比較する必要があります[23]。
先行研究のThinkingBoxは、隔離されたMCPセッションとバックエンドの最終状態を対象に、ステートフルなエージェント作業を評価するサンドボックスとベンチマークを提示しました。CATTは、MCPやAPIの開発チームがこうした検証をプルリクエストや定期CIに組み込み、記録した結果をビルド間で継続的に差分比較するための実務的な道筋を示しています[24]。
CATTを導入するチームにとって実務上の転換点は、APIスキーマテストや単発のエージェント実行を品質ゲートとしていた方式から、コネクタへの期待値を「実行可能なサービス契約」として定義し、継続検証する運用へ移ることです。この契約には、許可ツール、非公開引数、承認条件、バックエンドの結果判定、回答チェックなどを含めます[25]。
後輩プルリクエストごとにモデルを呼び出すのではなく、スクリプト再生とモデル試行を分離するのは、テストの実行時間やコストを抑える上で現実的ですね。
先輩その通りだね。PRでは決定論的なスクリプトでAPIや承認の回帰を素早く検出し、モデルの自律的な選択挙動は夜間やオンデマンドでじっくり確認するという使い分けが合理的だよ。
後輩単にスキーマの整合性を確認するだけでなく、バックエンドの実行結果まで契約としてCIで担保できるなら、ツールの改修時にも自信を持ってリリースできそうです。
実務導入において誰にどのような影響があるか:状態管理・コスト・互換性の境界線
CATTを実務に導入・運用する際は、サーバの状態管理、推論コスト、再現性の限界、セキュリティ境界を適切に把握する必要があります。
まず、テスト間の状態管理について、シナリオにreset URLが宣言されていない場合、CATTは反復試行間でサーバ状態が共有されると警告します[26, 27]。前回の状態が次の試行に残ると、モデルの判断変化による影響と、前回実行の副作用による影響を区別しにくくなります[28]。そのため、反復試行の結果を比較する際は、各試行の開始状態を揃えるか、状態を独立して確認できる試験条件を用意する必要があります[26, 27, 29]。
観測指標のpass^k(反復試行での合格率要約)にも注意が必要です。合否が揺れた場合、筆者の調査観点としてモデルの確率的出力、共有されたサーバ状態、ネットワーク要因、ハーネスの不具合などが挙げられますが、この指標だけでは原因を特定できないことがあります。そのため、原因調査の際には要因を切り分けるとよいでしょう。
コスト面では、スクリプト実行はモデル呼び出しなしで動作する一方、モデル駆動の試行には有料推論が伴います。反復試行数やシナリオごとのリクエスト回数に応じた利用料を見込む必要があります[29, 30]。また、再現性については、Meta Model APIのResponsesアダプターのように、接続先でseedパラメーターがサポートされず、CATTがgeneration.seedを拒否する経路があります。この経路では、固定seedによる再現性を前提にできません[31]。さらに、CATTに記録されるモデルプロファイルのsupportラベル(specified/unverifiedなど)は宣言であり、各実行で再検証されるわけではありません[32]。
外部副作用とセキュリティについて、シナリオのtest_onlyフラグが記録するのはテスト作成者の意図であり、サービス側を物理的に隔離する機能はありません。未知のsettlement(確定処理)に遭遇すると試行は停止します。そのため、実サービスへの書き込みを伴う試験では、サービス側のサンドボックスや検証用アカウントを使い、状態を確認せずに安易に再試行しない運用が求められます[33]。また、CATTのexportコマンドは認証情報、登録済みシークレット、連絡先をマスキング(redact)しますが、中断再開用のチェックポイントファイルには認証情報やツール結果、ホスト入力が含まれることがあります。そのため、結果を共有する際はexportを使い、実行フォルダー全体は非公開に保つよう案内されています[34]。
最後に、検証結果の解釈には境界があります。CATTの記録済みリリースエビデンスはmacOSを対象としており、READMEではLinux環境の一部機能が未認定(未qualification)とされています。そのため、合格結果には実行環境やOSを併記し、別の環境へそのまま一般化しないことが適切と説明されています[35]。加えて、CATTが提供するMuseやInstinctなどの環境は、アシスタントのホストを近似するサロゲートです。実ホストの非公開実装を再現したものでも、実ホストとの校正を経たものでもありません[36, 37]。したがって、CATTでのテスト合格が示すのは、設定したシナリオとサロゲートホスト環境下での振る舞いです。Museなどの商用ホスト型アシスタントとの互換性や採用を証明するものではないと明記されています[36, 37, 38]。



