---
title: 拒否とフォールバック
url: https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback
description: 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`はポリシー領域を示します（[拒否の形式](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#refusal-response)を参照）。通常は、同じリクエストを別のClaudeモデルに送信することで回答を得られます。このページでは、「refusal」（拒否）を認識する方法と、その再試行を設定する方法を説明します。

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

関連ページ：

* [停止理由とフォールバック](https://platform.claude.com/docs/ja/build-with-claude/handling-stop-reasons)：`stop_reason`の値の完全なリスト。
* [フォールバッククレジット](https://platform.claude.com/docs/ja/build-with-claude/fallback-credit)：再試行を自分で構築する際に、プロンプトキャッシュのコストを二重に支払うことを避ける方法。
* [SDKミドルウェア](https://platform.claude.com/docs/ja/cli-sdks-libraries/middleware)：これらすべてをラップするSDKヘルパー。
* [フォールバックと課金のクックブック](https://platform.claude.com/cookbook/fable-5-fallback-billing-guide)：エンドツーエンドの実例。

最もシンプルな設定は、Claude APIでベータ版として提供されています。`fallbacks`を`"default"`に設定すると、APIは拒否されたリクエストを、その拒否カテゴリに対してAnthropicが推奨するフォールバックモデルで再試行します。推奨フォールバックがないカテゴリでは、拒否がそのまま返されます。Claude Haiku 5.5にはサーバーサイドフォールバックがないため、[SDKミドルウェアによるクライアントサイドフォールバック](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#client-side-fallback)を使用するか、[再試行を自分で記述](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#manual-retry)してください。

<CodeGroup>
  ```bash cURL
  curl --fail-with-body -sS https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: server-side-fallback-2026-07-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5",
      "max_tokens": 1024,
      "fallbacks": "default",
      "messages": [{"role": "user", "content": "Hello, Claude"}]
    }'
  ```

  ```bash CLI
  ant beta:messages create \
    --model claude-fable-5 \
    --max-tokens 1024 \
    --message '{"role":"user","content":"Hello, Claude"}' \
    --fallbacks default \
    --beta server-side-fallback-2026-07-01
  ```

  ```python Python
  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)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await 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"]
  });
  console.log(response.model);
  ```

  ```csharp C#
  AnthropicClient client = new();

  BetaMessage response = await client.Beta.Messages.Create(
      new()
      {
          Model = Messages::Model.ClaudeFable5,
          MaxTokens = 1024,
          Messages = [new() { Content = "Hello, Claude", Role = Role.User }],
          Fallbacks = new Default(),
          Betas = [AnthropicBeta.ServerSideFallback2026_07_01],
      }
  );

  Console.WriteLine(response.Model.Raw());
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5,
  	MaxTokens: 1024,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hello, Claude")),
  	},
  	Fallbacks: anthropic.BetaFallbacksParamOfDefault(),
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaServerSideFallback2026_07_01},
  })
  if err != nil {
  	panic(err)
  }

  fmt.Println(response.Model)
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  BetaMessage response = client.beta().messages().create(MessageCreateParams.builder()
      .model(Model.CLAUDE_FABLE_5)
      .maxTokens(1024L)
      .addUserMessage("Hello, Claude")
      .fallbacksDefault()
      .addBeta(AnthropicBeta.SERVER_SIDE_FALLBACK_2026_07_01)
      .build());

  IO.println(response.model().asString());
  ```

  ```php PHP
  $client = new Client();

  $response = $client->beta->messages->create(
      model: 'claude-fable-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      fallbacks: 'default',
      betas: ['server-side-fallback-2026-07-01'],
  );

  echo $response->model, PHP_EOL;
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  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"]
  )

  puts response.model
  ```
</CodeGroup>

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

## 拒否の形式

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

```json
{
  "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`を設定したリクエスト（[サーバーサイドフォールバック](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#server-side-fallback)、ベータ版）にのみ存在します。APIがフォールバック試行をスキップした場合（例えば、フォールバックモデルがレート制限されていた場合）に直接再試行すべきモデルを示し、それ以外の場合は`null`です。これはヒントであり、保証ではありません。
* 拒否が名前付きカテゴリにマッピングされない場合、`category`と`explanation`はどちらも`null`になります。この`null`は通常の恒久的な値であり、プレースホルダーではありません。
* `refusal`以外のすべての停止理由では、`stop_details`自体が`null`です。

| `category`               | 意味                                                                                                                                                                                                                                                                                       | 出力前の拒否が課金対象 |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `"cyber"`                | リクエストがマルウェアやエクスプロイト開発などのサイバー被害を可能にする恐れがあります。無害なサイバーセキュリティ業務でもこのカテゴリがトリガーされることがあります。                                                                                                                                                                                                      | いいえ         |
| `"bio"`                  | リクエストが危険な実験手法などの生物学的被害を可能にする恐れがあります。有益なライフサイエンス業務でもこのカテゴリがトリガーされることがあります。                                                                                                                                                                                                                | はい          |
| `"frontier_llm"`         | リクエストが競合するAIモデルの開発を支援する恐れがあり、これは[Anthropicの商用利用規約](https://www.anthropic.com/legal/commercial-terms)で制限されています。無害な機械学習業務でもこのカテゴリがトリガーされることがあります。                                                                                                                                          | はい          |
| `"reasoning_extraction"` | リクエストが、モデルの内部推論をレスポンステキスト内に再現するよう求めています。代わりに構造化された形式で推論を取得するには、[適応型思考](https://platform.claude.com/docs/ja/build-with-claude/thinking)を使用してください。[推論を思考ブロック内に保つ](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks)を参照してください。 | はい          |
| `"general_harms"`        | リクエストが4つの名前付きカテゴリ以外の利用ポリシー領域に該当します。無害な業務でもこのカテゴリがトリガーされることがあります。                                                                                                                                                                                                                         | いいえ         |

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

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

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

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

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

Claudeに回答の説明を求めることは引き続き可能です。短い説明、結果の根拠となる証拠、または実行したアクションの要約を求めてください。モデルがどのように推論したかを確認するには、`display: "summarized"`を設定し、[`thinking`ブロック](https://platform.claude.com/docs/ja/build-with-claude/thinking#summarized-thinking)を読んでください。このカテゴリには推奨フォールバックモデルがないため、リクエストを再試行するのではなくプロンプトを変更してください。言い換えたリクエストでも拒否される場合は、[サポートに連絡](https://support.claude.com/en/articles/9015913-how-to-get-support)し、[リクエストID](https://platform.claude.com/docs/ja/api/errors#request-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`に表示されます。リクエストは引き続きレート制限にカウントされます。

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

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

課金対象カテゴリは、Anthropicがセーフガードの誤検知率の測定と改善を続けるにつれて変更される可能性があります。課金対象カテゴリは、[拒否カテゴリの表](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#refusal-response)の**出力前の拒否が課金対象**列に記載されています。

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

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

| 状況                           | 使用するもの                                                                                                                                                                                      | 理由                               |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| Claude API、最もシンプルな設定         | [サーバーサイドフォールバック](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#server-side-fallback)                                                                          | 1つのリクエスト、1つのレスポンス。APIが再試行を処理します。 |
| 任意のプラットフォーム、Anthropic SDKを使用 | [SDKミドルウェア](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#client-side-fallback)                                                                               | クライアントで一度設定するだけ。再試行は自動的に行われます。   |
| 生のHTTPまたはカスタム再試行ロジック         | [フォールバッククレジット](https://platform.claude.com/docs/ja/build-with-claude/fallback-credit)を使用した[手動再試行](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#manual-retry) | 完全な制御。フォールバッククレジットがコストを抑えます。     |

サーバーサイドフォールバックとSDKミドルウェアは、フォールバッククレジットを自動的に適用します。[フォールバッククレジット](https://platform.claude.com/docs/ja/build-with-claude/fallback-credit)のページが必要になるのは、再試行を自分で構築する場合のみです。Claude Haiku 5.5にはサーバーサイドフォールバックもフォールバッククレジットもないため、SDKミドルウェアまたは手動再試行を使用してください。

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

サーバーサイドフォールバックは、拒否されたリクエストを単一のAPI呼び出し内で再試行します。デフォルトモードでは、プライマリモデルが拒否し、その拒否カテゴリに推奨フォールバックがある場合、APIはそのカテゴリに対してAnthropicが推奨するモデルで同じリクエストを実行します。代わりに、[独自のフォールバックモデルを最大3つ指定する](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#naming-your-own-fallback-models)こともできます。いずれの場合も、回答したモデルを示す1つのレスポンスが返されるため、ユーザーは1回のラウンドトリップで回答を得られます。

<Note>
  サーバーサイドフォールバックはClaude APIでベータ版です。`fallbacks`パラメータは[Message Batches API](https://platform.claude.com/docs/ja/build-with-claude/batch-processing)ではサポートされておらず（これを含むバッチ項目はエラー結果として返されます）、Amazon Bedrock、Google Cloud、Microsoft Foundryでは利用できません。これらのプラットフォームでは、代わりに[SDKミドルウェアによるクライアントサイドフォールバック](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#client-side-fallback)を使用してください。Claude Haiku 5.5にはサーバーサイドフォールバックがありません。`fallbacks: "default"`を指定した場合、拒否されたリクエストは拒否されたままとなり、フォールバックモデルのリストを指定すると400エラーが返されます。
</Note>

### リクエストの作成

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

デフォルトルーティングは、選択していないモデルについて事前の[サイズ超過画像の拒否](https://platform.claude.com/docs/ja/build-with-claude/vision-coordinates#oversized-image-error)を引き起こすことはありません。`"oversized_image": "error"`とマークされた画像をリサイズすることになるルーティング先モデルは、代わりにルーティングから除外されるため、マークされた画像がリサイズされて処理されることはありません。

<CodeGroup>
  ```bash cURL
  curl --fail-with-body -sS https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: server-side-fallback-2026-07-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5",
      "max_tokens": 1024,
      "fallbacks": "default",
      "messages": [{"role": "user", "content": "Hello, Claude"}]
    }' |
    jq -c '{
      stop_reason,
      model,
      # usage.iterations に fallback_message エントリがあれば、フォールバックモデルが実行されたことを意味します。
      # stop_reason と照合して、フォールバックがレスポンスを返したことを確認します。
      served_by_fallback: (
        any(.usage.iterations[]?; .type == "fallback_message")
        and .stop_reason != "refusal"
      )
    }'
  ```

  ```bash CLI
  ant beta:messages create \
    --model claude-fable-5 \
    --max-tokens 1024 \
    --message '{"role":"user","content":"Hello, Claude"}' \
    --fallbacks default \
    --beta server-side-fallback-2026-07-01 \
    --format json |
    jq -c '{
      stop_reason,
      model,
      # usage.iterations に fallback_message エントリがあれば、フォールバックモデルが実行されたことを意味します。
      # stop_reason と照合して、フォールバックがレスポンスを返したことを確認します。
      served_by_fallback: (
        any(.usage.iterations[]?; .type == "fallback_message")
        and .stop_reason != "refusal"
      )
    }'
  ```

  ```python Python
  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,
          }
      )
  )
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await 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 と照合して、フォールバックがレスポンスを返したことを確認してください。
  const { stop_reason, model, usage } = response;
  const servedByFallback =
    (usage.iterations ?? []).some((entry) => entry.type === "fallback_message") &&
    stop_reason !== "refusal";

  console.log(
    JSON.stringify({
      stop_reason,
      model,
      served_by_fallback: servedByFallback
    })
  );
  ```

  ```csharp C#
  AnthropicClient client = new();

  var response = await client.Beta.Messages.Create(
      new()
      {
          Model = Messages::Model.ClaudeFable5,
          MaxTokens = 1024,
          Messages =
          [
              new() { Content = "Hello, Claude", Role = Role.User },
          ],
          Fallbacks = new Default(),
          Betas = [AnthropicBeta.ServerSideFallback2026_07_01],
      }
  );

  // usage.iterations に fallback_message エントリがあれば、フォールバックモデルが実行されたことを意味します。
  // stop_reason と併せて確認し、フォールバックが応答を返したことを確かめます。
  bool fallbackRan = (response.Usage.Iterations ?? []).Any(iteration =>
      iteration.TryPickBetaFallbackMessageIterationUsage(out _)
  );
  bool servedByFallback =
      fallbackRan && response.StopReason?.Value() != BetaStopReason.Refusal;

  Console.WriteLine(
      JsonSerializer.Serialize(
          new
          {
              stop_reason = response.StopReason?.Raw(),
              model = response.Model.Raw(),
              served_by_fallback = servedByFallback,
          }
      )
  );
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5,
  	MaxTokens: 1024,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hello, Claude")),
  	},
  	Fallbacks: anthropic.BetaFallbacksParamOfDefault(),
  	Betas:     []anthropic.AnthropicBeta{anthropic.AnthropicBetaServerSideFallback2026_07_01},
  })
  if err != nil {
  	panic(err)
  }

  // usage.iterations に fallback_message エントリがあれば、フォールバックモデルが実行されたことを意味します。
  // stop_reason と照合して、フォールバックがレスポンスを返したことを確認します。
  fallbackRan := slices.ContainsFunc(
  	response.Usage.Iterations,
  	func(iteration anthropic.BetaIterationsUsageItemUnion) bool {
  		_, isFallback := iteration.AsAny().(anthropic.BetaFallbackMessageIterationUsage)
  		return isFallback
  	},
  )
  servedByFallback := fallbackRan && response.StopReason != anthropic.BetaStopReasonRefusal

  summary, err := json.Marshal(struct {
  	StopReason       anthropic.BetaStopReason `json:"stop_reason"`
  	Model            anthropic.Model          `json:"model"`
  	ServedByFallback bool                     `json:"served_by_fallback"`
  }{response.StopReason, response.Model, servedByFallback})
  if err != nil {
  	panic(err)
  }
  fmt.Println(string(summary))
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  BetaMessage response = client.beta().messages().create(
      MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5)
          .maxTokens(1024L)
          .addUserMessage("Hello, Claude")
          .fallbacksDefault()
          .addBeta(AnthropicBeta.SERVER_SIDE_FALLBACK_2026_07_01)
          .build()
  );

  // fallback_messageの使用量エントリは、フォールバックモデルが
  // レスポンスを生成したことを意味し、refusalのstop_reasonはどのモデルも応答しなかったことを意味します。
  List<BetaUsage.Iteration> iterations =
      response.usage().iterations().orElse(List.of());
  boolean servedByFallback =
      iterations.stream().anyMatch(BetaUsage.Iteration::isFallbackMessage)
          && response.stopReason().filter(BetaStopReason.REFUSAL::equals).isEmpty();

  IO.println("""
      {"stop_reason":"%s","model":"%s","served_by_fallback":%b}\
      """.formatted(
          response.stopReason().map(BetaStopReason::asString).orElse("null"),
          response.model().asString(),
          servedByFallback));
  ```

  ```php PHP
  $client = new Client();

  $response = $client->beta->messages->create(
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      model: 'claude-fable-5',
      fallbacks: 'default',
      betas: ['server-side-fallback-2026-07-01'],
  );

  // usage.iterations に fallback_message エントリがあれば、フォールバックモデルが実行されたことを意味します。
  // stop_reason と組み合わせて、フォールバックがレスポンスを返したことを確認します。
  $iterations = $response->usage->iterations ?? [];
  $servedByFallback = array_any($iterations, fn($entry) => $entry->type === 'fallback_message')
      && $response->stopReason !== 'refusal';

  echo json_encode([
      'stop_reason' => $response->stopReason,
      'model' => $response->model,
      'served_by_fallback' => $servedByFallback,
  ]), PHP_EOL;
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  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 と併せて確認し、フォールバックがレスポンスを返したことを確かめます。
  iterations = response.usage.iterations || []
  served_by_fallback = iterations.any? { it.type == :fallback_message } &&
    response.stop_reason != :refusal

  stop_reason = response.stop_reason
  model = response.model
  puts JSON.generate({stop_reason:, model:, served_by_fallback:})
  ```
</CodeGroup>

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

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

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

<Note>
  ベータヘッダーには、`"default"`と明示的リスト形式の両方をサポートする日付`2026-07-01`、または明示的リスト形式のみを受け付ける`2026-06-01`のいずれかを正確に指定する必要があります。それ以外の`server-side-fallback-*`値では、`fallbacks`パラメータは400エラーで拒否されます。この機能の以前のプレビュー版に対して構築していた場合は、ベータヘッダーとリクエストおよびレスポンスの形式を、このページに記載されているものにまとめて更新してください。
</Note>

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

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

指定したフォールバックモデルは[サイズ超過画像チェック](https://platform.claude.com/docs/ja/build-with-claude/vision-coordinates#oversized-image-error)の対象になります。画像ブロックに`"oversized_image": "error"`を設定したリクエストは、リクエストされたモデルと指定されたすべてのフォールバックに対して事前にチェックされ、いずれかがその画像をリサイズすることになる場合は拒否されます。また、拒否時に報告されるリスケール目標はそれらすべてに適合するものになります。

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

<CodeGroup>
  ```bash cURL
  curl --fail-with-body -sS https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "anthropic-version: 2023-06-01" \
    -H "anthropic-beta: server-side-fallback-2026-07-01" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-fable-5",
      "max_tokens": 1024,
      "fallbacks": [{"model": "claude-opus-4-8"}],
      "messages": [{"role": "user", "content": "Hello, Claude"}]
    }'
  ```

  ```bash CLI
  ant beta:messages create \
    --model claude-fable-5 \
    --max-tokens 1024 \
    --message '{"role":"user","content":"Hello, Claude"}' \
    --fallbacks '[{"model":"claude-opus-4-8"}]' \
    --beta server-side-fallback-2026-07-01
  ```

  ```python Python
  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)
  ```

  ```typescript TypeScript
  const client = new Anthropic();

  const response = await 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"]
  });
  console.log(response.model);
  ```

  ```csharp C#
  AnthropicClient client = new();

  BetaMessage response = await client.Beta.Messages.Create(
      new()
      {
          Model = Messages::Model.ClaudeFable5,
          MaxTokens = 1024,
          Messages = [new() { Content = "Hello, Claude", Role = Role.User }],
          Fallbacks = new([new(Messages::Model.ClaudeOpus4_8)]),
          Betas = [AnthropicBeta.ServerSideFallback2026_07_01],
      }
  );

  Console.WriteLine(response.Model.Raw());
  ```

  ```go Go
  client := anthropic.NewClient()

  response, err := client.Beta.Messages.New(context.Background(), anthropic.BetaMessageNewParams{
  	Model:     anthropic.ModelClaudeFable5,
  	MaxTokens: 1024,
  	Messages: []anthropic.BetaMessageParam{
  		anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hello, Claude")),
  	},
  	Fallbacks: anthropic.BetaFallbacksParamUnion{
  		OfBetaFallbackArray: []anthropic.BetaFallbackParam{{Model: anthropic.ModelClaudeOpus4_8}},
  	},
  	Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaServerSideFallback2026_07_01},
  })
  if err != nil {
  	panic(err)
  }

  fmt.Println(response.Model)
  ```

  ```java Java
  AnthropicClient client = AnthropicOkHttpClient.fromEnv();

  BetaMessage response = client.beta().messages().create(MessageCreateParams.builder()
      .model(Model.CLAUDE_FABLE_5)
      .maxTokens(1024L)
      .addUserMessage("Hello, Claude")
      .fallbacksOfFallbackParams(List.of(BetaFallbackParam.builder()
          .model(Model.CLAUDE_OPUS_4_8)
          .build()))
      .addBeta(AnthropicBeta.SERVER_SIDE_FALLBACK_2026_07_01)
      .build());

  IO.println(response.model().asString());
  ```

  ```php PHP
  $client = new Client();

  $response = $client->beta->messages->create(
      model: 'claude-fable-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      fallbacks: [['model' => 'claude-opus-4-8']],
      betas: ['server-side-fallback-2026-07-01'],
  );

  echo $response->model, PHP_EOL;
  ```

  ```ruby Ruby
  client = Anthropic::Client.new

  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"]
  )

  puts response.model
  ```
</CodeGroup>

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

* エントリは順番に試行されます。各エントリは、他のエントリおよびリクエストされたモデルと異なる必要があります。
* 各エントリは、リクエストされたモデルで許可されたターゲットのいずれかである必要があります。ベータヘッダーを設定すると、そのリストは[Models API](https://platform.claude.com/docs/ja/api/models/list)のモデルのエントリに`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を選択した場合：

```json
{
  "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`エントリが付きます。

[スティッキールーティング](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#sticky-routing)により、後続のターンが直接フォールバックモデルに送信されることがあります。そのようなターンには`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`                                  | 結果とペアになっている場合は保持。対応する結果がない場合は削除。                                                                      |

<Note>
  `connector_text`ブロックは、一部のツール使用レスポンスがツール呼び出しの間に含めるナレーションテキストを保持します。
</Note>

### ストリーミング

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

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

* `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`に表示されます。

<Note>
  **ツール使用中の拒否：** 完了したツール作業はフォールバックを妨げません。リクエスト内でサーバーツール（例えば、ウェブ検索やコード実行）の実行が完了した後に拒否が発生した場合、フォールバック試行は続行されます。完了したツール結果は引き継がれ、フォールバックモデルは引き続きサーバーツールを呼び出すことができます。再試行されない唯一のケースは、任意のタイプのツール使用ブロック（クライアントツール、サーバーツール、またはMCPツール呼び出し）がストリーム上でまだ開いている間に発生するストリーミング拒否です。その拒否は直接返され、`fallback-credit-2026-07-01`ヘッダーが設定されている場合は、部分的なレスポンスを続行することで引き換え可能なクレジットトークンが引き続き付与されます。非ストリーミングリクエストは影響を受けません。APIは部分的な作業をクリアし、応答する前に再試行します。
</Note>

### 課金とレート制限

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

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

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

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

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

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

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

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

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

### セットアップ

`BetaRefusalFallbackMiddleware` (typescript: `betaRefusalFallbackMiddleware`; go: `betafallback.BetaRefusalFallbackMiddleware`; csharp: `BetaRefusalFallbackHandler`; java: `BetaRefusalFallbackInterceptor`; php: `RefusalFallbackMiddleware`)をクライアントコンストラクタに渡し、会話のリクエスト間で1つの`BetaFallbackState`インスタンスを共有します。

<CodeGroup exclude="shell">
  <CodeGroupItem language="cURL">
    拒否フォールバックミドルウェアはClaude SDKの一部であるため、cURLリクエストでは使用できません。単一のリクエスト内でフォールバックするには、[サーバーサイドフォールバック](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#server-side-fallback)を使用してください。再試行を自分で記述するには、[フォールバッククレジット](https://platform.claude.com/docs/ja/build-with-claude/fallback-credit)を参照してください。
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    `ant` CLIには拒否フォールバックミドルウェアが含まれていません。単一のリクエスト内でフォールバックするには、[サーバーサイドフォールバック](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#server-side-fallback)を使用してください。再試行を自分で記述するには、[フォールバッククレジット](https://platform.claude.com/docs/ja/build-with-claude/fallback-credit)を参照してください。
  </CodeGroupItem>

  ```python Python
  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}")
  ```

  ```typescript TypeScript
  import { BetaFallbackState, betaRefusalFallbackMiddleware } from "@anthropic-ai/sdk";

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

  // 会話全体で1つの状態を共有し、後続のリクエストが
  // 受け入れたモデルに固定されたままになるようにします。
  const fallbackState = new BetaFallbackState();

  // ストリーミング: 拒否が発生した場合、ミドルウェアはフォールバックモデルで再試行し、
  // そのイベントを開いているストリームに接続します。
  const stream = client.beta.messages
    .stream(
      {
        max_tokens: 1024,
        model: "claude-fable-5",
        messages: [{ role: "user", content: "Hello, Claude" }]
      },
      { fallbackState }
    )
    .on("text", (text) => process.stdout.write(text));

  const finalMessage = await stream.finalMessage();
  console.log("\nserved by:", finalMessage.model);

  // 非ストリーミング: 状態を再利用することで会話が固定されたままになります。
  const message = await client.beta.messages.create(
    {
      max_tokens: 1024,
      model: "claude-fable-5",
      messages: [{ role: "user", content: "Hello, Claude" }]
    },
    { fallbackState }
  );
  console.log("served by:", message.model);
  ```

  ```csharp C#
  using Anthropic;
  using Anthropic.Helpers;
  using Anthropic.Models.Beta.Messages;
  using Messages = Anthropic.Models.Messages;

  // 拒否された場合、ハンドラーは指定されたフォールバックモデルで再試行し、
  // 処理するすべてのリクエストにフォールバッククレジットのベータヘッダーを自動的に送信します。
  AnthropicClient client = new()
  {
      Handlers =
      [
          new BetaRefusalFallbackHandler { Fallbacks = [new(Messages::Model.ClaudeOpus4_8)] },
      ],
  };

  // この状態を共有する後続リクエストを、受け入れたモデルに固定します。
  BetaFallbackState fallbackState = BetaFallbackState.Create();

  MessageCreateParams parameters = new()
  {
      Model = Messages::Model.ClaudeFable5,
      MaxTokens = 1024,
      Messages = [new() { Content = "Hello, Claude", Role = Role.User }],
  };

  // ストリーミング：ストリームが拒否で終了した場合、ハンドラーはフォールバック
  // モデルのイベントを開いたままのストリームに接続します。
  BetaMessageContentAggregator aggregator = new();
  using (fallbackState.Use())
  {
      var responseUpdates = client.Beta.Messages.CreateStreaming(parameters);
      await foreach (BetaRawMessageStreamEvent rawEvent in responseUpdates.CollectAsync(aggregator))
      {
          if (
              rawEvent.TryPickContentBlockDelta(out var deltaEvent)
              && deltaEvent.Delta.TryPickText(out var textDelta)
          )
          {
              Console.Write(textDelta.Text);
          }
      }
  }
  BetaMessage streamedMessage = aggregator.Message();
  Console.WriteLine($"\nserved by: {streamedMessage.Model.Raw()}");

  // 非ストリーミング：状態を再利用すると、会話は受け入れたモデルに固定されたままになります。
  using (fallbackState.Use())
  {
      BetaMessage message = await client.Beta.Messages.Create(parameters);
      Console.WriteLine($"served by: {message.Model.Raw()}");
  }
  ```

  ```go Go
  import (
  // ...
  	"github.com/anthropics/anthropic-sdk-go/lib/betafallback"
  // ...
  )

  func main() {
  	ctx := context.Background()

  	// このミドルウェアは、拒否されたリクエストを各フォールバックモデルで順番に再試行し、
  	// リクエストをfallback-creditベータに自動的にオプトインします。
  	client := anthropic.NewClient(
  		option.WithMiddleware(betafallback.BetaRefusalFallbackMiddleware(
  			[]anthropic.BetaFallbackParam{{Model: anthropic.ModelClaudeOpus4_8}},
  		)),
  	)

  	// 会話ごとに1つの状態: それを共有するリクエストは受け入れたモデルに固定されるため、
  	// フォローアップが拒否したモデルに再度問い合わせることはありません。
  	state := &betafallback.BetaFallbackState{}
  	conversation := betafallback.WithBetaFallbackState(state)

  	params := anthropic.BetaMessageNewParams{
  		MaxTokens: 1024,
  		Model:     anthropic.ModelClaudeFable5,
  		Messages: []anthropic.BetaMessageParam{
  			anthropic.NewBetaUserMessage(anthropic.NewBetaTextBlock("Hello, Claude")),
  		},
  	}

  	// ストリーミング: 拒否時、ミドルウェアはその場で再試行し、フォールバックモデルの
  	// イベントを開いているストリームに1つの連続したメッセージとして接合します。
  	stream := client.Beta.Messages.NewStreaming(ctx, params, conversation)
  	defer stream.Close()
  	var streamed anthropic.BetaMessage
  	for stream.Next() {
  		event := stream.Current()
  		if err := streamed.Accumulate(event); err != nil {
  			panic(err)
  		}
  		switch eventVariant := event.AsAny().(type) {
  		case anthropic.BetaRawContentBlockDeltaEvent:
  			if textDelta, ok := eventVariant.Delta.AsAny().(anthropic.BetaTextDelta); ok {
  				fmt.Print(textDelta.Text)
  			}
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  	fmt.Println("\nserved by:", streamed.Model)

  	// 非ストリーミング: 共有状態により、このフォローアップはストリーミングされたターンを
  	// 処理したモデルに固定されます。
  	message, err := client.Beta.Messages.New(ctx, params, conversation)
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println("served by:", message.Model)
  }
  ```

  ```java Java
  import com.anthropic.client.AnthropicClient;
  import com.anthropic.client.okhttp.AnthropicOkHttpClient;
  import com.anthropic.core.RequestOptions;
  import com.anthropic.core.http.StreamResponse;
  import com.anthropic.helpers.BetaFallbackState;
  import com.anthropic.helpers.BetaMessageAccumulator;
  import com.anthropic.helpers.BetaRefusalFallbackInterceptor;
  import com.anthropic.models.beta.messages.BetaMessage;
  import com.anthropic.models.beta.messages.BetaRawMessageStreamEvent;
  import com.anthropic.models.beta.messages.MessageCreateParams;
  import com.anthropic.models.messages.Model;

  void main() {
      // インターセプターは拒否されたリクエストをフォールバックモデルで再試行します。処理するすべての
      // リクエストにfallback-creditベータヘッダーを自動的に追加します。
      AnthropicClient client = AnthropicOkHttpClient.builder()
          .fromEnv()
          .addInterceptor(BetaRefusalFallbackInterceptor.builder()
              .addFallback(Model.CLAUDE_OPUS_4_8)
              .build())
          .build();

      // リクエスト間で1つの状態を共有し、後続リクエストが受け入れたモデルに固定されるようにします。
      BetaFallbackState state = BetaFallbackState.create();

      MessageCreateParams params = MessageCreateParams.builder()
          .model(Model.CLAUDE_FABLE_5)
          .maxTokens(1024)
          .addUserMessage("Hello, Claude")
          .build();

      // ストリーミング: 拒否時、フォールバックモデルのイベントが開いているストリームに接合されます。
      BetaMessageAccumulator accumulator = BetaMessageAccumulator.create();
      try (StreamResponse<BetaRawMessageStreamEvent> streamResponse = client.beta()
              .messages()
              .createStreaming(params, RequestOptions.builder().fallbackState(state).build())) {
          streamResponse.stream()
              .peek(accumulator::accumulate)
              .forEach(event -> event.contentBlockDelta()
                  .flatMap(deltaEvent -> deltaEvent.delta().text())
                  .ifPresent(textDelta -> IO.print(textDelta.text())));
      }
      IO.println("\nserved by: " + accumulator.message().model().asString());

      // 非ストリーミング: 同じ状態を再利用することで会話が固定されたままになります。
      BetaMessage message = client.beta()
          .messages()
          .create(params, RequestOptions.builder().fallbackState(state).build());
      IO.println("served by: " + message.model().asString());
  }
  ```

  ```php PHP
  use Anthropic\Beta\Messages\BetaRawContentBlockDeltaEvent;
  use Anthropic\Beta\Messages\BetaTextDelta;
  use Anthropic\Client;
  use Anthropic\Lib\Middleware\BetaFallbackState;
  use Anthropic\Lib\Middleware\RefusalFallbackMiddleware;
  use Anthropic\Lib\Streaming\MessageAccumulator;

  // フォールバックチェーンを一度だけ設定します。拒否された場合、ミドルウェアがリクエストを
  // チェーンに沿って再試行し、fallback-creditベータヘッダーを自動的に送信します。
  $client = new Client(
      requestOptions: [
          'middleware' => [new RefusalFallbackMiddleware([['model' => 'claude-opus-4-8']])],
      ],
  );

  // 会話全体で1つの状態を共有し、後続のリクエストが
  // 受け入れたモデルに固定されるようにします。
  $state = new BetaFallbackState();

  // ストリーミング: 拒否された場合、ミドルウェアはフォールバックモデルのイベントを
  // 開いたままのストリームに接合します。アキュムレータのモデルが実際に応答したモデルです。
  $stream = $client->beta->messages->createStream(
      model: 'claude-fable-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      requestOptions: ['fallbackState' => $state],
  );
  $accumulator = MessageAccumulator::forBetaMessages();
  foreach ($stream as $event) {
      $accumulator->accumulate($event);
      if ($event instanceof BetaRawContentBlockDeltaEvent
          && $event->delta instanceof BetaTextDelta) {
          echo $event->delta->text;
      }
  }
  echo "\nserved by: {$accumulator->message()->model}\n";

  // 非ストリーミング: 同じミドルウェアを使用します。状態を再利用することで、会話は
  // 受け入れたモデルに固定されたままになります。
  $message = $client->beta->messages->create(
      model: 'claude-fable-5',
      maxTokens: 1024,
      messages: [['role' => 'user', 'content' => 'Hello, Claude']],
      requestOptions: ['fallbackState' => $state],
  );
  echo "served by: {$message->model}\n";
  ```

  ```ruby Ruby
  # 拒否された場合、ミドルウェアはフォールバックチェーンに沿ってリクエストを再試行します。
  # 処理するすべてのリクエストにfallback-creditベータヘッダーを付与して送信します。
  client = Anthropic::Client.new(
    middleware: [Anthropic::BetaRefusalFallbackMiddleware.new([{model: "claude-opus-4-8"}])]
  )

  # 会話全体で1つの状態を共有し、後続のリクエストが
  # 受け入れたモデルに固定されたままになるようにします。
  state = Anthropic::BetaFallbackState.new

  # ストリーミング：拒否された場合、ミドルウェアはフォールバックモデルの
  # イベントを開いたままのストリームに継ぎ足します。
  stream = client.beta.messages.stream(
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}],
    request_options: {fallback_state: state}
  )
  stream.text.each { print it }
  puts "\nserved by: #{stream.accumulated_message.model}"

  # 非ストリーミング：状態を再利用することで、会話は受け入れたモデルに固定されたままになります。
  message = client.beta.messages.create(
    model: "claude-fable-5",
    max_tokens: 1024,
    messages: [{role: "user", content: "Hello, Claude"}],
    request_options: {fallback_state: state}
  )
  puts "served by: #{message.model}"
  ```
</CodeGroup>

### 動作

* 再試行は、フォールバックリストを順番にたどります。フォールバックモデル自体が拒否した場合、リクエストは次のエントリに渡されます。
* リスト内のすべてのモデルが拒否した場合、ミドルウェアはエラーを発生させるのではなく、最終的な拒否（最後のモデルの拒否レスポンス）を返します。
* 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のみ](https://platform.claude.com/docs/ja/build-with-claude/thinking#preserved-for-model)であるため、APIはそれらを削除します。APIはまた、Claude Fable 5.1とClaude Mythos 5.1を除くすべてのフォールバックモデルについて、Claude Opus 5.5のブロックも削除します（[会話の途中でのモデルの切り替え](https://platform.claude.com/docs/ja/build-with-claude/preserved-thinking#switching-models)を参照）。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`に記録されるため、状態を共有する後続のリクエストは、拒否したモデルに再度問い合わせるのではなく、そのモデルに固定されたままになります。

<Note>
  ミドルウェアとサーバーサイドの`fallbacks`パラメータは同じ役割を果たします。どちらか一方を設定し、同じリクエストで両方を設定しないでください。ミドルウェアをインストールしたアプリケーションからサーバーサイドの`fallbacks`リクエストを送信するには、ミドルウェアなしの別のクライアントインスタンスを使用してください。
</Note>

## 再試行を自分で記述する

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

<Steps>
  <Step title="拒否を検出する">
    レスポンスに`stop_reason: "refusal"`があるか確認します。
  </Step>

  <Step title="フォールバックモデルで再送信する">
    `model`をClaude Opus 4.8などのフォールバックモデルに設定して、同じリクエストを送信します。拒否されたリクエストが`thinking: {"type": "between_tools"}`を送信していた場合は、まず`thinking`を変更してください。その値を受け付けるのはClaude Sonnet 5.5のみであるため、`thinking`を省略するか、フォールバックモデルが受け付ける値を設定してください。`2026-07-01`ヘッダーでの[サーバーサイドフォールバック](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#server-side-fallback)は、Claude Sonnet 5にフォールバックする際にこの変更を自動的に行います。Claude Fable 5.1またはClaude Fable 5が拒否したリクエストは、通常は別のモデルで処理できます。会話履歴の扱い方は、[フォールバッククレジット](https://platform.claude.com/docs/ja/build-with-claude/fallback-credit)を引き換えるかどうかによって異なります：

    * **クレジットを引き換えない場合：** 以前の`thinking`および`redacted_thinking`ブロックはそのまま残すことも、入力トークンを節約するために削除することもできます。いずれにしても、フォールバックモデルは通常それらを使用できません。[Claude Fable 5.1のブロックを読み取れる](https://platform.claude.com/docs/ja/build-with-claude/thinking#preserved-for-model)のは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のブロックも削除します（[会話の途中でのモデルの切り替え](https://platform.claude.com/docs/ja/build-with-claude/preserved-thinking#switching-models)を参照）。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が課金せずにそれらを削除します。
    * **クレジットを引き換える場合：** 引き換えには完全一致が必要なため、本文を変更せずに送信してください。引き換え時には以前のモデルの思考ブロックをサーバーが処理するため、それらを削除しないでください（[拒否されたリクエストと一致する必要があるフィールド](https://platform.claude.com/docs/ja/build-with-claude/fallback-credit#reference)を参照）。
  </Step>

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

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

## Message Batchesにおける拒否

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

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

1. 結果から拒否された項目を収集します。
2. マルチターン履歴内の思考ブロックはそのまま残すか、入力トークンを節約するために削除します。それらを読み取れないフォールバックモデルについては、[手動再試行](https://platform.claude.com/docs/ja/build-with-claude/refusals-and-fallback#manual-retry)と同様に、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"`に等しいかどうかを直接確認してください。

## 次のステップ

<CardGroup>
  <Card title="フォールバッククレジット" icon="scales" href="https://platform.claude.com/docs/ja/build-with-claude/fallback-credit">
    再試行を自分で構築する際に、プロンプトキャッシュのコストを二重に支払うことを避けます。
  </Card>

  <Card title="停止理由とフォールバック" icon="code" href="https://platform.claude.com/docs/ja/build-with-claude/handling-stop-reasons">
    すべての`stop_reason`値とその処理方法。
  </Card>

  <Card title="SDKミドルウェア" icon="settings" href="https://platform.claude.com/docs/ja/cli-sdks-libraries/middleware">
    拒否フォールバックヘルパーを含む、SDKミドルウェアの仕組み。
  </Card>

  <Card title="移行ガイド" icon="arrow-right" href="https://platform.claude.com/docs/ja/models/fable-5-1/migration-guide">
    既存のアプリケーションをClaude Fable 5.1に移行します。
  </Card>
</CardGroup>
