モデルフォールバックは1つの振る舞いではない。さまざまな安全制約を持つ、回復のための意思決定の集合である。
本番環境のモデルフォールバック戦略は、次の3つのワークフローを分けるべきである。
- 要求を再実行してもまだ安全な場合の再試行、または同等のフェイルオーバー。
- 別のモデルが同じ能力と品質契約を満たせる場合のクロスモデルフォールバック。
- 出力がすでにユーザーに届いている、またはツールの副作用が発生した可能性がある場合の停止、整合性確認、またはエスカレーション。
この分離が重要なのは、最も速い回復アクションが常に最も安全とは限らないからだ。失敗した分類リクエストを再実行するのは通常リスクが低い。しかし、ストリーミング応答の途中や、結果が不確かな支払いツール呼び出しの後で、モデルを黙って切り替えるのはそうではない。
このプレイブックは、フォールバック方針を、チームが実装・テスト・観測・リリースできる3つの運用ワークフローへと変換し、制御された本番ロールアウトを通じて展開できるようにする。
The model fallback decision in one table
プロバイダー名ではなく、リクエストの状態から始める。
| Request state | Preferred workflow | Typical action | Do not do |
|---|---|---|---|
| No response bytes, transient transport error | Workflow 1 | Bounded retry, then equivalent endpoint failover | Retry without a deadline or budget |
| No response bytes, rate limit or overload | Workflow 1 | Honor retry guidance, apply jitter, then move to equivalent capacity | Create a synchronized retry storm |
| Primary target unavailable, compatible model exists | Workflow 2 | Check the fallback contract, then route to the approved alternate | Assume every model supports the same tools, schema, or context |
| Structured response fails validation | Workflow 2 | Repair once or try an approved model that meets the schema contract | Treat HTTP 200 as task success |
| Partial stream already delivered | Workflow 3 | Stop, mark partial, offer an explicit restart | Splice a second model into the same answer invisibly |
| Write-side tool may have executed | Workflow 3 | Reconcile tool state using an idempotency record | Replay the entire model-and-tool workflow automatically |
| Safety or policy classification is uncertain | Workflow 3 | Escalate or fail closed according to product policy | Lower the safety bar to preserve availability |
基本ルールはシンプルだ。再試行は対象を維持し、同等のフェイルオーバーはモデル契約を維持し、クロスモデルフォールバックは契約リスクを変える。各ステップには、より強い適格性チェックが必要である。
サーキットブレーカー、エラーの正規化、プロバイダーニュートラルなコントローラーについてさらに詳しくは、LLM API fallback routing playbookを参照。
Before the workflows: define one fallback envelope
すべてのリクエストは、制限付きのエンベロープを持ってルーティング層に入るべきである。このエンベロープは、リクエストを停止しなければならないまでに、システムがどれだけの回復を許可されるかを示す。
type FallbackEnvelope = {
requestId: string;
deadlineMs: number;
maxAttempts: number;
maxAddedLatencyMs: number;
maxCostUsd?: number;
allowEquivalentFailover: boolean;
allowCrossModelFallback: boolean;
allowAfterPartialOutput: false;
sideEffectMode: "none" | "read_only" | "write_possible";
requiredCapabilities: string[];
requiredSchemaVersion?: string;
};
これらの値は、グローバルなデフォルトではなくプロダクトのワークフローから取得するべきです。バックグラウンドの要約ジョブは、対話型のコーディングアシスタントよりも多くのレイテンシを許容できます。ツールを使わないチャット回答は、コードをデプロイしたりメールを送信したりできるエージェントとは異なる復旧動作を許容できます。
このエンベロープは、ネストした再試行も防ぎます。SDK、アプリケーション、ゲートウェイ、プロバイダーアダプターがそれぞれ独立して再試行すると、小さな障害が大きな試行バーストに膨らむ可能性があります。総試行予算をどのレイヤーが管理するかを1つ決め、下位レイヤーには既に消費した分をすべて報告させるようにします。
フォールバックエンベロープをポリシー as コードにする
型定義は意図を文書化しますが、本番のルーティングには、アプリケーションコードを変更せずに運用担当者がレビューできるバージョン付きポリシーが必要です。ポリシーは監査できる程度に小さく保ち、汎用的なフォールバックチェーンが高リスクのワークフローに入り込まないよう、十分に具体的にします。
このスターター構成では、よくある3つのルートクラスを分離しています。
policy_version: 2026-08-02
routes:
interactive_chat:
deadline_ms: 12000
max_attempts: 2
max_added_latency_ms: 2500
allow_equivalent_failover: true
allow_cross_model_fallback: true
allow_after_partial_output: false
side_effect_mode: none
required_capabilities: [streaming]
structured_extraction:
deadline_ms: 30000
max_attempts: 3
max_added_latency_ms: 8000
allow_equivalent_failover: true
allow_cross_model_fallback: true
allow_after_partial_output: false
side_effect_mode: none
required_capabilities: [structured_output]
required_schema_version: invoice-v4
tool_agent_write:
deadline_ms: 45000
max_attempts: 2
max_added_latency_ms: 5000
allow_equivalent_failover: true
allow_cross_model_fallback: false
allow_after_partial_output: false
side_effect_mode: write_possible
required_capabilities: [tool_use]
上記の値は例であり、普遍的な閾値ではありません。ユーザー向けのレイテンシ目標、タスクの経済性、評価結果、そして副作用リスクに基づいて設定してください。重要な設計上の選択は、書き込み可能なエージェントが、動作の異なるモデルへ黙って切り替えられないようにすることです。
実行時には、ルーターはポリシーをリクエスト状態および観測された失敗状態と組み合わせる必要があります。簡潔な判定関数があれば、その境界をテスト可能にできます。
type RecoveryAction =
| "retry_same_target"
| "failover_equivalent"
| "fallback_approved_model"
| "reconcile_side_effect"
| "restart_required"
| "stop";
function chooseRecovery(input: {
errorClass: string;
attemptsUsed: number;
deadlineRemainingMs: number;
partialOutput: boolean;
sideEffectState: "none" | "safe" | "uncertain";
equivalentAvailable: boolean;
approvedAlternateAvailable: boolean;
policy: FallbackEnvelope;
}): RecoveryAction {
if (input.sideEffectState === "uncertain") return "reconcile_side_effect";
if (input.partialOutput) return "restart_required";
if (input.attemptsUsed >= input.policy.maxAttempts) return "stop";
if (input.deadlineRemainingMs <= 0) return "stop";
const transient = [
"transport_transient",
"rate_limited",
"provider_overloaded",
"provider_server_error",
].includes(input.errorClass);
if (transient && input.attemptsUsed === 0) return "retry_same_target";
if (transient && input.equivalentAvailable) return "failover_equivalent";
if (
input.policy.allowCrossModelFallback &&
input.approvedAlternateAvailable
) {
return "fallback_approved_model";
}
return "stop";
}
候補の選定は、回復の判断とは切り離しておいてください。chooseRecovery はどのワークフローを許可するかを決定し、その後に候補セレクターが能力、コンテキスト、リージョン、コスト、品質ポリシーでターゲットを絞り込みます。この分離により、チームは「回復ワークフローの選択を誤った」のか、「代替モデルの選択を誤った」のかを区別できるため、インシデントレビューが容易になります。
ポリシーはバージョン管理し、そのバージョンをすべての試行トレースに付与してください。フォールバックのリグレッションが発生した場合、運用担当者は、どのポリシーが判断したのか、どの候補が適格だったのか、そしてその時点でどの予算が残っていたのかを答えられる必要があります。
ワークフロー 1: 再試行、その後に同等経路へフェイルオーバー
このワークフローは、操作が再実行可能で、システムが部分出力を公開していない、または side effect の不確定な状態に入っていない場合に使用します。
同等ターゲットとは、重要な契約を維持する別経路のことです。つまり、同じモデルの動作クラス、必要な機能、スキーマ要件、安全設定、互換性のあるコンテキスト上限を満たします。リージョン、デプロイメント、プロバイダーのエンドポイント、容量プールが異なっていても構いません。
ステップ 1: 障害を正規化する
プロバイダー固有のレスポンスを、次の小さな内部分類にマッピングします:
transport_transientrate_limitedprovider_overloadedprovider_server_errorauthentication_or_permissioninvalid_requestdeadline_exhaustedcontract_failurepartial_outputside_effect_uncertain
通常、自動再実行の対象になるのは最初の 4 つだけです。認証、権限、不正なリクエストのエラーは、別のエンドポイントでリクエストが修復される可能性が低いため停止すべきです。契約違反はワークフロー 2 に属します。部分出力と不確定な side effect はワークフロー 3 に属します。
ステップ 2: 残りの予算を計算する
各試行の前に、次を確認してください:
remaining time > estimated next-attempt latency + response safety margin
remaining attempts > 0
remaining added latency > 0
remaining cost budget > estimated attempt cost, when a cost ceiling exists
必要な予算がいずれか枯渇している場合は、さらに別のプロバイダーを試すのではなく終了します。
ステップ 3: バックオフとジッターを使って再試行する
利用可能であれば、プロバイダーの再試行ガイダンスに従ってください。そうでない場合は、ジッター付きの指数バックオフを適用し、遅延をリクエストの期限内に収めます。
function retryDelayMs(attempt: number, retryAfterMs?: number): number {
if (retryAfterMs !== undefined) return retryAfterMs;
const base = Math.min(250 * 2 ** attempt, 4_000);
const jitter = Math.random() * base * 0.3;
return Math.round(base + jitter);
}
ジッターが重要なのは、多数の同時クライアントが同じスケジュールで再試行すると、過負荷事象を長引かせる可能性があるためです。あなたのLLM レート制限ガイドでは、RPM、TPM、キュー、同時実行、再試行予算がどのように相互作用するかを定義すべきです。
ステップ 4: 同等のキャパシティへ切り替える
同じターゲットの健全性が依然として回復しない場合は、次を確認したうえでのみ同等のエンドポイントへルーティングします:
- サーキットがクローズ、またはプローブ用にハーフオープンであること。
- ターゲットが必要な入力および出力モードをサポートしていること。
- ターゲットがコンテキスト上限内でリクエストを受け入れられること。
- ターゲットが想定された安全性およびデータ処理設定を使用していること。
- 試行がまだ期限とコスト枠内に収まること。
同等のフェイルオーバーは、応答契約の維持を目的とするため、通常はモデルを変更するよりもリスクが低いです。
ステップ 5: 回復理由を記録する
次のようなルート結果を返します:
{
"workflow": "retry_equivalent_failover",
"primary_attempts": 2,
"equivalent_failover_attempts": 1,
"recovered": true,
"recovery_reason": "provider_overloaded",
"added_latency_ms": 684
}
製品がその透明性を約束していない限り、内部のプロバイダー詳細をエンドユーザーに公開しないでください。ただし、トレースと運用ログには保持してください。
ワークフロー 2: 制御されたクロスモデル・フォールバック
クロスモデル・フォールバックは、代替モデルがそのタスクについて事前承認されている場合にのみ適切です。テキストを返すモデルであるだけでは不十分で、ワークフロー契約を満たす必要があります。
ステップ 1: 機能契約を作成する
各ルートクラスに対する譲れない要件を定義します。
{
"route_class": "support_ticket_triage_v3",
"required": {
"input": ["text"],
"output": ["json_schema"],
"tools": [],
"minimum_context_tokens": 24000,
"schema": "triage-result-v3",
"languages": ["en", "es", "de"],
"safety_profile": "customer-support-standard"
},
"fallback_models": [
"approved-model-b",
"approved-model-c"
]
}
ツールを使用するルートでは、ツール選択の挙動、並列ツールのサポート、引数スキーマの扱い、そしてモデルが「呼び出さない」条件を確実に遵守するかどうかを含めます。構造化出力については、各試行後に実際の応答をスキーマに照らして検証します。
Step 2: separate transport success from task success
HTTP の成功レスポンスであっても、製品ワークフローでは失敗することがあります。少なくとも 3 つの層で評価してください。
- Transport success: プロバイダーが完全な応答を返した。
- Contract success: 応答がパースされ、スキーマに一致し、サポートされているツールを正しく使用した。
- Task success: 出力が実際に、許容できる品質レベルでユーザーの作業を完了した。
この区別は、フォールバック候補を比較する際に不可欠です。応答率は高いが、スキーマやツールの失敗が頻発するモデルは、信頼できるフォールバックではありません。
Step 3: rank approved candidates by policy
本番ルーターは、あるモデルが普遍的に最適だと装うことなく、運用シグナルを使って適格な対象をスコアリングできます。
type Candidate = {
id: string;
capabilitiesPass: boolean;
circuitOpen: boolean;
estimatedLatencyMs: number;
estimatedCostUsd: number;
recentContractSuccess: number;
recentTaskSuccess: number;
};
function eligible(candidate: Candidate, envelope: FallbackEnvelope): boolean {
return (
candidate.capabilitiesPass &&
!candidate.circuitOpen &&
candidate.estimatedLatencyMs <= envelope.maxAddedLatencyMs &&
(envelope.maxCostUsd === undefined ||
candidate.estimatedCostUsd <= envelope.maxCostUsd)
);
}
すべてのタスクに対して静的な「primary, backup, backup」リストを使うのは避けてください。コード生成に最適なフォールバック集合は、抽出、翻訳、視覚、またはツール実行に最適な集合とは異なる場合があります。
Step 4: validate the fallback output
まず決定論的なチェックを適用します。
- JSON またはスキーマの検証
- 必須フィールドのチェック
- ツール引数の検証
- 引用または URL 形式のチェック
- 長さと言語の制約
- 禁止された出力パターン
その後、ワークフロー固有の品質チェックを追加します。これには、軽量ルール、タスク評価器、サンプリングした人手レビュー、または検証済みの judge モデルが含まれます。品質ゲートに失敗した場合、そのフォールバックを復旧したとは見なさないでください。
Step 5: canary policy changes
新しいフォールバックモデルを拡大適用する前に、次を実施します。
- オフライン評価セットを再実行する。
- ポリシーが許す場合はシャドウトラフィックを流す。
- 適格な失敗のごく一部で候補を有効化する。
- 契約成功、タスク成功、レイテンシ、コストを比較する。
- 復旧価値が回帰リスクを上回る場合にのみ拡大する。
これらの測定値は、各試行につき 1 つの route と 1 つの span を記録する LLM API observability スキーマで追跡します。
Workflow 3: stop, reconcile, or escalate
一部の失敗では、別のモデル呼び出しを行うべきではありません。正しいフォールバックは、制御された停止です。
Case 1: partial streaming output
応答トークンがユーザーに届いた後で、モデルを静かに切り替えると、矛盾、重複コンテンツ、壊れたコードブロック、または突然の文体変化を招く可能性があります。また、最終応答の帰属やデバッグも難しくなります。
代わりに、次のような明示的な結果のいずれかを使用してください:
- 回復可能なエラーと「再試行」アクションでストリームを終了する。
- 最初から回答を再開するよう提案する。
- アプリケーションに設計された再開プロトコルがあり、新しいモデルが受け取る prefix が厳密に受け入れ済みのものと一致する場合にのみ継続する。
デフォルトは allowAfterPartialOutput: false にすべきです。
ケース 2: ツールの副作用が不確実な場合
モデルが支払い、メール、デプロイ、チケット、またはデータベース書き込みツールを選択したとします。オーケストレーターが結果を記録する前に接続が失敗していても、ツールは成功していた可能性があります。ワークフロー全体を再実行すると、副作用が重複することがあります。
書き込み系ツールは次の方法で保護してください:
- プロバイダーの試行ではなく、ユーザー操作に基づく冪等キー。
planned、started、succeeded、failed、unknownの状態を持つ永続的な実行記録。- ツール境界での重複排除。
- 再実行の前に行う照合クエリ。
- 不確実性が残る影響の大きい操作に対する人間のレビュー。
type ToolExecution = {
operationId: string;
toolName: string;
state: "planned" | "started" | "succeeded" | "failed" | "unknown";
externalReference?: string;
};
function nextAction(execution: ToolExecution): "continue" | "reconcile" | "stop" {
if (execution.state === "succeeded") return "continue";
if (execution.state === "failed") return "stop";
return "reconcile";
}
プロバイダーの認証情報とツールの認証情報は分離してください。安全な API キー管理ガイドでは、関連するシークレットとアクセス制御のモデルを扱っています。
ケース 3: 安全性、権限、またはポリシーの不確実性
可用性は、安全性や認可の判断を弱めるべきではありません。フォールバック候補が必要なポリシー制御をサポートしていない場合、そのルートは利用不可です。システムが操作の許可可否を判断できない場合は、製品のリスクモデルに従ってクローズドに失敗するか、エスカレーションしてください。
ケース 4: 条件を満たす候補がない
アプリケーションが処理できる型付きの失敗を返します:
{
"status": "unavailable",
"reason": "no_eligible_fallback",
"retryable": true,
"retry_after_ms": 30000,
"request_id": "req_123"
}
明確に劣化した応答のほうが、スキーマに違反したり、誤ったツールを使ったり、誤った副作用を起こしたりする一見成功したような回答よりも優れています。
3つのワークフローを1つのステートマシンにまとめる
オーケストレーション層は、遷移を明示的にすべきです。
START
-> PRIMARY_ATTEMPT
-> SUCCESS: 検証して返却
-> TRANSIENT + replayable: WORKFLOW_1
-> CONTRACT_FAILURE + approved alternate: WORKFLOW_2
-> PARTIAL_OUTPUT or SIDE_EFFECT_UNCERTAIN: WORKFLOW_3
WORKFLOW_1
-> バジェット内で再試行
-> バジェット内で同等のフェイルオーバー
-> 互換性のある代替が許可されている場合: WORKFLOW_2
-> それ以外: STOP
WORKFLOW_2
-> 機能確認
-> 代替の試行
-> 契約とタスクの検証
-> 検証済みの成功時のみ返却
-> それ以外: STOP
WORKFLOW_3
-> 部分的または不確実な状態としてマーク
-> 可能であれば外部の副作用を整合
-> 明示的な再開または人間へのエスカレーションを提示
-> 危険な作業を黙って再実行しない
これは、マルチモデル・ゲートウェイにとっても適切な境界です。OpenAI互換のエンドポイントの背後にモデルアクセスを集約すると、統合の重複は減らせますが、それでもアプリケーションはワークフローの意図を提供する必要があります。たとえば、期限、副作用モード、必要なツール、スキーマのバージョン、そしてクロスモデルのフォールバックが許可されるかどうかです。Flatkeyは、モデルプロバイダーをまたいで1つのキーと1つの統合面を求めるチーム向けに、統一APIアクセス層を提供します。それでも最も安全なルーティングポリシーは、明示的なアプリケーション契約から始まります。
自動フォールバックを有効にする前に、5つの障害訓練を実施する
制御された障害を一度も扱ったことのないフォールバック経路は、単なる図にすぎません。安全境界の異なる各ルート種別を、失敗でテストしてください。
| 訓練 | 注入する条件 | 期待される動作 | 保持すべき証跡 |
|---|---|---|---|
| 1. プライマリのタイムアウト | プライマリを、試行ごとのタイムアウトを超えるまで遅延させる | 総期限と試行バジェットが残っている場合のみ再試行する | 試行のタイムスタンプ、前後のバジェット、最終ルート理由 |
| 2. レート制限のバースト | レート制限レスポンスを上限付きの系列で返す | ジッターを適用し、再試行ガイダンスを尊重し、同期再試行を避ける | バックオフ分布、キュー深度、回復件数と期限超過件数 |
| 3. 無効な構造化出力 | HTTP成功でスキーマ違反の本文を返す | 契約違反として扱い、承認済みのスキーマ対応代替のみを試し、再度検証する | 検証エラー、候補の適格性記録、受理済みタスクの結果 |
| 4. ストリーム中の切断 | ユーザーに見えるトークンの後で接続を終了する | ストリームを停止し、明示的な再開を要求する | 部分出力フラグ、ユーザー向け状態、サイレントな差し込みが発生していないことの確認 |
| 5. あいまいなツール結果 | 書き込み側ツールが実行された可能性がある後で応答を失わせる | いかなる再実行の前にも操作IDで整合する | 冪等性レコード、外部状態の照会、重複副作用件数 |
まずはローカルまたはステージング環境で訓練を行い、その後、範囲を絞った本番ゲームデーで実施してください。目的は、すべてのリクエストが生き残ることを証明することではありません。システムが意図した状態で失敗し、その事象を診断するのに十分な証跡を示し、ポリシーが許す以上の遅延、コスト、または副作用リスクを消費しないことを証明することです。
各訓練について、4つの層を個別に検証してください:
- 決定の正しさ: ルーターが意図したワークフローを選択した。
- 予算の正しさ: すべての試行が、共有された期限、試行回数、コストの枠内に収まっていた。
- 出力の正しさ: 最終結果が契約とタスクの検証に合格した、または明示的な劣化状態を返した。
- 監査の正しさ: トレースにポリシーのバージョン、失敗クラス、候補の適格性、ルートの理由、ユーザーに見える結果が記録されていた。
プロバイダーアダプター、リトライの責任者、モデル候補、スキーマのバージョン、ツール契約、またはストリーミング実装を変更したら、そのたびにこのドリルを繰り返してください。公開 API の形が変わっていないように見えても、こうした変更はリプレイの安全性を変える可能性があります。
本番前にフォールバック準備状況スコアカードを使う
自動フォールバックを有効にするには、いくつかのハッピーパステストに合格するだけでは不十分です。あるルートは、5つの独立したリリースゲートを通過してはじめて自動化の対象になります。
| ゲート | 合格条件 | 証拠 | 次の場合に自動フォールバックをブロック |
|---|---|---|---|
| リプレイの安全性 | 各試行の境界ごとに、リクエストを繰り返してよいかどうかをチームが証明できる | 副作用の分類、冪等性設計、部分出力ルール | 照合キーなしで書き込みが発生した可能性がある |
| 契約互換性 | すべての候補が、必要なコンテキスト、ツール、スキーマ、モダリティ、ポリシー制御をサポートしている | バージョン管理された機能マトリクスと契約テスト | モデルファミリーやマーケティング上のラベルから互換性が推測されている |
| タスク品質 | 代替案が、そのルートの実際のワークロードに対して許容可能な結果を出す | ルート固有の評価セットとレビュー済みの失敗ケース | トランスポート成功または一般的なベンチマークスコアしかない |
| 予算管理 | リトライとフォールバックが、1つの期限、試行上限、コスト上限を共有する | 予算消費を示す失敗ドリルのトレース | 複数の層が独立してリトライできる、または呼び出し元の期限を超えられる |
| 運用管理 | オンコールエンジニアがフォールバック決定を特定、無効化、説明できる | ポリシーバージョン、ルート理由、キルスイッチ、ダッシュボード、ランブック | 回復経路を、アプリケーションの完全なデプロイなしに切り離せない |
スコアカードはリリース成果物として扱ってください。ルートクラス、ポリシーバージョン、承認済み候補、評価器のバージョン、ドリル結果、担当者、レビュー日を記録します。単一のグローバルな「fallback enabled」フラグではリスクが大きく隠れます。承認はワークフロークラスごとに行うべきです。
コピペ可能な準備記録
fallback_readiness:
route_class: support_ticket_extraction
policy_version: fallback-v4
owner: ai-platform
primary_target: primary-model
approved_candidates:
- equivalent-deployment
- alternate-model
gates:
replay_safety: pass
contract_compatibility: pass
task_quality: pass
budget_control: pass
operational_control: pass
evidence:
capability_matrix: contracts/support-ticket-v3.yaml
evaluation_set: evals/support-ticket-2026-08.jsonl
failure_drill_run: drills/2026-08-03.json
dashboard: ai-routing/support-ticket
runbook: runbooks/support-ticket-fallback.md
release:
mode: canary
rollback_owner: oncall-ai-platform
next_review_at: 2026-09-03
このファイルは、この正確な形式である必要はありません。重要なのは、リリース判断がレビュー可能であり、本番トレースに記録された同じポリシーバージョンに紐づいていることです。
4つの段階でモデルフォールバック戦略を展開する
自動フォールバックは、オフラインテストからいきなりすべての本番リクエストに適用すべきではありません。ユーザーに見える前に判断ミスを露出させる4つの段階を使いましょう。
ステージ1: 判断をシャドーする
フォールバックコントローラーを監視専用モードで実行します。ユーザーへの応答は引き続きプライマリ経路が決定し、コントローラーは自分なら何をしたかを記録します。
確認する項目:
- どのくらいの頻度で、ポリシーが失敗を再試行可能と判定するか。
- どのくらいの頻度で候補が適格になるか。
- どの予算が復旧を止めてしまうか。
- 部分出力の後や副作用が不確かな場合に、ポリシーがフォールバックを提案するかどうか。
- プロバイダー正規化済みエラーが、インシデント診断に十分な詳細を保持しているかどうか。
シャドーモードは、たとえば「429ごとにフォールバックする」や「いかなるスキーマエラーの後も別モデルを試す」といった広すぎるルールを見つけるのに特に有用です。こうしたルールはコードレビューでは妥当に見えても、実際のリクエスト状態に対しては悪い挙動を示すことがあります。
ステージ2: リスクの低いワークフローでカナリア展開する
読み取り専用の分類、抽出、バックグラウンド要約など、リプレイ安全なトラフィックのごく一部にフォールバックを有効化します。書き込み側のツール、安全性に敏感な判断、ユーザーに見えるストリーミングを伴うルートは除外します。
ルートレベルの結果を使って、カナリアをプライマリのみの経路と比較します:
- HTTP成功だけでなく、受け入れられたタスク率。
- 復旧による追加レイテンシ。
- 受け入れられたタスクあたりのコスト差分。
- 候補ごとの契約検証失敗。
- 期限超過と、適格なフォールバックなしの比率。
- ユーザーによるキャンセルまたは明示的な再開率。
プロバイダーのエラー率が下がったからといって、カナリアを拡大しないでください。最終的なユーザー結果が許容範囲に収まり、復旧経路がその許容範囲内にとどまる場合にのみ拡大します。
ステージ3: リスククラスごとに自動復旧を制約する
準備完了スコアカードを通過したワークフロークラスだけを拡張します。ポリシーの違いは明示的に保ちます:
| リスク区分 | デフォルトの自動化 | 必要な安全策 |
|---|---|---|
| 読み取り専用、ストリーミング出力なし | 再試行、同等フェイルオーバー、承認済みのクロスモデルフォールバック | 契約とタスクの検証 |
| 読み取り専用、ストリーミング出力あり | 最初のユーザー可視バイトの前のみ復旧 | 部分出力の状態管理と明示的な再開 |
| 読み取り専用ツールを使うツール使用 | ツール実行前に再試行し、代替ツール契約を検証 | ツールスキーマとツール選択のテスト |
| 書き込みを伴うツール使用 | 曖昧な実行後は停止して整合性を確認 | 永続的な操作IDと外部状態の参照 |
| 安全性、権限、またはコンプライアンスの判断 | 製品の承認済みポリシーに従って失敗させる | 可用性を理由としたポリシーのダウングレードなし |
この段階では、ゲートウェイとアプリケーション契約が交わります。ゲートウェイはエラーを正規化し、予算を強制し、対象となるキャパシティを選択できます。アプリケーション側では、出力が外部に出たか、副作用が発生しうるか、どの品質チェックやポリシーチェックが必須かを、引き続き明示しなければなりません。
ステージ4: 徐々に拡大し、変更を再認定する
トラフィックを制限付きの段階で増やします。各段階で、ルーティング層全体を停止させることなく、1つのポリシーバージョン、1つのルートクラス、1つのプロバイダーアダプター、または1つの候補を無効化できる能力を維持します。
次のいずれかが変更されたら、関連するスコアカードのゲートを再実行します。
- モデルまたはモデルバージョン。
- プロバイダーアダプターまたはエンドポイント。
- プロンプトテンプレートまたはシステム指示。
- ツール定義または権限スコープ。
- 構造化出力スキーマ。
- 再試行の責任分担またはタイムアウト設定。
- ストリーミングトランスポートまたはクライアントの挙動。
- 安全性ポリシーまたは品質評価器。
フォールバックの準備状況は、その前提条件が変わると失効します。以前のプロンプト、スキーマ、またはツールセットで承認された候補は、慣性だけで自動的に適格なままにしてはいけません。
カナリアを有効化する前にロールバック条件を定義する
カナリアは、何がそれを停止させるかを事前にチームで合意している場合にのみ安全です。広範なインシデントを待つのではなく、ルート固有のトリガーを使います。
次のいずれかを観測したら、影響を受けるポリシーをロールバックまたは無効化します。
- 書き込み側の副作用が重複している、または不確実である。
- 許容できるタスク成功を伴わないクロスモデル契約の成功。
- 部分的なストリーム失敗や、見えないレスポンスのスプライシングの増加。
- 復旧試行によって引き起こされる締切超過の繰り返し。
- 予算上限が超過している、または無視されている。
- 必要な能力または安全性ポリシーに違反する候補選択。
- デプロイ後にフォールバック理由の分布が説明なく変化する。
- インシデント中にポリシーバージョンまたは試行レベルのトレースデータが欠落している。
ロールバックアクションは、失敗の範囲と同じくらい狭くあるべきです。事象によっては、1つの候補を無効化する、ルートを同等フェイルオーバーのみに固定する、allowCrossModelFallback を false に設定する、1つのプロバイダーに対して回路を開く、あるいはワークフローをプライマリのみモードに戻す、といった対応になります。
アプリケーションの再構築を必要とするロールバック機構は避けてください。インシデント発生時には復旧ポリシーが頻繁に変わり、最も安全な対応は、緊急のコードパッチではなく、監査可能なバージョンを伴う設定変更であることが多いです。
すべてのフォールバック事象に1つのインシデント・ワークシートを使う
各プロバイダーが異なるエラー形状を公開し、各アプリケーションが異なるリクエスト状態を記録していると、フォールバック・インシデントは診断が難しくなります。プロバイダー非依存のワークシートを1つ記録してください。
fallback_incident:
incident_id: inc-2026-08-03-001
route_class: support_ticket_extraction
request_id: req_123
policy_version: fallback-v4
request_state:
output_started: false
side_effect_mode: none
tool_execution_state: not_started
deadline_remaining_ms: 1820
attempts_remaining: 1
primary_failure:
normalized_class: overloaded
provider_status: 529
retry_guidance_present: true
recovery_decision:
workflow: cross_model_fallback
candidate: alternate-model
reason: equivalent_capacity_unavailable
validation:
transport_success: true
contract_success: true
task_success: false
failure_reason: required_field_omitted
user_outcome:
state: explicit_failure
partial_output: false
duplicate_side_effect: false
containment:
action: disable_candidate_for_route
owner: oncall-ai-platform
最も重要な区別は、復旧成功とユーザー成功の間にあります。フォールバック要求は有効な HTTP レスポンスを返しても、スキーマに失敗したり、誤ったツールを選択したり、必須の事実を省略したり、ルートの品質しきい値に違反したりすることがあります。インシデントレビューは、その結果を最終的にユーザーが見えるタスクまで追跡すべきです。
60分のモデルフォールバック・ゲームデイを実施する
単体テストは、個々の分岐が実行されることを証明します。フォールバック・ゲームデイは、期限、リトライ、ストリーム、検証、ツール、テレメトリー、オペレーター制御が相互作用する中で、復旧システム全体が正しく動作することを証明します。
演習は一度に1つのワークフロー・クラスに対して実施してください。グローバルなプロバイダー障害シミュレーションから始めてはいけません。読み取り専用抽出や内部要約のような狭いルートの方が、より明確な証拠を生み、ポリシーが誤っていた場合の影響範囲も限定できます。
ゲームデイ憲章を定義する
誰かが障害を注入する前に、1ページの憲章を書いてください。憲章は、この演習が即席の障害対応になってしまうのを防ぎます。
game_day:
id: fallback-gd-2026-08-04-extraction
route_class: structured_extraction
policy_version: fallback-v4
environment: staging
exercise_owner: ai-platform
incident_commander: reliability
primary_target: primary-model
approved_fallbacks:
- equivalent-deployment
- alternate-schema-capable-model
traffic_scope:
synthetic_requests: 100
production_percentage: 0
safety_limits:
stop_after_minutes: 60
max_error_rate_percent: 5
max_duplicate_side_effects: 0
max_unexplained_route_decisions: 0
success_definition:
- every request ends accepted, explicitly degraded, or safely stopped
- no request exceeds the shared attempt budget
- no partial stream is silently continued by another model
- every fallback decision includes a policy version and route reason
まずは合成トラフィックまたはリプレイ安全なトラフィックを使用します。ルートが書き込みを引き起こす可能性がある場合は、ツールを制御されたテストダブルまたは、冪等性のルックアップをサポートするサンドボックスに置き換えます。ゲームデーは回復制御をテストすべきであり、顧客状態を危険にさらすべきではありません。
4つの役割を割り当てる
チームは迅速に意思決定できる程度に小さく保ちつつ、観察と実行は分離します。
| 役割 | 演習中の責務 | 行ってはならないこと |
|---|---|---|
| 演習リード | シナリオを開始し、タイムラインを管理し、停止条件を宣言する | 記録せずにシナリオ途中でフォールバックポリシーを変更する |
| オペレーター | ルートの健全性を監視し、候補を無効化し、キルスイッチを使用する | 障害を注入したり、証跡を編集したりする |
| オブザーバー | タイムスタンプ、スクリーンショット、トレース、ユーザーに見える結果を記録する | リクエストを手動で修正してルーターを「合格」させる手助けをする |
| アプリケーションオーナー | タスク品質とワークフロー固有の劣化を評価する | HTTPの成功だけを根拠に結果を承認する |
非常に小規模なチームでは1人が2つの役割を兼ねることもできますが、障害を注入する担当者が、そのシステムが正しく応答したかどうかを唯一評価する人であってはなりません。
シナリオの階段を構築する
最も曖昧さの少ない障害から始め、ルートが前の段を通過してから次のリスクを追加します。
| 段 | 注入 | ルーターが証明すべきこと | 昇格条件 |
|---|---|---|---|
| 1. クリーンな同等フェイルオーバー | 応答バイトが返る前にプライマリエンドポイントを利用不可にする | アプリケーション契約を変えずに同等のキャパシティへ移行できる | 受け入れ可能な結果、1つのルート理由、共有バジェットの順守 |
| 2. リトライ圧力 | リトライ可能なエラーを制限付きで短時間集中して返す | バックオフとジッターが試行回数の増幅なしに機能する | ネストしたリトライ増幅がないこと; デッドラインが依然として権威を持つ |
| 3. セマンティックな契約失敗 | 通信としては成功だが、構造化結果が無効な応答を返す | ステータスコードではなく検証が受け入れを制御する | 代替先が適格であり、その結果が同じバリデーターを通過する |
| 4. 部分ストリーム | 可視出力の後に切断する | システムが停止し、回答を部分的としてマークする | サイレントなモデルの差し込みはない; 再開は明示的である |
| 5. 不確実なツール完了 | 書き込みが実行された可能性がある後にモデル応答を失う | ワークフローがリプレイ前に外部状態を照合する | Operation IDの検索が完了する; 重複書き込みはゼロのまま |
| 6. フォールバックの劣化 | 承認済みの代替先をより遅く、または品質を低くする | ストップロスとロールバックのルールが可用性圧力より優先される | 候補が削除される、または事前定義のしきい値で自動化が無効化される |
複雑なマルチモデルシナリオへ直接飛ばしてはいけません。同等フェイルオーバーでバジェットとトレースの契約を維持できないなら、挙動の異なるモデルを追加しても診断はより難しくなるだけで、より現実的にはなりません。
明示的な境界で障害を注入する
障害がリクエストのライフサイクルのどの境界で入るのかを正確にラベル付けします。「プロバイダーが失敗した」では、役立つテスト記録としては曖昧すぎます。
type InjectionPoint =
| "before_connect"
| "after_connect_before_headers"
| "after_headers_before_body"
| "after_partial_stream"
| "after_tool_dispatch_before_ack"
| "after_tool_ack_before_model_response"
| "after_transport_success_before_validation";
境界によって、どの復旧アクションが安全かが決まります。接続前のタイムアウトは、多くの場合リトライできます。ユーザーが出力を見た後の切断には、明示的な再開が必要です。書き込み側のツール呼び出しの後に確認応答が失われた場合は、整合性の回復が必要です。この3つをすべて同じタイムアウト分類として扱うと、重複アクションと一貫性のない応答が本番環境に入り込みます。
フォールトインジェクション層がそれらの境界を狙えない場合は、演習の前に、その境界マーカーをプロバイダーアダプターまたはオーケストレーション層に追加してください。粗い失敗トグルは可用性テストには有用ですが、リプレイ安全性テストには不十分です。
リクエストごとに1つの証跡行を記録する
ゲームデイは、ダッシュボードのスクリーンショットだけでなく、リクエストレベルの台帳を生成すべきです。簡潔な1行が、説明のつかない判断を可視化します。
| Field | Example | Why it matters |
|---|---|---|
request_id |
req_01J... |
ゲートウェイ、モデル、バリデーター、ツールの証跡を結び付ける |
scenario_id |
partial-stream-01 |
結果を注入された条件に結び付ける |
policy_version |
fallback-v4 |
どのルーティングルールが判断したかを証明する |
failure_class |
stream_interrupted |
トランスポート、契約、ポリシー、ツールの不確実性を分ける |
injection_point |
after_partial_stream |
リプレイ安全性を確立する |
attempts_used |
1/2 |
リトライ増幅を検出する |
elapsed_ms |
4830/12000 |
残りのデッドライン予算を示す |
cost_budget_state |
within |
復旧がユニットエコノミクスを無視するのを防ぐ |
selected_action |
restart_required |
ルーターの判断を記録する |
candidate_id |
none |
別のモデルが検討されたかどうかを示す |
validator_result |
not_run |
トランスポート復旧とタスク受理を分ける |
side_effect_state |
none |
整合性回復の要件を明示する |
user_outcome |
partial_marked |
顧客が体験したことを記録する |
operator_action |
none |
自動復旧と手動封じ込めを区別する |
台帳は、ポリシーのスナップショット、バリデーターのバージョン、障害設定、ダッシュボードのエクスポートと一緒に保存してください。これらのバージョンがなければ、合格した演習も、次のアダプターやモデルの変更後には再現できません。
昇格ルールで演習を採点する
次の3つのいずれかの निर्णयを使用します: promote、fix and rerun、またはstop automation。あいまいな「ほぼ通過」は避けてください。
次のすべてが真である場合にのみ、ルートをpromoteします:
- すべてのリクエストに、説明された終端状態がある。
- いかなる試行チェーンも、共有デッドライン、試行回数、または設定されたコスト上限を超えない。
- 受け入れられたすべての出力が、そのルートのバリデータまたは評価ルールに合格する。
- 部分的な出力と不確かな副作用は、明示的な停止または照合の状態に入る。
- オペレーターは、アプリケーションコードをデプロイせずに、1つの候補またはポリシー全体を無効化できる。
- アラートは、回復失敗と、有害な回復の両方を識別する。たとえば、許容できないタスク品質でのフォールバック成功など。
安全モデルは正しいが、証拠または実装が不完全な場合はfix and rerunを選びます。たとえば、ルート理由の欠落、発火が遅すぎるアラート、または契約には合格するがレイテンシ目標を満たさない候補などです。
演習で再生のあいまいさ、重複した副作用、黙ったストリームの分割、説明のないルーティング、ポリシーのバイパス、または現在の状態機械では表現できない障害モードが見つかった場合は、stop automationを選びます。それらはチューニングの問題ではなく、設計上の欠落です。
コピー可能なゲームデイ・スコアカードを使用する
game_day_result:
game_day_id: fallback-gd-2026-08-04-extraction
route_class: structured_extraction
policy_version: fallback-v4
evaluator_version: extraction-eval-v7
started_at: 2026-08-04T09:00:00Z
completed_at: 2026-08-04T10:00:00Z
scenarios:
equivalent_failover: pass
retry_pressure: pass
semantic_contract_failure: pass
partial_stream: pass
uncertain_tool_completion: not_applicable
fallback_degradation: fix
totals:
requests: 100
accepted: 94
explicitly_degraded: 6
unsafe_or_unexplained: 0
duplicate_side_effects: 0
deadline_violations: 0
decision: fix_and_rerun
blockers:
- alternate p95 latency exceeded the route objective during degradation
owner: ai-platform
rerun_due: 2026-08-11
サンプル値は例示です。自分のルート目標と評価しきい値を使用してください。重要なのは、最終判断が保持された証拠と、名前付きのオーナーを指し示していることです。
発見をリリース制御に変換する
ゲームデイは、すべての発見を次の4つの恒久的な制御のいずれかに変換して終えてください:
- Policy change: 候補の適格性、試行予算、デッドライン、またはルートクラスのルール。
- Contract test: 機能、スキーマ、ツール、ストリーミング、または安全性の互換性チェック。
- Operational control: アラート、ダッシュボード、キルスイッチ、候補の隔離、またはインシデント手順。
- Product behavior: 明示的な再起動、劣化状態メッセージ、手動確認、または照合画面。
観察事項の一覧で演習を終えないでください。オーナー、制御タイプ、および再実行条件のない発見は、実際のインシデントで再び現れます。
これらの演習の背後にあるテレメトリ層については、LLM API observability guideを使用してください。再試行の責任範囲とレート制限の挙動については、ゲームデイをLLM rate limits and retry strategyと組み合わせて実施してください。チームがまだゲートウェイ境界を定義している段階なら、まずLLM gateway beginner guideから始めてください。
7日間の実装シーケンス
チームはこの順序を使って、場当たり的なモデル一覧から制御されたワークフロー・プレイブックへ移行できます。
- 1日目 — ルートを棚卸しする: 出力モード、副作用リスク、ツール、スキーマ、期限、現在の再試行担当を分類する。
- 2日目 — エンベロープを定義する: ルートクラスごとに、試行回数、レイテンシー、コスト、機能、再実行の上限を設定する。
- 3日目 — 契約を構築する: 承認済み候補を文書化し、ツール、スキーマ、コンテキスト、モダリティ、ポリシーの互換性をテストする。
- 4日目 — 意思決定を計測可能にする: 正規化された失敗、リクエスト状態、ポリシーバージョン、候補の適格性、予算、検証、ユーザー結果を記録する。
- 5日目 — 障害ドリルを実施する: タイムアウト、レート制限バースト、無効な出力、ストリーム途中の切断、あいまいなツール実行を注入する。
- 6日目 — シャドーとカナリアを行う: まず意思決定を観察し、その後、事前定義したロールバックトリガー付きで、低リスクの限定ルートを有効化する。
- 7日目 — 振り返って拡張する: 受理タスク率、追加レイテンシー、コスト差分、安全でない再実行シグナル、候補不在のフォールバックイベントを確認してから拡大する。
このシーケンスは意図的にワークフロー起点です。モデルのランク付けリストを選ぶことは小さな一歩にすぎません。本番で重要なのは、いつシステムが継続できるのか、いつ検証しなければならないのか、そしていつ停止しなければならないのかを証明することです。
モデルフォールバック戦略の展開チェックリスト
ポリシー
- すべてのルートクラスにフォールバックのエンベロープがある。
- フォールバックポリシーはバージョン管理され、設定としてレビュー可能である。
- 再試行可能なエラーはプロバイダー間で正規化されている。
- 総再試行予算には1人の責任者がいる。
- 同等のエンドポイントは代替モデルと区別されている。
- モデル横断の候補にはバージョン管理された機能契約がある。
- 部分出力はデフォルトで透過的なフォールバックを無効にする。
- 書き込み側のツールは永続的な冪等性レコードを使用する。
検証
- 転送、契約、タスク成功は個別に計測される。
- 構造化出力はフォールバック後に検証される。
- ツール引数とツール選択の挙動はモデルごとにテストされる。
- フォールバック評価セットは実際のルートクラスを表している。
- 新しい候補はオフライン評価と本番カナリアを通過する。
- 適用対象となる各ルートクラスで、5つの障害ドリルすべてに合格する。
運用
- 各試行では、ルート理由、対象、レイテンシー、結果を記録します。
- ダッシュボードでは、プライマリ、リトライ、同等フェイルオーバー、クロスモデル復旧を個別に表示します。
- アラートには、期限超過とフォールバック候補なし率を含めます。
- サーキットブレーカーは制御されたハーフオープンプローブを使用します。
- インシデントレビューには、ユーザーに見える品質と重複副作用リスクを含めます。
- すべての試行トレースには、アクティブなフォールバックポリシーのバージョンを記録します。
- 各ルートには、完了済みの準備状況スコアカードと、指名されたオーナーがあります。
- カナリアロールバックのトリガーと、範囲の狭いキルスイッチをテストします。
- インシデント用ワークシートには、リクエスト状態、検証、ユーザー結果を記録します。
フォールバックが役立っていることを示す指標
プロバイダーのエラー率だけを最適化しないでください。ユーザーの結果を追跡します。
| 指標 | 答える質問 |
|---|---|
| リトライ回復率 | 同一対象への再試行は、そのレイテンシーに見合う価値があるか? |
| 同等フェイルオーバー回復率 | 冗長キャパシティは安全にサービスを復旧できるか? |
| クロスモデル契約成功率 | 代替応答は必要なインターフェースを満たしているか? |
| クロスモデルタスク成功率 | ユーザーは意図した作業を引き続き完了できるか? |
| 追加フォールバックレイテンシー | 復旧によってどれだけ遅延が増えるか? |
| フォールバックコスト差分 | 復旧経路のコストはいくらか? |
| 部分ストリーム失敗率 | システムが回復不能な表示状態に到達する頻度はどれくらいか? |
| 副作用整合率 | 継続前に外部状態を検証しなければならない頻度はどれくらいか? |
| 重複副作用インシデント | 再実行保護は失敗したか? |
| フォールバック候補なし率 | ルート契約が厳しすぎるのか、それともキャパシティが不足しているのか? |
これらの指標はルートクラス別に分けてください。集計した回復率だけでは、抽出ではフォールバックがうまく機能していても、コード生成やツール使用では不十分であることを隠してしまう可能性があります。
ロールアウト中は、これらの指標をポリシーバージョンとリリース段階ごとに比較します。そうすることで、プロバイダーのインシデントと、コントローラーの変更、候補の変更、または拡大されたカナリアを切り分けられます。
よくある質問
モデルフォールバック戦略とは何ですか?
モデルフォールバック戦略とは、AIリクエストを同じ対象に再試行するのか、同等キャパシティにフェイルオーバーするのか、承認済みの代替モデルに切り替えるのか、あるいは再実行が安全でないため停止するのかを決定するためのポリシーです。
リトライとフォールバックの違いは何ですか?
リトライは、同じ対象またはデプロイメントに対してリクエストを繰り返します。同等フェイルオーバーは、同じモデル契約を維持することを意図したキャパシティにリクエストを移します。クロスモデルフォールバックはモデルを変更するため、能力と品質の検証が必要です。
429エラーのたびに別のモデルへ切り替えるべきですか?
いいえ。まず制限の種類を分類し、リトライ指針に従い、残りの期限を確認し、上限付きのリトライまたはキューを使用します。承認済みの代替キャパシティがある場合はモデル切り替えが役立つこともありますが、出力品質、ツールの挙動、コストが変わる可能性もあります。
ストリーミング応答は途中でフォールバックできますか?
通常、トークンがユーザーに届いた後に透過的に切り替えないほうが安全です。アプリケーションに検証済みの再開プロトコルがない限り、ストリームを停止し、明示的な再開を促してください。
ルートにはいくつのフォールバックモデルを持たせるべきですか?
意味のある回復を提供できる、承認済みの最小セットを使用してください。候補が増えるほど、評価、監視、インシデント対応の作業も増えます。長くても未検証のリストは、レジリエンスではありません。
フォールバックロジックはどこに置くべきですか?
プロバイダーの正規化、ルーティング、試行予算、可観測性は、ゲートウェイまたはオーケストレーション層に集約してください。副作用リスク、スキーマ要件、安全ポリシー、品質しきい値といったワークフロー固有の意図は、アプリケーションの近くに置いてください。
チームは自動モデルフォールバックをどのように展開すべきですか?
シャドーモードで開始し、リプレイしても安全なワークフローだけをカナリア化し、トラフィックを広げる前にロールバック条件を定義し、モデル、プロンプト、ツール、スキーマ、再試行の責任分界、安全要件が変わるたびにフォールバックポリシーを再認証してください。
ワークフローのリスクに合わせてフォールバックを構築する
最適なモデルフォールバック戦略は、「次のモデルを試す」ことではありません。それは、境界を定めた意思決定システムです。
- ワークフロー 1 は、再試行と同等のキャパシティで再実行可能なリクエストを回復します。
- ワークフロー 2 は、能力と品質のチェックを通過した後にのみモデルを切り替えます。
- ワークフロー 3 は、出力や副作用によって復旧が安全でなくなった場合、自動再実行を停止します。
この設計は、契約違反を隠したり、ユーザー操作を重複させたりすることなく、可用性を向上させます。チームがモデルプロバイダー間でアクセスを標準化している場合は、Flatkey の OpenAI 互換の統合 API レイヤーを統合面として使用し、これらのワークフロー固有の封筒をすべての本番ルートに付与してください。



