---
title: Отказы и резервная обработка
url: https://platform.claude.com/docs/ru/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 включают классификаторы безопасности, которые могут отклонить запрос. Когда это происходит, вы получаете обычный ответ, а не ошибку, со значением `stop_reason: "refusal"`. Его поле `stop_details.category` указывает область политики (см. [Как выглядит отказ](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#refusal-response)). Обычно вы всё равно можете получить ответ, отправив тот же запрос другой модели Claude. На этой странице показано, как распознать «refusal» (отказ) и как настроить такой повтор.

Прочитайте эту страницу, если вы строите решение на любой из этих моделей и хотите, чтобы отклонённые запросы автоматически переходили к другой модели. Она также применима, если вы увидели `"refusal"` в ответе и хотите узнать, что делать дальше.

Связанные страницы:

* [Причины остановки и резервная обработка](https://platform.claude.com/docs/ru/build-with-claude/handling-stop-reasons): полный список значений `stop_reason`.
* [Резервный кредит](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit): как избежать двойной оплаты стоимости кэша подсказок, когда вы реализуете повтор самостоятельно.
* [Промежуточное ПО SDK](https://platform.claude.com/docs/ru/cli-sdks-libraries/middleware): вспомогательный компонент SDK, который оборачивает всё это.
* [Руководство по резервной обработке и биллингу](https://platform.claude.com/cookbook/fable-5-fallback-billing-guide): проработанный сквозной пример.

Самая простая настройка, доступная в бета-версии в Claude API: задайте для `fallbacks` значение `"default"`, и API повторит отклонённый запрос на «fallback model» (резервной модели), которую Anthropic рекомендует для соответствующей категории отказа. Для категорий без рекомендованной резервной модели отказ остаётся в силе. У Claude Haiku 5.5 нет серверной резервной обработки, поэтому для неё используйте [клиентскую резервную обработку с промежуточным ПО SDK](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#client-side-fallback) или [реализуйте повтор самостоятельно](https://platform.claude.com/docs/ru/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>

В следующих разделах описано, что содержит ответ с отказом, когда использовать серверную или клиентскую резервную обработку и как каждая из них тарифицируется.

## Как выглядит отказ

Отказ — это успешный ответ HTTP 200 с `stop_reason: "refusal"`:

```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/ru/build-with-claude/refusals-and-fallback#server-side-fallback), бета). Указывает модель для прямого повтора, когда API пропустил резервную попытку (например, резервная модель достигла ограничения скорости), и равно `null` в остальных случаях. Это подсказка, а не гарантия.
* `category` и `explanation` оба равны `null`, когда отказ не соответствует именованной категории. Это `null` — нормальное, постоянное значение, а не заглушка.
* Сам `stop_details` равен `null` для любой причины остановки, кроме `refusal`.

| `category`               | Что это означает                                                                                                                                                                                                                                                                                                                                                                                                        | Тарифицируется до какого-либо вывода |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| `"cyber"`                | Запрос может способствовать кибервреду, например разработке вредоносного ПО или эксплойтов. Безобидная работа в области кибербезопасности также может вызвать эту категорию.                                                                                                                                                                                                                                            | Нет                                  |
| `"bio"`                  | Запрос может способствовать биологическому вреду, например опасным лабораторным методам. Полезная работа в области наук о жизни также может вызвать эту категорию.                                                                                                                                                                                                                                                      | Да                                   |
| `"frontier_llm"`         | Запрос может помочь в разработке конкурирующих моделей ИИ, что ограничено [коммерческими условиями Anthropic](https://www.anthropic.com/legal/commercial-terms). Безобидная работа в области машинного обучения также может вызвать эту категорию.                                                                                                                                                                      | Да                                   |
| `"reasoning_extraction"` | Запрос просит модель воспроизвести свои внутренние рассуждения в тексте ответа. Чтобы вместо этого получить рассуждения в структурированной форме, используйте [адаптивные размышления](https://platform.claude.com/docs/ru/build-with-claude/thinking). См. [Храните рассуждения в блоках размышлений](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks). | Да                                   |
| `"general_harms"`        | Запрос относится к области политики использования за пределами четырёх именованных категорий. Безобидная работа также может вызвать эту категорию.                                                                                                                                                                                                                                                                      | Нет                                  |

Отказ может прийти до какого-либо вывода или в середине потока после частичного вывода. В любом случае считайте любой частичный вывод неполным и отбрасывайте его.

### Храните рассуждения в блоках размышлений

Отказ `reasoning_extraction` обычно вызван подсказкой, которая просит модель поместить свои размышления или рассуждения в вывод — дословно или в фиксированном формате. Типичные примеры:

* Раздел `<thinking>`, `<reasoning>` или черновик, который модель заполняет перед ответом
* Поле `reasoning`, `thinking` или `trace` в выводе JSON или во входных данных инструмента
* Личные заметки модели или текущий журнал её рассуждений
* Рассуждения, запрошенные дословно или полностью

Такая формулировка может находиться в «system prompt» (системной подсказке), навыке или описании инструмента, поэтому проверьте и их.

Вы по-прежнему можете попросить Claude объяснить свой ответ. Попросите краткое объяснение, доказательства, лежащие в основе результата, или сводку выполненных действий. Чтобы увидеть, как рассуждала модель, установите `display: "summarized"` и прочитайте [блоки `thinking`](https://platform.claude.com/docs/ru/build-with-claude/thinking#summarized-thinking). У этой категории нет рекомендованной резервной модели, поэтому измените подсказку, а не повторяйте запрос. Если переформулированный запрос всё равно отклоняется, [обратитесь в службу поддержки](https://support.claude.com/en/articles/9015913-how-to-get-support) и укажите [идентификатор запроса](https://platform.claude.com/docs/ru/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"`. Это категории, в которых Anthropic по состоянию на сентябрь 2026 года фиксирует небольшое число «false positives» (ложных срабатываний). Такие отказы тарифицируются как любой другой запрос, по ставкам модели, которая его выполнила. Отказ до какого-либо вывода в любой другой категории или с категорией `null` не тарифицируется. В любом случае `content` пуст, а счётчики токенов отображаются в `usage`. Запрос всё равно учитывается в ваших ограничениях скорости.

**Отказы в середине потока:** отказ в середине потока тарифицирует входные токены и уже переданный вывод по обычным ставкам.

**Резервная обработка:** при использовании резервной обработки отказ, который её вызвал, тарифицируется в дополнение к резервному запросу, если он пришёл в середине потока или относится к одной из тарифицируемых категорий. [Резервный кредит](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit) компенсирует промах кэша подсказок у резервного запроса, поэтому вам не приходится платить за кэширование разговора дважды. Отказ Claude Haiku 5.5 не содержит резервного кредита, поэтому резервный запрос после него оплачивается по полной стоимости записи кэша подсказок резервной модели. О том, как серверная резервная обработка отражает каждую попытку, см. [Биллинг и ограничения скорости](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#billing-and-rate-limits).

Список тарифицируемых категорий может меняться по мере того, как Anthropic продолжает измерять и снижать частоту ложных срабатываний своих мер защиты. Тарифицируемые категории перечислены в столбце **Тарифицируется до какого-либо вывода** [таблицы категорий отказов](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#refusal-response).

## Выбор подхода к резервной обработке

Есть три способа повторить отклонённый запрос на другой модели. Правильный выбор зависит от того, где вы работаете и какой уровень контроля вам нужен.

| Ваша ситуация                                   | Используйте                                                                                                                                                                                             | Почему                                                               |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| Claude API, самая простая настройка             | [Серверная резервная обработка](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#server-side-fallback)                                                                       | Один запрос, один ответ. API выполняет повтор.                       |
| Любая платформа, с использованием SDK Anthropic | [Промежуточное ПО SDK](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#client-side-fallback)                                                                                | Настраивается один раз на клиенте. Повторы происходят автоматически. |
| Чистый HTTP или собственная логика повторов     | [Ручной повтор](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#manual-retry) с [резервным кредитом](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit) | Полный контроль. Резервный кредит снижает стоимость.                 |

Серверная резервная обработка и промежуточное ПО SDK применяют резервный кредит за вас. Страница [Резервный кредит](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit) нужна только тогда, когда вы реализуете повтор самостоятельно. У Claude Haiku 5.5 нет ни серверной резервной обработки, ни резервного кредита, поэтому используйте промежуточное ПО SDK или ручной повтор.

## Серверная резервная обработка

Серверная резервная обработка повторяет отклонённый запрос внутри одного вызова API. В режиме по умолчанию, когда основная модель отклоняет запрос и для категории отказа есть рекомендованная резервная модель, API выполняет тот же запрос на модели, которую Anthropic рекомендует для этой категории. Вместо этого вы можете [указать до трёх собственных резервных моделей](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#naming-your-own-fallback-models). В любом случае вы получаете один ответ, в котором указана ответившая модель, так что ваш пользователь получает ответ за один цикл обмена.

<Note>
  Серверная резервная обработка находится в бета-версии на Claude API. Параметр `fallbacks` не поддерживается в [Message Batches API](https://platform.claude.com/docs/ru/build-with-claude/batch-processing) (элемент пакета, который его содержит, возвращается как результат с ошибкой) и недоступен на Amazon Bedrock, Google Cloud и Microsoft Foundry. На этих платформах используйте вместо него [клиентскую резервную обработку с промежуточным ПО SDK](https://platform.claude.com/docs/ru/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/ru/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"}]
    }'
  ```

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

  # Запись fallback_message в usage.iterations означает, что сработала резервная модель;
  # сопоставьте её со 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"]
  });

  // Запись fallback_message в usage.iterations означает, что сработала резервная модель;
  // сопоставьте её со 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],
      }
  );

  // Запись fallback_message в usage.iterations означает, что сработала резервная модель;
  // сопоставьте её со 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)
  }

  // Запись fallback_message в usage.iterations означает, что сработала резервная модель;
  // сопоставьте её со 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()
  );

  // Запись usage с fallback_message означает, что ответ сформировала резервная
  // модель; stop_reason refusal означает, что ни одна модель его не обслужила.
  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'],
  );

  // Запись fallback_message в usage.iterations означает, что сработала резервная модель;
  // сопоставьте её со 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"]
  )

  # Запись fallback_message в usage.iterations означает, что сработала резервная модель;
  # сопоставьте её со 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/ru/api/models/list). Чтобы узнать, какая модель обслужила отклонённый запрос, проверьте поле верхнего уровня `model` в ответе и найдите запись `fallback_message` в `usage.iterations`, как это делают примеры на этой странице.

Только отклонение классификатором безопасности запускает резервную обработку. Ограничение скорости, перегрузка или ошибка сервера на запрошенной модели возвращаются вам как есть.

<Note>
  Бета-заголовок должен содержать ровно дату `2026-07-01`, которая поддерживает как `"default"`, так и форму явного списка, или `2026-06-01`, которая принимает только форму явного списка. При любом другом значении `server-side-fallback-*` параметр `fallbacks` отклоняется с ошибкой 400. Если вы разрабатывали под более раннюю предварительную версию этой функции, обновите бета-заголовок и формы запроса и ответа вместе до приведённых на этой странице.
</Note>

### Указание собственных резервных моделей

Вместо маршрутизации по умолчанию вы можете задать `fallbacks` как список до трёх моделей. Когда запрошенная модель отклоняет запрос, API выполняет следующую модель в цепочке на том же запросе. Используйте эту форму, когда хотите точно контролировать, какие модели обслуживают отклонённые запросы, например закрепить модель, которую ваше приложение квалифицировало.

Указанные резервные модели учитываются в [проверке слишком больших изображений](https://platform.claude.com/docs/ru/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` применяется несколько правил:

* Записи перебираются по порядку. Каждая должна отличаться от других записей и от запрошенной модели.
* Каждая запись должна входить в число разрешённых целевых моделей для запрошенной модели. При установленном бета-заголовке этот список публикуется как `allowed_fallback_models` в записи модели в [Models API](https://platform.claude.com/docs/ru/api/beta/models/list).
* Каждая запись указывает `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` задайте `thinking` в записи Claude Sonnet 5, иначе запрос будет заранее отклонён.
* Как и в режиме по умолчанию, переключение на резервную модель вызывает только отклонение классификатором безопасности. Ограничение скорости, перегрузка или ошибка сервера на запрошенной модели возвращаются вам как есть.
* Если резервная модель достигла ограничения скорости или перегружена, резервная попытка не выполняется, и вместо этого возвращается предыдущий отказ. В этом случае `stop_details.recommended_model` отказа указывает модель, к которой можно напрямую повторить запрос. Рассчитывайте ограничения скорости резервной модели на ожидаемый объём отказов, иначе под нагрузкой переключения на резервную модель будут превращаться в отказы.

Ответ имеет одинаковую форму в обоих режимах: модель, обслужившая ход, указана в поле верхнего уровня `model`, блок содержимого `fallback` отмечает передачу, а `usage.iterations` фиксирует каждую попытку.

### Что содержит ответ

Ответ выглядит как любое другое сообщение, с двумя дополнениями:

* Поле верхнего уровня `model` сообщает модель, которая создала возвращённое сообщение, будь то запрошенная модель или резервная.

* Блок содержимого `fallback` отмечает каждую точку в `content`, где вывод одной модели сменяется выводом следующей: `{"type": "fallback", "from": {"model": ...}, "to": {"model": ...}}`.

  * `from.model` повторяет строку модели, которую вы отправили, когда отклоняющий переход — это запрошенная модель.
  * `to.model` — всегда разрешённый идентификатор модели, которая продолжает.

При отказе до какого-либо вывода блок `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/ru/build-with-claude/refusals-and-fallback#sticky-routing) может направить последующий ход напрямую к резервной модели. Такой ход не содержит блока содержимого `fallback`, потому что ни одна модель не отклонила этот ход. Определите его по записи `fallback_message` в `usage.iterations`, отсутствию записи `message` для запрошенной модели и полю `model` ответа.

### Продолжение разговора

На следующем ходе отправьте содержимое ассистента обратно в том виде, в котором вы его получили. После резервного перехода в середине вывода `content` может включать типы блоков, которые отклонившая модель создала до передачи. В следующей таблице указано, какие из них сохранять, а какие отбрасывать при повторной отправке хода.

| Тип блока                                                                           | На следующем ходе                                                                                                                                                                                                                          |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `fallback`                                                                          | Сохраните его точно там, где он появился. API использует его позицию для проверки блоков размышлений вокруг него, поэтому запрос, который повторяет блоки размышлений с обеих сторон границы, отклоняется, если блок опущен или перемещён. |
| `text`                                                                              | Сохранить.                                                                                                                                                                                                                                 |
| Любой блок после последнего блока `fallback`                                        | Сохранить.                                                                                                                                                                                                                                 |
| `thinking`, `redacted_thinking` или `connector_text` до последнего блока `fallback` | Отбросить.                                                                                                                                                                                                                                 |
| Клиентский `tool_use` до последнего блока `fallback`                                | Отбросить.                                                                                                                                                                                                                                 |
| `server_tool_use` до последнего блока `fallback`                                    | Сохранить, если он в паре со своим результатом. Отбросить, если у него нет соответствующего результата.                                                                                                                                    |

<Note>
  Блок `connector_text` содержит текст повествования, который некоторые ответы с использованием инструментов включают между вызовами инструментов.
</Note>

### Потоковая передача

При запросе с «streaming» (потоковой передачей) повтор происходит в том же потоке, и ничто из уже полученного вами не становится недействительным. То, что вы видите, зависит от того, когда происходит отклонение.

**Когда отклонение происходит до какого-либо вывода:**

* `message_start` указывает резервную модель, а блок `fallback` является первым блоком содержимого.
* Поскольку `message_start` ожидает начала резервной попытки, время до первого байта включает отклонённую попытку.

**Когда отклонение происходит в середине вывода:**

* Открытый блок содержимого закрывается, и блок `fallback` (обычная пара `content_block_start` и `content_block_stop` без дельт) отмечает границу.
* Резервная модель продолжает с частичного вывода. Только блоки `text` частичного вывода передаются резервной модели в качестве контекста. Другие типы блоков остаются в `content`.
* `message_start` уже указал запрошенную модель, поэтому считывайте обслуживающую модель из `to.model` блока `fallback` и из записи `fallback_message` в `usage.iterations` финального `message_delta`.

### Непотоковые ответы

При непотоковом запросе отклонение в середине вывода ведёт себя иначе: ответ опускает частичный вывод отклонившей модели, и резервная модель отвечает с нуля. Результат выглядит как отклонение до какого-либо вывода, с блоком `fallback` первым. Отклонённая попытка и её выходные токены всё равно отображаются в `usage.iterations`.

<Note>
  **Отклонения во время использования инструментов:** завершённая работа инструментов не блокирует резервную обработку. Когда отклонение срабатывает после того, как серверные инструменты (например, веб-поиск или выполнение кода) завершили выполнение в рамках запроса, резервная попытка продолжается: завершённые результаты инструментов переносятся, и резервная модель может продолжать вызывать серверные инструменты. Единственный случай, в котором повтор не выполняется, — это потоковое отклонение, которое срабатывает, пока блок использования инструмента любого типа (клиентский инструмент, серверный инструмент или вызов инструмента MCP) всё ещё открыт в потоке: этот отказ возвращается напрямую, и если установлен заголовок `fallback-credit-2026-07-01`, он всё равно содержит токен кредита, который можно погасить, продолжив частичный ответ. Непотоковые запросы не затрагиваются; API очищает частичную работу и повторяет перед ответом.
</Note>

### Биллинг и ограничения скорости

К каждой попытке применяются правила из раздела [Как тарифицируются отказы](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#how-refusals-are-billed) и ставки модели, которая её выполняла. Попытка, отклонённая до создания какого-либо вывода, тарифицируется, только если тарифицируется категория её отказа, а её токены в любом случае сообщаются в её записи `usage.iterations`. Каждая попытка, создавшая вывод, включая ту, что была отклонена в середине ответа, тарифицируется отдельно. Массив `usage.iterations` — это запись по попыткам того, за что вам выставляется счёт. Счётчики верхнего уровня `usage` описывают только попытку, создавшую возвращённое сообщение. Токены разных моделей никогда не суммируются в одно поле.

Каждая выполненная попытка, включая отклонённую, учитывается в ограничениях скорости своей собственной модели.

### Закреплённая маршрутизация

После того как разговор перешёл на резервную модель, API записывает, какая модель его обслужила. Последующие запросы для этого разговора, включающие `fallbacks`, направляются напрямую к этой резервной модели без запуска запрошенной модели. Это позволяет избежать оплаты попытки, которая предсказуемо была бы снова отклонена на каждом ходе.

Несколько свойств решения о маршрутизации:

* Оно сохраняется примерно 1 час и ограничено вашей организацией.
* Оно хранится как хэш содержимого префикса разговора плюс модель, которая его обслужила. Само содержимое сообщений не хранится.
* Оно работает по принципу «best-effort» (без гарантий), поэтому ваш код должен обрабатывать ситуацию, когда запрошенная модель пробуется снова в любой момент.

Закреплённая маршрутизация применяется как к потоковым, так и к непотоковым запросам. При потоковом запросе решение о маршрутизации принимается до открытия потока, поэтому поле `model` события `message_start` уже содержит идентификатор резервной модели.

## Клиентская резервная обработка с промежуточным ПО 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`) в конструктор клиента и используйте один экземпляр `BetaFallbackState` для всех запросов разговора.

<CodeGroup exclude="shell">
  <CodeGroupItem language="cURL">
    Промежуточное ПО для резервной обработки отказов является частью Claude SDK, поэтому запрос cURL не может его использовать. Чтобы перейти на резервную модель в рамках одного запроса, используйте [серверную резервную обработку](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#server-side-fallback). Чтобы реализовать повтор самостоятельно, см. [Резервный кредит](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit).
  </CodeGroupItem>

  <CodeGroupItem language="CLI">
    CLI `ant` не включает промежуточное ПО для резервной обработки отказов. Чтобы перейти на резервную модель в рамках одного запроса, используйте [серверную резервную обработку](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#server-side-fallback). Чтобы реализовать повтор самостоятельно, см. [Резервный кредит](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit).
  </CodeGroupItem>

  ```python Python
  from anthropic import Anthropic, BetaFallbackState, BetaRefusalFallbackMiddleware

  # При отказе middleware повторяет запрос на указанной резервной модели и
  # автоматически отправляет бета-заголовок fallback-credit с каждым обрабатываемым запросом.
  client = Anthropic(
      middleware=[BetaRefusalFallbackMiddleware([{"model": "claude-opus-4-8"}])],
  )

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

  # Потоковая передача: при отказе middleware повторяет запрос на резервной модели и
  # вставляет её события в открытый поток.
  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";

  // При отказе middleware повторяет запрос на указанной резервной модели и
  // автоматически отправляет beta-заголовок fallback-credit с каждым обрабатываемым запросом.
  const client = new Anthropic({
    middleware: [betaRefusalFallbackMiddleware([{ model: "claude-opus-4-8" }])]
  });

  // Используйте одно состояние на весь диалог, чтобы последующие запросы оставались
  // привязанными к модели, которая приняла запрос.
  const fallbackState = new BetaFallbackState();

  // Потоковая передача: при отказе middleware повторяет запрос на резервной модели и
  // встраивает её события в открытый поток.
  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;

  // При отказе обработчик повторяет запрос на указанной резервной модели и
  // автоматически отправляет бета-заголовок fallback-credit с каждым обрабатываемым запросом.
  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()

  	// Middleware повторяет отклонённый запрос на каждой резервной модели по
  	// очереди и автоматически включает запросы в бету fallback-credit.
  	client := anthropic.NewClient(
  		option.WithMiddleware(betafallback.BetaRefusalFallbackMiddleware(
  			[]anthropic.BetaFallbackParam{{Model: anthropic.ModelClaudeOpus4_8}},
  		)),
  	)

  	// Одно состояние на диалог: запросы с общим состоянием закреплены за
  	// принявшей моделью, и последующий запрос не обращается к отказавшей модели.
  	state := &betafallback.BetaFallbackState{}
  	conversation := betafallback.WithBetaFallbackState(state)

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

  	// Потоковая передача: при отказе middleware повторяет запрос на месте, вставляя
  	// события резервной модели в открытый поток как одно непрерывное сообщение.
  	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();

      // Используйте одно состояние для всех запросов, чтобы последующие оставались привязаны к принявшей модели.
      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;

  // Настройте цепочку резервных моделей один раз. При отказе middleware повторяет
  // запрос далее по цепочке и отправляет бета-заголовок fallback-credit за вас.
  $client = new Client(
      requestOptions: [
          'middleware' => [new RefusalFallbackMiddleware([['model' => 'claude-opus-4-8']])],
      ],
  );

  // Используйте одно состояние на весь диалог, чтобы последующие запросы оставались
  // привязаны к модели, принявшей запрос.
  $state = new BetaFallbackState();

  // Потоковая передача: при отказе middleware вставляет события резервной модели
  // в ещё открытый поток. Модель аккумулятора — это обслуживающая модель.
  $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";

  // Без потоковой передачи: тот же middleware. Повторное использование состояния
  // сохраняет привязку диалога к модели, принявшей запрос.
  $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
  # При отказе middleware повторяет запрос по цепочке резервных моделей.
  # Он отправляет бета-заголовок fallback-credit с каждым обрабатываемым запросом.
  client = Anthropic::Client.new(
    middleware: [Anthropic::BetaRefusalFallbackMiddleware.new([{model: "claude-opus-4-8"}])]
  )

  # Используйте одно состояние на весь диалог, чтобы последующие запросы оставались
  # закреплены за моделью, принявшей запрос.
  state = Anthropic::BetaFallbackState.new

  # Потоковая передача: при отказе middleware встраивает события резервной модели
  # в ещё открытый поток.
  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/ru/build-with-claude/thinking#preserved-for-model), поэтому API их отбрасывает. API также отбрасывает блоки Claude Opus 5.5 для всех резервных моделей, кроме Claude Fable 5.1 и Claude Mythos 5.1 (см. [Переключение моделей посреди разговора](https://platform.claude.com/docs/ru/build-with-claude/preserved-thinking#switching-models)). Он отбрасывает и блоки Claude Sonnet 5.5 для всех резервных моделей, кроме Claude Opus 5.5 в Claude API и Google Cloud. Claude Opus 5.5 и Claude Sonnet 5.5 читают блоки Claude Haiku 5.5 в Claude API и Google Cloud, а для резервной модели, которая не может их читать, 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` или задайте значение, которое принимает резервная модель. [Серверная резервная обработка](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#server-side-fallback) при заголовке `2026-07-01` вносит это изменение за вас при переключении на Claude Sonnet 5. Другая модель обычно может обслужить запрос, который отклоняет Claude Fable 5.1 или Claude Fable 5. То, как вы обрабатываете историю разговора, зависит от того, погашаете ли вы [резервный кредит](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit):

    * **Без погашения кредита:** вы можете оставить предыдущие блоки `thinking` и `redacted_thinking` на месте или удалить их, чтобы сэкономить входные токены. Резервная модель обычно не может их использовать в любом случае: только Claude Fable 5.1 и Claude Mythos 5.1 [читают блоки Claude Fable 5.1](https://platform.claude.com/docs/ru/build-with-claude/thinking#preserved-for-model), и только эти две модели, а также Claude Fable 5 и Claude Mythos 5 читают блоки Claude Fable 5, поэтому для любой другой резервной модели API их отбрасывает. API также отбрасывает блоки Claude Opus 5.5 для всех резервных моделей, кроме Claude Fable 5.1 и Claude Mythos 5.1 (см. [Переключение моделей посреди разговора](https://platform.claude.com/docs/ru/build-with-claude/preserved-thinking#switching-models)). Он отбрасывает и блоки Claude Sonnet 5.5 для всех резервных моделей, кроме Claude Opus 5.5 в Claude API и Google Cloud. Повтор после отказа Claude Haiku 5.5 всегда относится к этому случаю. Claude Opus 5.5 и Claude Sonnet 5.5 читают блоки Claude Haiku 5.5 в Claude API и Google Cloud, поэтому на этих платформах оставляйте эти блоки на месте при переключении на любую из этих двух моделей. Для резервной модели, которая не может их читать, API отбрасывает их, не тарифицируя.
    * **С погашением кредита:** отправьте тело без изменений, поскольку для погашения требуется точное совпадение. При погашении сервер сам обрабатывает блоки размышлений предыдущей модели, поэтому не удаляйте их (см. [Поля, которые должны совпадать с отклонённым запросом](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit#reference)).
  </Step>

  <Step title="Оставайтесь на резервной модели">
    В многоходовых разговорах продолжайте использовать резервную модель для последующих ходов, а не переключайтесь обратно.
  </Step>
</Steps>

Ручной повтор записывает кэш подсказок резервной модели с нуля, что стоит дороже, чем чтение существующего кэша. [Резервный кредит](https://platform.claude.com/docs/ru/build-with-claude/fallback-credit) возмещает эту стоимость; погашайте его при каждом повторе, который вы реализуете самостоятельно. Отказ Claude Haiku 5.5 не содержит резервного кредита, поэтому повтор после него оплачивается по полной стоимости записи кэша подсказок резервной модели.

## Отказы в Message Batches

Отклонённый запрос в [Message Batch](https://platform.claude.com/docs/ru/build-with-claude/batch-processing) возвращается как `result.type: "succeeded"` с `stop_reason: "refusal"`. Результаты пакетов содержат тот же объект `stop_details`, что и синхронные ответы, поэтому вы можете обнаруживать отказы либо через `stop_reason`, либо через `stop_details.type`. Одно отличие: пакетные отказы не создают резервных кредитов, поэтому `stop_details` в результате пакета никогда не включает `fallback_credit_token`.

Серверная резервная обработка недоступна для пакетов (пакетный запрос, включающий `fallbacks`, даёт результат с ошибкой для каждого элемента). Чтобы повторить отклонённые элементы пакета:

1. Соберите отклонённые элементы из результатов.
2. Оставьте блоки размышлений в многоходовых историях на месте или удалите их, чтобы сэкономить входные токены. Для резервной модели, которая не может их читать, API отбрасывает их, не тарифицируя, как и при [ручном повторе](https://platform.claude.com/docs/ru/build-with-claude/refusals-and-fallback#manual-retry).
3. Если отклонённый элемент отправлял `thinking: {"type": "between_tools"}`, опустите `thinking` или задайте значение, которое принимает резервная модель. Только Claude Sonnet 5.5 принимает `between_tools`.
4. Отправьте их повторно на резервную модель в виде нового пакета или прямых запросов.

## Распространённые ошибки

* **Повторяйте на другой модели.** Повторная отправка отклонённого запроса той же модели обычно приводит к ещё одному отказу. Направляйте повтор на резервную модель.
* **Планируйте бюджет повторов на запрос, а не на ход или сессию.** Один ход может породить несколько отказов, например агент плюс его субагенты.
* **Настраивайте резервную обработку на каждом пути запроса.** Обработчики повторов, ветви восстановления после ошибок и фоновые рабочие процессы — всем она нужна. Обработчик, который повторно выдаёт запрос без резервной обработки, теряет защиту именно на тех запросах, которым она, скорее всего, понадобится.
* **Давайте вызовам субагентов собственную резервную обработку.** Параметр `fallbacks` не распространяется на вызовы моделей, выполняемые изнутри выполнения инструментов.
* **Делайте резервную обработку свойством запроса, а не окружающего состояния.** Общий флаг, кэшированное значение конфигурации или глобальный переключатель могут рассинхронизироваться и незаметно оставить запрос без защиты. Когда вы не можете подтвердить, что резервная обработка активна, настройте её, а не предполагайте, что она включена.
* **Инструментируйте отказы как отдельный сигнал.** Отказ — это HTTP 200, поэтому мониторинг, построенный на частоте ошибок или ответах 5xx, никогда его не увидит. Генерируйте одно событие на каждый отказ и одно на каждый ответ, обслуженный резервной моделью (запись `fallback_message` в `usage.iterations` отмечает последний), затем настройте оповещение о разнице между двумя счётчиками.
* **Ветвитесь по `stop_reason` или `stop_details.type`, а не по `content` или внутренним полям `stop_details`.** Объект `stop_details` всегда присутствует при отказе, но его поля `category` и `explanation` могут быть `null`. Проверяйте напрямую, что `stop_reason` равен `"refusal"`.

## Следующие шаги

<CardGroup>
  <Card title="Резервный кредит" icon="scales" href="https://platform.claude.com/docs/ru/build-with-claude/fallback-credit">
    Избегайте двойной оплаты стоимости кэша подсказок, когда реализуете повтор самостоятельно.
  </Card>

  <Card title="Причины остановки и резервная обработка" icon="code" href="https://platform.claude.com/docs/ru/build-with-claude/handling-stop-reasons">
    Каждое значение `stop_reason` и как его обрабатывать.
  </Card>

  <Card title="Промежуточное ПО SDK" icon="settings" href="https://platform.claude.com/docs/ru/cli-sdks-libraries/middleware">
    Как работает промежуточное ПО SDK, включая вспомогательный компонент резервной обработки отказов.
  </Card>

  <Card title="Руководство по миграции" icon="arrow-right" href="https://platform.claude.com/docs/ru/models/fable-5-1/migration-guide">
    Перенесите существующее приложение на Claude Fable 5.1.
  </Card>
</CardGroup>
