
AI出力が不安定なときのフォールバック設計|リトライの型
PoCのときは、きれいに動いていた。 それを本番に出した途端、ときどき返事の形式が崩れたり、急に応答が返ってこなかったり、料金やレート制限に引っかかって止まったりする——そんな経験、ありますよね。
「ちゃんとテストしたのに」と自分を責めたくなるかもしれません。でも、これはあなたの実装が雑だったからではありません。AIの出力は、同じ入力でも毎回まったく同じにはならないもので、外部APIである以上、遅延も失敗も普通に起きます。つまり、不安定さは「直すバグ」ではなく、「最初から織り込んでおく前提」なのです。
この記事では、AIが時々おかしくなってもシステム全体は止めないための、フォールバック(代替経路)とリトライ(再試行)の組み方を整理します。一度に完璧な多重防御を作る必要はありません。まず効くところから、小さく一つずつ一緒に入れていきましょう。
結論:AI機能は「失敗する前提」で囲みます。順番は、①タイムアウトで待ちすぎを止める → ②整形・検証して、形が崩れた出力を弾く → ③弾いたら賢くリトライ(待ち時間を空けて/回数を区切って)→ ④それでもダメなら代替経路(簡易版・キャッシュ・ルールベース)→ ⑤最後は人へエスカレーション。この5段を、いきなり全部でなく、まず「タイムアウト」と「リトライの上限」の2つから入れると、本番の事故が目に見えて減ります。
不安定なAIを安全に業務へ載せる鍵は、賢いプロンプトより、失敗したときの受け止め方にあります。そこが決まっていると、AIがゆらいでも、現場のあなたが夜中に叩き起こされずに済みます。
なぜ「成功する前提」で組むと、本番でつらくなるのか
AIを呼ぶコードを最初に書くとき、つい「リクエストを投げる→返ってきた答えを使う」という一本道で書いてしまいます。PoCはそれで十分動きます。
けれど本番では、この一本道のあちこちで現実がつまずきます。
- 応答がいつまでも返ってこない(混雑・大きな入力で遅延)
- 返ってはきたが、期待した形式じゃない(JSONが壊れている、よけいな前置きがついている)
- レート制限や一時的なエラーで弾かれる(429・503など)
- 内容は返ったが、明らかに的外れ/もっともらしい誤りが混じる
一本道のコードは、このどれか一つで止まります。そして止まった先にいるのは、それを使っている利用者や、深夜に通知を受けるあなたです。
だからやることは、難しいアルゴリズムではありません。 「うまくいかなかったら、次にどうするか」を、つまずきの種類ごとに先に決めておくこと。それだけで、同じAIを使っていても、システムの粘り強さがまるで変わります。
段1:タイムアウト——「待ちすぎ」を先に止める

まず最初に入れたいのは、タイムアウトです。地味ですが、いちばん効きます。
AIの応答は、入力が大きいときや混雑時に、思った以上に長くかかることがあります。待ち時間に上限を決めておかないと、応答待ちのリクエストがたまり、やがて全体を巻き込んで詰まります。
- 1回の呼び出しに「ここまで待ったら諦める」秒数を決める(例:用途に応じて10〜30秒)
- 諦めたら、すぐ次の段(リトライや代替)へ渡す
- ストリーミングを使うなら「最初の1文字が来るまで」の上限も別に持つ
ポイントは、ユーザーを待たせる上限と、システムを守る上限は別物だということ。利用者向けの画面なら「数秒で何か返す」を優先し、裏のバッチ処理なら長めに待ってよい、というように、場面ごとに線を引きます。
数値で迷ったら、まず用途で割り切ると動きやすいです。下の早見で自分のケースを先に決めてから、秒数やリトライ回数を詰めます(リトライの詳細は段3で)。
| 用途 | タイムアウトの目安 | リトライ回数 |
|---|---|---|
| 同期(ユーザーが画面で待つ操作) | 短め(数秒) | 0〜1回 |
| 非同期(裏のバッチ処理) | 長め | 2〜3回 |
裏のバッチのように「待たせる相手がいない」場面では、ユーザー向けと裏処理でタイムアウトを二重に管理する必要はありません。守りたい上限を1つ決めれば十分です。
段2:検証——「形が崩れた出力」を受け取った所で弾く
返ってきた答えを、そのまま信じて次の処理に流さない。これがフォールバックの土台です。
AIの出力は自然文なので、JSONを頼んでも前後によけいな説明がついたり、必須の項目が欠けたりします。受け取った直後に、最低限の検証を通します。
- 期待する形式(JSON・特定のキー・数値の範囲など)に合っているか
- 必須項目が欠けていないか、想定外の値が入っていないか
- 文字数・件数など、明らかにおかしい量になっていないか
ここで弾く基準を持っておくと、「壊れた出力が下流に流れて、別の場所で謎のエラーになる」という一番やっかいな事故を防げます。検証に通らなかったものは失敗とみなして、次の段へ渡します。なお、出力そのものの中身が正しいかは検証だけでは見抜けないことがあるので、もっともらしい誤りの見分け方はハルシネーションの見抜き方もあわせて。
段3:リトライ——「賢く」もう一度だけ試す
タイムアウトや検証で弾いたものの一部は、もう一度試すと成功します(一時的な混雑、たまたまの形式崩れなど)。ただし、やみくもな再試行は逆効果です。
賢いリトライには、コツが3つあります。
- 回数を区切る:無限に試さない。2〜3回までなど上限を決める。
- 間隔を空けて、少しずつ延ばす:すぐ再送せず、待ってから。回数ごとに待ち時間を延ばす(指数バックオフ)と、混雑時に傷口を広げません。
- 「再試行していい失敗」だけ再試行する:レート制限(429)や一時エラー(503)は再試行向き。入力が悪い・認証エラーなどは、何度試しても同じなので即あきらめて次へ。
特に注意したいのが、お金とレート制限です。リトライは便利ですが、1回ごとに料金がかかり、レート制限も消費します。上限を決めずに再試行を増やすと、コストが想定外に膨らみます。見積もりの考え方はAI APIの料金とレート制限を見積もるが参考になります。
段4:代替経路——「AIなしでも、最低限は返せる」状態を持つ
リトライしても通らないことは、必ずあります。そのとき画面に「エラー」とだけ出して終わらせないための逃げ道を、あらかじめ用意しておきます。
代替の選択肢は、用途によっていくつかあります。
- 簡易版に切り替える:高機能なモデルが無理なら、軽いモデルや短い処理で「とりあえずの答え」を返す
- キャッシュ/前回の結果を使う:同じような入力なら、過去の妥当な結果を一時的に流用する
- ルールベースに落とす:AIをやめて、決め打ちのロジックや定型文で最低限を返す
- 正直に「今は使えません」と返す:無理に答えを作らず、後で再実行できる導線を出す
ただ、キャッシュや簡易版は口で言うほど安くありません。一から作る余裕がない現場は、まず「正直に今は使えません+後で再実行できる導線」の1択だけでも十分です。これだけで「黙って壊れる」のは防げます。簡易版やキャッシュは、余裕が出てきてから足せば間に合います。
大事なのは、どれを選ぶにしても「黙って壊れない」こと。利用者から見て「結果は簡素だが破綻はしていない」状態を保てれば、AIが不調でも業務は止まりません。「常にAIで完璧な答えを出す」より、「AIが落ちても最低限は回る」ほうが、本番ではずっと信頼されます。
段5:エスカレーション——最後は、人にバトンを渡す
自動の手を尽くしても収まらないときは、人が引き取れる形にして終わります。ここを設計しておくと、AIの不調が「誰も気づかないまま放置」になりません。
- 失敗した入力・出力・回数をログに残す(後から再現・原因追跡できるように)
- 一定以上の失敗が続いたら、担当へ通知する(鳴らしすぎない閾値で)
- 利用者には「確認のうえ折り返します」など、人が引き取った合図を返す
通知は、閾値の設計やアラート基盤がないと絵に描いた餅になりがちです。専用の監視がなければ、まずは失敗をログに1行残すだけで十分。「いつ・何が・何回失敗したか」が後から追えれば、最初の一歩としては足りています。通知や閾値は、基盤が整ってからの後付けでかまいません。
AIを業務に載せるときは、もともと「出力は人が確認する前提」で組むのが基本です。フォールバックの最終段は、その人の確認とつながっています。どこに人を挟むかは人の確認を挟むAIワークフロー(HITL)の組み方で詳しく整理しています。
明日からやること(小さく始める3つ)
5段を一度に作ると重いので、効果の大きい順に、まずこの3つから。
- タイムアウトと「リトライ上限」を入れる:いちばん詰まりやすい所が、まず止まらなくなります。回数は2〜3回、間隔は少し空ける、から。
- AIの出力を受け取った直後に1つだけ検証を足す:「必須キーがあるか」など最小の1チェックでいい。壊れた出力の下流流出が止まります。
- 失敗時に返す『代替の一手』を1つ決めておく:簡易版・定型文・「後で折り返し」のどれでも。これだけで「黙って壊れる」がなくなります。
AI出力フォールバック設計チェックリスト
実装やレビューのときに、そのまま使えます。各段の先頭に「これだけは必須」の最低ラインを1つ置きました。まずそこだけ埋めれば、その段は最低限回ります。残りは「余裕があれば」の任意項目。全部埋める前提ではないので、今日できる所から進めてください。
段1:タイムアウト
- 【必須】1回の呼び出しに待ち時間の上限を1つ決めたか
- (余裕があれば)ユーザー向けと裏処理で、上限を別々に考えたか ※待たせる相手がいない裏バッチだけなら、二重管理は不要
- (余裕があれば)諦めた後に渡す先(次の段)があるか
段2:検証
- 【必須】必須キーがあるかなど、最低1つの検証を入れたか
- (余裕があれば)量(文字数・件数)が異常でないか見ているか
- (余裕があれば)検証落ちを「失敗」として次の段に渡せているか
段3:リトライ
- 【必須】リトライ回数の上限を決めたか
- (余裕があれば)間隔を空けて、徐々に延ばす形にしたか
- (余裕があれば)「再試行していい失敗/無駄な失敗」を区別したか
- (余裕があれば)リトライによる料金・レート制限の増加を見込んだか ※リトライ0回の同期処理なら、この項目は省いてよい
段4:代替経路
- 【必須】AIが使えないときの代替を1つ持ったか(まずは「今は使えません+後で再実行」だけでよい)
- (余裕があれば)簡易版・キャッシュなど、より親切な代替を用意したか
- (余裕があれば)代替に切り替えたことが分かるようになっているか
段5:エスカレーション
- 【必須】失敗の入力・出力・回数をログに残しているか(まずは1行でよい)
- (余裕があれば)失敗が続いたら人に通知する仕組みがあるか ※専用の監視がなければ後付けでよい
- (余裕があれば)利用者に「人が引き取った」と伝わる導線があるか
最後に
AIが本番で時々おかしくなるのは、あなたの作り方が甘いからではありません。 ゆらぐものを、ゆらぐ前提で囲えているか——本番で効いてくるのは、そこだけです。

完璧に賢いAIを目指すより、転んでも自分で立ち直れる仕組みのほうが、現場ではずっと頼りになります。 今日ひとつ、タイムアウトを入れる。それだけで、あなたのシステムは少しだけ強く、あなたの夜は少しだけ静かになります。一歩ずつでいきましょう。