Claude Platform Docs
MessagesClaude で構築する

拒否とフォールバック

Claude Fableモデル、Claude Opusモデル、Claude Sonnet 5.5、およびClaude Haiku 5.5が分類器による拒否をどのように返すか、また拒否されたリクエストをフォールバックモデルで再試行する方法について説明します。

Claude Fable 5.1、Claude Fable 5、Claude Opus 5.5、Claude Opus 5、Claude Sonnet 5.5、Claude Haiku 5.5には、リクエストを拒否できる「safety classifier」(安全性分類器)が含まれています。拒否が発生した場合、エラーではなく通常のレスポンスがstop_reason: "refusal"とともに返されます。そのstop_details.categoryはポリシー領域を示します(拒否の形式を参照)。通常は、同じリクエストを別のClaudeモデルに送信することで回答を得られます。このページでは、「refusal」(拒否)を認識する方法と、その再試行を設定する方法を説明します。

これらのモデルのいずれかを基盤に構築していて、拒否されたリクエストを自動的に別のモデルへフォールスルーさせたい場合に、このページをお読みください。また、レスポンスで"refusal"を目にして、次に何をすべきか知りたい場合にも当てはまります。

関連ページ:

最もシンプルな設定は、Claude APIでベータ版として提供されています。fallbacksを"default"に設定すると、APIは拒否されたリクエストを、その拒否カテゴリに対してAnthropicが推奨するフォールバックモデルで再試行します。推奨フォールバックがないカテゴリでは、拒否がそのまま返されます。Claude Haiku 5.5にはサーバーサイドフォールバックがないため、SDKミドルウェアによるクライアントサイドフォールバックを使用するか、再試行を自分で記述してください。

client = Anthropic()

response = client.beta.messages.create(
    model="claude-fable-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello, Claude"}],
    fallbacks="default",
    betas=["server-side-fallback-2026-07-01"],
)
print(response.model)

以下のセクションでは、拒否レスポンスに含まれる内容、サーバーサイドまたはクライアントサイドのフォールバックをいつ使用するか、そしてそれぞれがどのように課金されるかについて説明します。

拒否の形式

拒否は、stop_reason: "refusal"を持つ成功したHTTP 200レスポンスです:

{
  "id": "msg_01XFUDYJgAACzvnptvVoYEL",
  "type": "message",
  "role": "assistant",
  "model": "claude-fable-5",
  "content": [],
  "stop_reason": "refusal",
  "stop_details": {
    "type": "refusal",
    "category": "cyber",
    "explanation": "This request was declined because it could enable cyber harm."
  },
  "usage": {
    "input_tokens": 412,
    "output_tokens": 0
  }
}

stop_detailsオブジェクトは拒否の理由を説明します:

  • category: 分類器をトリガーしたポリシー領域を示します。
  • explanation: 人間が読める説明です。テキストは安定していないため、解析するのではなく表示してください。
  • recommended_model: fallbacksを設定したリクエスト(サーバーサイドフォールバック、ベータ版)にのみ存在します。APIがフォールバック試行をスキップした場合(例えば、フォールバックモデルがレート制限されていた場合)に直接再試行すべきモデルを示し、それ以外の場合はnullです。これはヒントであり、保証ではありません。
  • 拒否が名前付きカテゴリにマッピングされない場合、categoryとexplanationはどちらもnullになります。このnullは通常の恒久的な値であり、プレースホルダーではありません。
  • refusal以外のすべての停止理由では、stop_details自体がnullです。
category意味出力前の拒否が課金対象
"cyber"リクエストがマルウェアやエクスプロイト開発などのサイバー被害を可能にする恐れがあります。無害なサイバーセキュリティ業務でもこのカテゴリがトリガーされることがあります。いいえ
"bio"リクエストが危険な実験手法などの生物学的被害を可能にする恐れがあります。有益なライフサイエンス業務でもこのカテゴリがトリガーされることがあります。はい
"frontier_llm"リクエストが競合するAIモデルの開発を支援する恐れがあり、これはAnthropicの商用利用規約で制限されています。無害な機械学習業務でもこのカテゴリがトリガーされることがあります。はい
"reasoning_extraction"リクエストが、モデルの内部推論をレスポンステキスト内に再現するよう求めています。代わりに構造化された形式で推論を取得するには、適応型思考を使用してください。推論を思考ブロック内に保つを参照してください。はい
"general_harms"リクエストが4つの名前付きカテゴリ以外の利用ポリシー領域に該当します。無害な業務でもこのカテゴリがトリガーされることがあります。いいえ

拒否は、出力が一切ない段階で届くこともあれば、部分的な出力の後にストリームの途中で届くこともあります。いずれの場合も、部分的な出力は不完全なものとして扱い、破棄してください。

推論を思考ブロック内に保つ

reasoning_extractionの拒否は通常、モデルに思考や推論を出力に含めるよう求めるプロンプトから発生します。逐語的に求める場合も、固定形式で求める場合もあります。一般的な例:

  • 回答前にモデルが記入する<thinking>、<reasoning>、またはスクラッチパッドのセクション
  • JSON出力やツール入力内のreasoning、thinking、またはtraceフィールド
  • モデルの非公開メモ、または推論の経過を記録したログ
  • 逐語的または完全な形で求められる推論

こうした文言はシステムプロンプト、スキル、またはツールの説明に含まれている場合があるため、それらも確認してください。

Claudeに回答の説明を求めることは引き続き可能です。短い説明、結果の根拠となる証拠、または実行したアクションの要約を求めてください。モデルがどのように推論したかを確認するには、display: "summarized"を設定し、thinkingブロックを読んでください。このカテゴリには推奨フォールバックモデルがないため、リクエストを再試行するのではなくプロンプトを変更してください。言い換えたリクエストでも拒否される場合は、サポートに連絡し、リクエストIDを含めてください。

拒否の課金方法

以下の課金ルールは、Claude API、Amazon Bedrock、Claude Platform on AWS、Google Cloud、Microsoft Foundryのすべてのプラットフォームに適用されます。

出力前の拒否: Anthropicのセーフガードを大規模に回避しようとする試みを阻止するため、出力前に届いた拒否は、そのstop_details.categoryが"bio"、"frontier_llm"、または"reasoning_extraction"の場合に課金されます。これらは、2026年9月時点でAnthropicが誤検知の発生量が少ないと測定しているカテゴリです。これらの拒否は、他のリクエストと同様に、実行したモデルの料金で課金されます。それ以外のカテゴリ、またはカテゴリがnullの出力前の拒否は課金されません。いずれの場合も、contentは空で、トークン数はusageに表示されます。リクエストは引き続きレート制限にカウントされます。

ストリーム途中の拒否: ストリーム途中の拒否では、入力トークンとすでにストリーミングされた出力が通常料金で課金されます。

フォールバック: フォールバックを使用する場合、それをトリガーした拒否は、ストリームの途中で届いた場合、または課金対象カテゴリのいずれかに該当する場合に、フォールバックリクエストに加えて課金されます。フォールバッククレジットはフォールバックリクエストのプロンプトキャッシュミスを補償するため、会話のキャッシュに二重に支払う必要はありません。Claude Haiku 5.5の拒否にはフォールバッククレジットが付与されないため、その後のフォールバックではフォールバックモデルのプロンプトキャッシュ書き込みの全コストを支払います。サーバーサイドフォールバックが各試行をどのように報告するかについては、課金とレート制限を参照してください。

課金対象カテゴリは、Anthropicがセーフガードの誤検知率の測定と改善を続けるにつれて変更される可能性があります。課金対象カテゴリは、拒否カテゴリの表の出力前の拒否が課金対象列に記載されています。

フォールバック方式の選択

拒否されたリクエストを別のモデルで再試行する方法は3つあります。どれが適切かは、実行環境と必要な制御の度合いによって異なります。

状況使用するもの理由
Claude API、最もシンプルな設定サーバーサイドフォールバック1つのリクエスト、1つのレスポンス。APIが再試行を処理します。
任意のプラットフォーム、Anthropic SDKを使用SDKミドルウェアクライアントで一度設定するだけ。再試行は自動的に行われます。
生のHTTPまたはカスタム再試行ロジックフォールバッククレジットを使用した手動再試行完全な制御。フォールバッククレジットがコストを抑えます。

サーバーサイドフォールバックとSDKミドルウェアは、フォールバッククレジットを自動的に適用します。フォールバッククレジットのページが必要になるのは、再試行を自分で構築する場合のみです。Claude Haiku 5.5にはサーバーサイドフォールバックもフォールバッククレジットもないため、SDKミドルウェアまたは手動再試行を使用してください。

サーバーサイドフォールバック

サーバーサイドフォールバックは、拒否されたリクエストを単一のAPI呼び出し内で再試行します。デフォルトモードでは、プライマリモデルが拒否し、その拒否カテゴリに推奨フォールバックがある場合、APIはそのカテゴリに対してAnthropicが推奨するモデルで同じリクエストを実行します。代わりに、独自のフォールバックモデルを最大3つ指定することもできます。いずれの場合も、回答したモデルを示す1つのレスポンスが返されるため、ユーザーは1回のラウンドトリップで回答を得られます。

リクエストの作成

fallbacksパラメータを文字列"default"に設定し、server-side-fallback-2026-07-01ベータヘッダーを送信します。するとAPIは、リクエストされたモデルのサーバー定義のデフォルトルーティングを適用します。このルーティングは、分類器が報告する拒否カテゴリに基づいて推奨フォールバックモデルを選択するため、推奨が変わってもモデルリストを自分で管理することなく、拒否されたリクエストが処理されます。

デフォルトルーティングは、選択していないモデルについて事前のサイズ超過画像の拒否を引き起こすことはありません。"oversized_image": "error"とマークされた画像をリサイズすることになるルーティング先モデルは、代わりにルーティングから除外されるため、マークされた画像がリサイズされて処理されることはありません。

client = Anthropic()

response = client.beta.messages.create(
    model="claude-fable-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello, Claude"}],
    fallbacks="default",
    betas=["server-side-fallback-2026-07-01"],
)

# usage.iterations に fallback_message エントリがあれば、フォールバックモデルが実行されたことを意味します。
# stop_reason と照合して、フォールバックがレスポンスを返したことを確認します。
fallback_ran = any(
    iteration.type == "fallback_message"
    for iteration in response.usage.iterations or []
)
served_by_fallback = fallback_ran and response.stop_reason != "refusal"

print(
    json.dumps(
        {
            "stop_reason": response.stop_reason,
            "model": response.model,
            "served_by_fallback": served_by_fallback,
        }
    )
)

Anthropicは、モデルの能力に応じて、各モデルごと、および各ポリシーカテゴリごとに個別にセーフガードを設定しています。カテゴリによっては、フラグが立てられたリクエストは能力の低いモデルにフォールバックされるか、拒否されます。"default"モードは、これらのモデルごと・カテゴリごとの推奨をエンコードしているため、拒否されたリクエストはそのカテゴリに対してAnthropicが推奨するモデルで再試行されます。いずれの場合もフォールバックは可視化されます。レスポンスには処理したモデルが示され、fallbackコンテンツブロックが引き継ぎを示します。

ルーティングはサーバーサイドで適用され、Models APIでモデルごとに公開されることはありません。拒否されたリクエストをどのモデルが処理したかを確認するには、このページのサンプルのように、レスポンスのトップレベルのmodelフィールドを確認し、usage.iterations内のfallback_messageエントリを探してください。

フォールバックをトリガーするのは安全性分類器による拒否のみです。リクエストされたモデルでのレート制限、過負荷、またはサーバーエラーは、そのまま返されます。

独自のフォールバックモデルの指定

デフォルトルーティングの代わりに、fallbacksを最大3つのモデルのリストに設定できます。リクエストされたモデルが拒否すると、APIはチェーン内の次のモデルで同じリクエストを実行します。アプリケーションで検証済みのモデルを固定するなど、拒否されたリクエストをどのモデルが処理するかを正確に制御したい場合に、この形式を使用してください。

指定したフォールバックモデルはサイズ超過画像チェックの対象になります。画像ブロックに"oversized_image": "error"を設定したリクエストは、リクエストされたモデルと指定されたすべてのフォールバックに対して事前にチェックされ、いずれかがその画像をリサイズすることになる場合は拒否されます。また、拒否時に報告されるリスケール目標はそれらすべてに適合するものになります。

ハイライトされた行が、デフォルトルーティングのリクエストとの唯一の違いです。

client = Anthropic()

response = client.beta.messages.create(
    model="claude-fable-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello, Claude"}],
    fallbacks=[{"model": "claude-opus-4-8"}],
    betas=["server-side-fallback-2026-07-01"],
)
print(response.model)

fallbacksリストにはいくつかのルールが適用されます:

  • エントリは順番に試行されます。各エントリは、他のエントリおよびリクエストされたモデルと異なる必要があります。
  • 各エントリは、リクエストされたモデルで許可されたターゲットのいずれかである必要があります。ベータヘッダーを設定すると、そのリストはModels APIのモデルのエントリにallowed_fallback_modelsとして公開されます。
  • 各エントリはmodelを指定し、その試行に限りmax_tokens、thinking、output_config、speedを上書きできます。
  • リクエストは、指定されたすべてのモデルへの直接リクエストとして有効である必要があります。フォールバックモデルがリクエストで使用されている機能をサポートしていない場合、APIはリクエストを事前に拒否します。2026-07-01ヘッダーでは、thinking: {"type": "between_tools"}が例外です。Claude Sonnet 5.5のリクエストがClaude Sonnet 5にフォールバックする場合、フォールバック試行はthinking: {"type": "disabled"}とdisplay: "omitted"で実行されます。2026-06-01では、Claude Sonnet 5のエントリにthinkingを設定しないと、リクエストは事前に拒否されます。
  • デフォルトモードと同様に、フォールバックをトリガーするのは安全性分類器による拒否のみです。リクエストされたモデルでのレート制限、過負荷、またはサーバーエラーは、そのまま返されます。
  • フォールバックモデルがレート制限に達しているか過負荷の場合、フォールバック試行は行われず、代わりに直前の拒否が返されます。その場合、拒否のstop_details.recommended_modelに、直接再試行すべきモデルが示されます。想定される拒否の量に合わせてフォールバックモデルのレート制限を確保してください。そうしないと、負荷がかかったときにフォールバックが拒否に戻ってしまいます。

レスポンスの形式はどちらのモードでも同じです。ターンを処理したモデルはトップレベルのmodelフィールドに表示され、fallbackコンテンツブロックが引き継ぎを示し、usage.iterationsが各試行を記録します。

レスポンスに含まれる内容

レスポンスは他のメッセージと同様ですが、2つの追加要素があります:

  • トップレベルのmodelフィールドは、返されたメッセージを生成したモデルを報告します。それがリクエストされたモデルであってもフォールバックであっても同様です。
  • fallbackコンテンツブロックは、content内で1つのモデルの出力が次のモデルに引き継がれる各ポイントを示します:{"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}。
    • 拒否したホップがリクエストされたモデルである場合、from.modelは送信したモデル文字列をそのまま返します。
    • to.modelは常に、続行するモデルの解決済みIDです。

出力が一切ない段階での拒否の場合、fallbackブロックが最初のコンテンツブロックになります。例えば、デフォルトルーティングが拒否のカテゴリに対してClaude Opus 4.8を選択した場合:

{
  "id": "msg_01XFUDYJgAACzvnptvVoYEL",
  "type": "message",
  "role": "assistant",
  "model": "claude-opus-4-8",
  "content": [
    {
      "type": "fallback",
      "from": { "model": "claude-fable-5" },
      "to": { "model": "claude-opus-4-8" }
    },
    { "type": "text", "text": "Hi! How can I help you today?" }
  ],
  "stop_reason": "end_turn",
  "stop_details": null,
  "usage": {
    "input_tokens": 412,
    "output_tokens": 264,
    "cache_read_input_tokens": 0,
    "cache_creation_input_tokens": 0,
    "iterations": [
      {
        "type": "message",
        "model": "claude-fable-5",
        "input_tokens": 535,
        "output_tokens": 0,
        "cache_read_input_tokens": 0,
        "cache_creation_input_tokens": 0
      },
      {
        "type": "fallback_message",
        "model": "claude-opus-4-8",
        "input_tokens": 412,
        "output_tokens": 264,
        "cache_read_input_tokens": 0,
        "cache_creation_input_tokens": 0
      }
    ]
  }
}

usage.iterations配列はすべての試行を記録します。拒否したモデルは通常のmessageエントリとして表示され、ターンを処理したモデルはfallback_messageエントリとして表示されます。チェーン内のすべてのモデルが拒否した場合、レスポンスは最後のモデルの拒否となり、それ以前の各ホップにはmessageエントリ、最後のホップにはfallback_messageエントリが付きます。

スティッキールーティングにより、後続のターンが直接フォールバックモデルに送信されることがあります。そのようなターンにはfallbackコンテンツブロックが含まれません。そのターンではどのモデルも拒否していないためです。usage.iterations内のfallback_messageエントリ、リクエストされたモデルのmessageエントリがないこと、およびレスポンスのmodelフィールドによって識別してください。

会話の継続

次のターンでは、受け取ったアシスタントコンテンツをそのまま送り返してください。出力途中のフォールバックの後、contentには拒否したモデルが引き継ぎ前に生成したブロックタイプが含まれることがあります。以下の表は、ターンをエコーする際にどれを保持し、どれを削除するかを示しています。

ブロックタイプ次のターンでの扱い
fallback出現した位置に正確に保持してください。APIはその位置を使用して周囲の思考ブロックを検証するため、境界の両側の思考ブロックをエコーするリクエストは、このブロックが省略または移動されていると拒否されます。
text保持。
最後のfallbackブロックより後のすべてのブロック保持。
最後のfallbackブロックより前のthinking、redacted_thinking、またはconnector_text削除。
最後のfallbackブロックより前のクライアントサイドtool_use削除。
最後のfallbackブロックより前のserver_tool_use結果とペアになっている場合は保持。対応する結果がない場合は削除。

ストリーミング

ストリーミングリクエストでは、再試行は同じストリーム上で行われ、すでに受信したものが無効になることはありません。何が表示されるかは、拒否がいつ発生するかによって異なります。

出力が一切ない段階で拒否が発生した場合:

  • message_startはフォールバックモデルを示し、fallbackブロックが最初のコンテンツブロックになります。
  • message_startはフォールバック試行の開始を待つため、最初のバイトまでの時間には拒否された試行が含まれます。

出力途中で拒否が発生した場合:

  • 開いているコンテンツブロックが閉じ、fallbackブロック(デルタのない通常のcontent_block_startとcontent_block_stopのペア)が境界を示します。
  • フォールバックモデルは部分的な出力から続行します。部分的な出力のうちtextブロックのみがコンテキストとしてフォールバックモデルに渡されます。他のブロックタイプはcontentに残ります。
  • message_startはすでにリクエストされたモデルを示しているため、処理したモデルはfallbackブロックのto.modelと、最後のmessage_deltaのusage.iterations内のfallback_messageエントリから読み取ってください。

非ストリーミングレスポンス

非ストリーミングリクエストでは、出力途中の拒否の動作が異なります。レスポンスは拒否したモデルの部分的な出力を省略し、フォールバックモデルが最初から回答します。結果は出力が一切ない段階での拒否のように見え、fallbackブロックが最初に来ます。拒否された試行とその出力トークンは引き続きusage.iterationsに表示されます。

課金とレート制限

各試行には、拒否の課金方法のルールが、実行したモデルの料金で適用されます。出力を一切生成する前に拒否した試行は、その拒否カテゴリが課金対象の場合にのみ課金されます。いずれの場合も、そのトークンはusage.iterationsエントリに報告されます。出力を生成したすべての試行(レスポンスの途中で拒否したものを含む)は、個別に課金されます。usage.iterations配列は、課金対象の試行ごとの記録です。トップレベルのusageカウントは、返されたメッセージを生成した試行のみを表します。異なるモデルのトークンが1つのフィールドに合算されることはありません。

拒否したものを含め、実行されたすべての試行は、それぞれのモデルのレート制限にカウントされます。

スティッキールーティング

会話がフォールバックした後、APIはどのモデルがそれを処理したかを記録します。その会話に対するfallbacksを含む後続のリクエストは、リクエストされたモデルを実行せずに、直接そのフォールバックモデルに送られます。これにより、毎ターン予測どおりに再び拒否されるであろう試行に対して支払うことを避けられます。

ルーティング決定のいくつかの特性:

  • 約1時間保持され、組織にスコープされます。
  • 会話プレフィックスのコンテンツハッシュと、それを処理したモデルとして保存されます。メッセージコンテンツ自体は保存されません。
  • ベストエフォートであるため、コードはリクエストされたモデルがいつでも再び試行される可能性に対応する必要があります。

スティッキールーティングはストリーミングリクエストと非ストリーミングリクエストの両方に適用されます。ストリーミングリクエストでは、ルーティング決定はストリームが開く前に行われるため、message_startイベントのmodelフィールドにはすでにフォールバックモデルのIDが含まれています。

SDKミドルウェアによるクライアントサイドフォールバック

SDKには拒否フォールバック用のミドルウェアが含まれています。フォールバックモデルのリストを指定して、クライアントで一度設定します。その後、client.beta.messagesを通じた呼び出しは、どのプラットフォームでも拒否されたリクエストを自動的に再試行します。ミドルウェアは処理するすべてのリクエストでfallback-credit-2026-07-01ベータヘッダーも送信するため、リクエストごとの設定なしで再試行の料金が再計算されます。Claude Haiku 5.5の拒否にはフォールバッククレジットが付与されないため、その後の再試行ではフォールバックモデルのプロンプトキャッシュ書き込みの全コストを支払います。

セットアップ

BetaRefusalFallbackMiddlewareをクライアントコンストラクタに渡し、会話のリクエスト間で1つのBetaFallbackStateインスタンスを共有します。

from anthropic import Anthropic, BetaFallbackState, BetaRefusalFallbackMiddleware

# 拒否が発生した場合、ミドルウェアは指定されたフォールバックモデルで再試行し、
# 処理するすべてのリクエストにfallback-creditベータヘッダーを自動的に送信します。
client = Anthropic(
    middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])],
)

state = BetaFallbackState()  # pins follow-ups to the model that accepted

# ストリーミング: 拒否が発生した場合、ミドルウェアはフォールバックモデルで再試行し、
# そのイベントを開いているストリームに継ぎ足します。
with (
    state,
    client.beta.messages.stream(
        max_tokens=1024,
        model="claude-fable-5",
        messages=[{"role": "user", "content": "Hello, Claude"}],
    ) as stream,
):
    for text in stream.text_stream:
        print(text, end="", flush=True)
    final_message = stream.get_final_message()
print(f"\nserved by: {final_message.model}")

# 非ストリーミング: 状態を再利用することで会話が固定されたまま維持されます。
with state:
    message = client.beta.messages.create(
        max_tokens=1024,
        model="claude-fable-5",
        messages=[{"role": "user", "content": "Hello, Claude"}],
    )
print(f"served by: {message.model}")

動作

  • 再試行は、フォールバックリストを順番にたどります。フォールバックモデル自体が拒否した場合、リクエストは次のエントリに渡されます。
  • リスト内のすべてのモデルが拒否した場合、ミドルウェアはエラーを発生させるのではなく、最終的な拒否(最後のモデルの拒否レスポンス)を返します。
  • Claude Fable 5.1、Claude Opus 5.5、Claude Sonnet 5.5、Claude Haiku 5.5、またはClaude Fable 5の思考ブロックは変更されずにそのまま渡されます。各再試行では元のリクエスト本文が再送信され、ミドルウェアが後続のリクエストで会話履歴から削除するブロックは、ミドルウェア自身が追加したfallback境界ブロックのみです。フォールバックモデルはClaude Fable 5.1のブロックを読み取れません。これを読み取れるのはClaude Fable 5.1とClaude Mythos 5.1のみであるため、APIはそれらを削除します。APIはまた、Claude Fable 5.1とClaude Mythos 5.1を除くすべてのフォールバックモデルについて、Claude Opus 5.5のブロックも削除します(会話の途中でのモデルの切り替えを参照)。Claude Sonnet 5.5のブロックも、Claude APIおよびGoogle Cloud上のClaude Opus 5.5を除くすべてのフォールバックモデルについて削除されます。Claude Opus 5.5とClaude Sonnet 5.5は、Claude APIおよびGoogle Cloud上でClaude Haiku 5.5のブロックを読み取ります。それらを読み取れないフォールバックモデルについては、APIがそれらを削除します。
  • ミドルウェアを通じて応答されたレスポンスには、サーバー側フォールバックのレスポンスと同様に、各モデルの境界にfallbackコンテンツブロックが含まれます。ミドルウェアは、後続のリクエストでこれらのブロックを自動的に管理します。
  • 受け入れたモデルはBetaFallbackStateに記録されるため、状態を共有する後続のリクエストは、拒否したモデルに再度問い合わせるのではなく、そのモデルに固定されたままになります。

再試行を自分で記述する

生のHTTPまたはカスタム再試行ロジックを使用する場合は、ミドルウェアがラップしているパターンを実装します:

  1. 拒否を検出する

    レスポンスにstop_reason: "refusal"があるか確認します。

  2. フォールバックモデルで再送信する

    modelをClaude Opus 4.8などのフォールバックモデルに設定して、同じリクエストを送信します。拒否されたリクエストがthinking: {"type": "between_tools"}を送信していた場合は、まずthinkingを変更してください。その値を受け付けるのはClaude Sonnet 5.5のみであるため、thinkingを省略するか、フォールバックモデルが受け付ける値を設定してください。2026-07-01ヘッダーでのサーバーサイドフォールバックは、Claude Sonnet 5にフォールバックする際にこの変更を自動的に行います。Claude Fable 5.1またはClaude Fable 5が拒否したリクエストは、通常は別のモデルで処理できます。会話履歴の扱い方は、フォールバッククレジットを引き換えるかどうかによって異なります:

    • クレジットを引き換えない場合: 以前のthinkingおよびredacted_thinkingブロックはそのまま残すことも、入力トークンを節約するために削除することもできます。いずれにしても、フォールバックモデルは通常それらを使用できません。Claude Fable 5.1のブロックを読み取れるのはClaude Fable 5.1とClaude Mythos 5.1のみであり、Claude Fable 5のブロックを読み取れるのはこれら2つのモデルとClaude Fable 5、Claude Mythos 5のみであるため、その他のフォールバックモデルについてはAPIがそれらを削除します。APIはまた、Claude Fable 5.1とClaude Mythos 5.1を除くすべてのフォールバックモデルについて、Claude Opus 5.5のブロックも削除します(会話の途中でのモデルの切り替えを参照)。Claude Sonnet 5.5のブロックも、Claude APIおよびGoogle Cloud上のClaude Opus 5.5を除くすべてのフォールバックモデルについて削除されます。Claude Haiku 5.5の拒否後の再試行は、常にこのケースに該当します。Claude Opus 5.5とClaude Sonnet 5.5は、Claude APIおよびGoogle Cloud上でClaude Haiku 5.5のブロックを読み取るため、そこでいずれかのモデルにフォールバックする場合は、それらのブロックをそのまま残してください。それらを読み取れないフォールバックモデルについては、APIが課金せずにそれらを削除します。
    • クレジットを引き換える場合: 引き換えには完全一致が必要なため、本文を変更せずに送信してください。引き換え時には以前のモデルの思考ブロックをサーバーが処理するため、それらを削除しないでください(拒否されたリクエストと一致する必要があるフィールドを参照)。
  3. フォールバックモデルを使い続ける

    マルチターンの会話では、元のモデルに戻すのではなく、後続のターンでもフォールバックモデルを使い続けてください。

手動再試行ではフォールバックモデルのプロンプトキャッシュを最初から書き込むため、既存のキャッシュを読み取るよりもコストがかかります。フォールバッククレジットはそのコストを払い戻します。自分で構築するすべての再試行で引き換えてください。Claude Haiku 5.5の拒否にはフォールバッククレジットが付与されないため、その後の再試行ではフォールバックモデルのプロンプトキャッシュ書き込みの全コストを支払います。

Message Batchesにおける拒否

Message Batch内で拒否されたリクエストは、stop_reason: "refusal"を持つresult.type: "succeeded"として返されます。バッチ結果は同期レスポンスと同じstop_detailsオブジェクトを持つため、stop_reasonまたはstop_details.typeのいずれかで拒否を検出できます。1つの違いとして、バッチの拒否はフォールバッククレジットを発行しないため、バッチ結果のstop_detailsにfallback_credit_tokenが含まれることはありません。

サーバーサイドフォールバックはバッチでは利用できません(fallbacksを含むバッチリクエストは項目ごとのエラー結果を生成します)。拒否されたバッチ項目を再試行するには:

  1. 結果から拒否された項目を収集します。
  2. マルチターン履歴内の思考ブロックはそのまま残すか、入力トークンを節約するために削除します。それらを読み取れないフォールバックモデルについては、手動再試行と同様に、APIが課金せずにそれらを削除します。
  3. 拒否された項目がthinking: {"type": "between_tools"}を送信していた場合は、thinkingを省略するか、フォールバックモデルが受け付ける値を設定します。between_toolsを受け付けるのはClaude Sonnet 5.5のみです。
  4. それらを新しいバッチとして、または直接リクエストとして、フォールバックモデルで再送信します。

よくある落とし穴

  • 別のモデルで再試行してください。 拒否されたリクエストを同じモデルに再送信すると、通常は再び拒否されます。再試行はフォールバックモデルに向けてください。
  • 再試行の予算はターンごとやセッションごとではなく、リクエストごとに設定してください。 1つのターンで複数の拒否が発生することがあります。例えば、エージェントとそのサブエージェントなどです。
  • すべてのリクエストパスでフォールバックを設定してください。 再試行ハンドラー、エラー回復ブランチ、バックグラウンドワーカーのすべてに必要です。フォールバックなしでリクエストを再発行するハンドラーは、まさに最も必要とされる可能性の高いリクエストで保護を失います。
  • サブエージェント呼び出しには独自のフォールバックを設定してください。 fallbacksパラメータは、ツール実行内部から行われるモデル呼び出しには伝播しません。
  • フォールバックは周囲の状態ではなく、リクエストのプロパティにしてください。 共有フラグ、キャッシュされた設定値、またはグローバルトグルは同期がずれ、気づかないうちにリクエストが保護されないままになる可能性があります。フォールバックが有効であることを確認できない場合は、有効であると仮定するのではなく、設定してください。
  • 拒否を独自のシグナルとして計測してください。 拒否はHTTP 200であるため、エラー率や5xxレスポンスに基づく監視では検出されません。拒否ごとに1つのイベント、フォールバックで処理されたレスポンスごとに1つのイベント(usage.iterations内のfallback_messageエントリが後者を示します)を発行し、2つのカウントの差に対してアラートを設定してください。
  • contentやstop_detailsの内部フィールドではなく、stop_reasonまたはstop_details.typeで分岐してください。 stop_detailsオブジェクトは拒否時に常に存在しますが、そのcategoryおよびexplanationフィールドはnullになることがあります。stop_reasonが"refusal"に等しいかどうかを直接確認してください。

次のステップ

再試行を自分で構築する際に、プロンプトキャッシュのコストを二重に支払うことを避けます。

すべてのstop_reason値とその処理方法。

拒否フォールバックヘルパーを含む、SDKミドルウェアの仕組み。

既存のアプリケーションをClaude Fable 5.1に移行します。

Was this page helpful?