Отказы и резервная обработка
Как модели Claude Fable и Claude Opus возвращают отказы классификатора и как повторить отклонённые запросы на резервной модели.
Claude Fable 5.1, Claude Fable 5 и Claude Opus 5 включают классификаторы безопасности, которые могут отклонить запрос. Когда это происходит, вы получаете обычный ответ, а не ошибку, с stop_reason: "refusal". Его поле stop_details.category указывает область политики (см. Как выглядит отказ). Обычно вы всё равно можете получить ответ, отправив тот же запрос другой модели Claude. На этой странице показано, как распознать «refusal» (отказ) и как настроить такой повтор.
Прочитайте эту страницу, если вы строите решение на любой из этих моделей и хотите, чтобы отклонённые запросы автоматически переходили к другой модели. Она также применима, если вы увидели "refusal" в ответе и хотите узнать, что делать дальше.
Связанные страницы:
- Причины остановки и резервная обработка: полный список значений
stop_reason. - Резервный кредит: как избежать двойной оплаты стоимости кэша подсказок, когда вы реализуете повтор самостоятельно.
- Промежуточное ПО SDK: вспомогательный компонент SDK, который оборачивает всё это.
- Руководство по резервной обработке и биллингу: проработанный сквозной пример.
Самая простая настройка, в бета-версии на Claude API: установите fallbacks в значение "default", и API повторит отклонённый запрос на «fallback model» (резервной модели), которую Anthropic рекомендует для его категории отказа. Для категорий без рекомендованной резервной модели отказ остаётся в силе.
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)В следующих разделах описано, что содержит ответ с отказом, когда использовать серверную или клиентскую резервную обработку и как каждая из них тарифицируется.
Как выглядит отказ
Отказ — это успешный ответ HTTP 200 с stop_reason: "refusal":
{
"id": "msg_01XFUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"model": "claude-fable-5",
"content": [],
"stop_reason": "refusal",
"stop_details": {
"type": "refusal",
"category": "cyber",
"explanation": "This request was declined because it could enable cyber harm."
},
"usage": {
"input_tokens": 412,
"output_tokens": 0
}
}Объект stop_details объясняет отклонение:
category: указывает область политики, которая вызвала срабатывание классификатора.explanation: человекочитаемое описание. Текст не является стабильным, поэтому отображайте его, а не разбирайте программно.recommended_model: присутствует только в запросах, которые задаютfallbacks(серверная резервная обработка, бета). Указывает модель для прямого повтора, когда API пропустил резервную попытку (например, резервная модель достигла ограничения скорости), и равноnullв остальных случаях. Это подсказка, а не гарантия.categoryиexplanationоба равныnull, когда отказ не соответствует именованной категории. Этоnull— нормальное, постоянное значение, а не заглушка.- Сам
stop_detailsравенnullдля любой причины остановки, кромеrefusal.
category | Что это означает |
|---|---|
"cyber" | Запрос может способствовать кибервреду, например разработке вредоносного ПО или эксплойтов. Безобидная работа в области кибербезопасности также может вызвать эту категорию. |
"bio" | Запрос может способствовать биологическому вреду, например опасным лабораторным методам. Полезная работа в области наук о жизни также может вызвать эту категорию. |
"frontier_llm" | Запрос может помочь в разработке конкурирующих моделей ИИ, что ограничено коммерческими условиями Anthropic. Безобидная работа в области машинного обучения также может вызвать эту категорию. |
"reasoning_extraction" | Запрос просит модель воспроизвести её внутренние рассуждения в тексте ответа. Чтобы вместо этого получить рассуждения в структурированной форме, используйте адаптивное мышление. |
"general_harms" | Запрос относится к области политики использования за пределами четырёх именованных категорий. Безобидная работа также может вызвать эту категорию. |
Отказ может прийти до какого-либо вывода или в середине потока после частичного вывода. В любом случае считайте любой частичный вывод неполным и отбрасывайте его.
Выбор подхода к резервной обработке
Есть три способа повторить отклонённый запрос на другой модели. Правильный выбор зависит от того, где вы работаете и какой уровень контроля вам нужен.
| Ваша ситуация | Используйте | Почему |
|---|---|---|
| Claude API, самая простая настройка | Серверная резервная обработка | Один запрос, один ответ. API выполняет повтор. |
| Любая платформа, с использованием SDK Anthropic | Промежуточное ПО SDK | Настраивается один раз на клиенте. Повторы происходят автоматически. |
| Чистый HTTP или собственная логика повторов | Ручной повтор с резервным кредитом | Полный контроль. Резервный кредит снижает стоимость. |
Серверная резервная обработка и промежуточное ПО SDK применяют резервный кредит за вас. Страница Резервный кредит нужна вам только тогда, когда вы реализуете повтор самостоятельно.
Серверная резервная обработка
Серверная резервная обработка повторяет отклонённый запрос внутри одного вызова API. В режиме по умолчанию, когда основная модель отклоняет запрос и для категории отказа есть рекомендованная резервная модель, API выполняет тот же запрос на модели, которую Anthropic рекомендует для этой категории. Вместо этого вы можете указать до трёх собственных резервных моделей. В любом случае вы получаете один ответ, в котором указана ответившая модель, так что ваш пользователь получает ответ за один цикл обмена.
Выполнение запроса
Установите параметр fallbacks в строку "default" и отправьте бета-заголовок server-side-fallback-2026-07-01. Затем API применяет определённую на сервере маршрутизацию по умолчанию для запрошенной модели, которая выбирает рекомендованную резервную модель на основе категории отказа, сообщаемой классификатором, так что отклонённые запросы обслуживаются без необходимости поддерживать список моделей по мере изменения рекомендаций.
Маршрутизация по умолчанию никогда не вызывает предварительное отклонение из-за слишком большого изображения для моделей, которые вы не выбирали: маршрутизируемая модель, которая изменила бы размер изображения, помеченного "oversized_image": "error", вместо этого исключается из маршрутизации, поэтому помеченное изображение никогда не обслуживается с изменённым размером.
client = Anthropic()
response = client.beta.messages.create(
model="claude-fable-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
fallbacks="default",
betas=["server-side-fallback-2026-07-01"],
)
# Запись 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,
}
)
)Anthropic устанавливает защитные меры для каждой модели индивидуально и для каждой категории политики в соответствии с возможностями модели: в зависимости от категории помеченный запрос может перейти к менее мощной модели или быть отклонён. Режим "default" кодирует эти рекомендации по моделям и категориям за вас, так что отклонённый запрос повторяется на модели, которую Anthropic рекомендует для этой категории. Резервные переходы видны в любом случае: в ответе указана модель, которая его обслужила, а блок содержимого fallback отмечает передачу.
Маршрутизация применяется на стороне сервера и не публикуется для каждой модели в Models API. Чтобы узнать, какая модель обслужила отклонённый запрос, проверьте поле верхнего уровня model в ответе и найдите запись fallback_message в usage.iterations, как это делают примеры на этой странице.
Только отклонение классификатором безопасности запускает резервную обработку. Ограничение скорости, перегрузка или ошибка сервера на запрошенной модели возвращаются вам как есть.
Указание собственных резервных моделей
Вместо маршрутизации по умолчанию вы можете задать fallbacks как список до трёх моделей. Когда запрошенная модель отклоняет запрос, API выполняет следующую модель в цепочке на том же запросе. Используйте эту форму, когда хотите точно контролировать, какие модели обслуживают отклонённые запросы, например закрепить модель, которую ваше приложение квалифицировало.
Указанные резервные модели учитываются в проверке слишком больших изображений: запрос, в блоке изображения которого задано "oversized_image": "error", предварительно проверяется относительно запрошенной модели и каждой указанной резервной модели, отклоняется, если любая из них изменила бы размер этого изображения, а сообщаемая в отклонении целевая величина масштабирования подходит для всех них.
Выделенные строки — единственное отличие от запроса с маршрутизацией по умолчанию.
client = Anthropic()
response = client.beta.messages.create(
model="claude-fable-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello, Claude"}],
fallbacks=[{"model": "claude-opus-4-8"}],
betas=["server-side-fallback-2026-07-01"],
)
print(response.model)К списку fallbacks применяется несколько правил:
- Записи пробуются по порядку. Каждая должна отличаться от других записей и от запрошенной модели.
- Каждая запись должна быть одной из разрешённых целей запрошенной модели. При установленном бета-заголовке этот список публикуется как
allowed_fallback_modelsв записи модели в Models API. - Каждая запись указывает
modelи может переопределятьmax_tokens,thinking,output_configиspeedтолько для этой попытки. - Запрос должен быть допустимым как прямой запрос к каждой указанной модели. Если резервная модель не поддерживает функцию, которую использует запрос, API отклоняет запрос заранее.
- Как и в режиме по умолчанию, только отклонение классификатором безопасности запускает резервную обработку. Ограничение скорости, перегрузка или ошибка сервера на запрошенной модели возвращаются вам как есть.
- Если резервная модель достигла ограничения скорости или перегружена, резервная попытка не выполняется, и вместо неё возвращается предшествующий отказ. Поле
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 для категории отказа:
{
"id": "msg_01XFUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"model": "claude-opus-4-8",
"content": [
{
"type": "fallback",
"from": { "model": "claude-fable-5" },
"to": { "model": "claude-opus-4-8" }
},
{ "type": "text", "text": "Hi! How can I help you today?" }
],
"stop_reason": "end_turn",
"stop_details": null,
"usage": {
"input_tokens": 412,
"output_tokens": 264,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0,
"iterations": [
{
"type": "message",
"model": "claude-fable-5",
"input_tokens": 535,
"output_tokens": 0,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
},
{
"type": "fallback_message",
"model": "claude-opus-4-8",
"input_tokens": 412,
"output_tokens": 264,
"cache_read_input_tokens": 0,
"cache_creation_input_tokens": 0
}
]
}
}Массив usage.iterations фиксирует каждую попытку. Модель, которая отклонила запрос, отображается как обычная запись message, а модель, обслужившая ход, — как запись fallback_message. Если каждая модель в цепочке отклоняет запрос, ответом является отказ последней модели, с записью message для каждого предыдущего перехода и записью fallback_message для последнего.
Закреплённая маршрутизация может направить последующий ход напрямую к резервной модели. Такой ход не содержит блока содержимого fallback, потому что ни одна модель не отклонила этот ход. Определите его по записи fallback_message в usage.iterations, отсутствию записи message для запрошенной модели и полю model ответа.
Продолжение разговора
На следующем ходе отправьте содержимое ассистента обратно в том виде, в котором вы его получили. После резервного перехода в середине вывода content может включать типы блоков, которые отклонившая модель создала до передачи. В следующей таблице указано, какие из них сохранять, а какие отбрасывать при повторной отправке хода.
| Тип блока | На следующем ходе |
|---|---|
fallback | Сохраните его точно там, где он появился. API использует его позицию для проверки блоков мышления вокруг него, поэтому запрос, который повторяет блоки мышления с обеих сторон границы, отклоняется, если блок опущен или перемещён. |
text | Сохранить. |
Любой блок после последнего блока fallback | Сохранить. |
thinking, redacted_thinking или connector_text до последнего блока fallback | Отбросить. |
Клиентский tool_use до последнего блока fallback | Отбросить. |
server_tool_use до последнего блока fallback | Сохранить, если он в паре со своим результатом. Отбросить, если у него нет соответствующего результата. |
Потоковая передача
При запросе с «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.
Биллинг и ограничения скорости
Попытка, отклонённая до создания какого-либо вывода, не тарифицируется: её токены сообщаются в её записи usage.iterations, но не оплачиваются. Каждая попытка, создавшая вывод, включая ту, что была отклонена в середине ответа, тарифицируется отдельно по ставкам модели, которая её выполняла. Массив usage.iterations — это запись по попыткам того, за что вам выставляется счёт. Счётчики верхнего уровня usage описывают только попытку, создавшую возвращённое сообщение. Токены разных моделей никогда не суммируются в одно поле.
Каждая выполненная попытка, включая отклонённую, учитывается в ограничениях скорости своей собственной модели.
Закреплённая маршрутизация
После того как разговор перешёл на резервную модель, API записывает, какая модель его обслужила. Последующие запросы для этого разговора, включающие fallbacks, направляются напрямую к этой резервной модели без запуска запрошенной модели. Это позволяет избежать оплаты попытки, которая предсказуемо была бы снова отклонена на каждом ходе.
Несколько свойств решения о маршрутизации:
- Оно сохраняется примерно 1 час и ограничено вашей организацией.
- Оно хранится как хэш содержимого префикса разговора плюс модель, которая его обслужила. Само содержимое сообщений не хранится.
- Оно работает по принципу «best-effort» (без гарантий), поэтому ваш код должен обрабатывать ситуацию, когда запрошенная модель пробуется снова в любой момент.
Закреплённая маршрутизация применяется как к потоковым, так и к непотоковым запросам. При потоковом запросе решение о маршрутизации принимается до открытия потока, поэтому поле model события message_start уже содержит идентификатор резервной модели.
Клиентская резервная обработка с промежуточным ПО SDK
Каждый SDK Anthropic включает «middleware» (промежуточное ПО) для резервной обработки отказов. Вы настраиваете его один раз на клиенте со своим списком резервных моделей. Вызовы через client.beta.messages затем автоматически повторяют отклонённые запросы на любой платформе. Промежуточное ПО также отправляет бета-заголовок fallback-credit-2026-07-01 с каждым обрабатываемым запросом, так что повторы переоцениваются без настройки для каждого запроса.
Настройка
Передайте промежуточное ПО в конструктор клиента и используйте один экземпляр BetaFallbackState для всех запросов разговора.
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}")Как оно работает
- Повторы проходят по вашему списку резервных моделей по порядку. Резервная модель, которая сама отказывает, передаёт запрос следующей записи.
- Когда каждая модель в списке отклонила запрос, промежуточное ПО возвращает финальный отказ (ответ с отказом последней модели), а не выбрасывает ошибку.
- Блоки мышления от Claude Fable 5.1 или Claude Fable 5 проходят без изменений. Каждый повтор заново отправляет ваше исходное тело запроса, и единственные блоки, которые промежуточное ПО удаляет из истории разговора в последующих запросах, — это граничные блоки
fallback, которые оно добавило само. Резервная модель не может читать блоки Claude Fable 5.1, которые сохраняются только для этой модели или более новой, поэтому API их отбрасывает. - Ответы, обслуженные через промежуточное ПО, включают блок содержимого
fallbackна каждой границе моделей, так же как ответы серверной резервной обработки. Промежуточное ПО управляет этими блоками за вас в последующих запросах. - Модель, которая приняла запрос, записывается в
BetaFallbackState, поэтому последующие запросы, использующие то же состояние, остаются закреплёнными за ней, а не повторно обращаются к модели, которая отказала.
Самостоятельная реализация повтора
При работе через чистый HTTP или с собственной логикой повторов реализуйте шаблон, который оборачивает промежуточное ПО:
Обнаружьте отказ
Проверьте ответ на наличие
stop_reason: "refusal".Повторно отправьте на резервную модель
Отправьте тот же запрос с
model, установленным на резервную модель, например Claude Opus 4.8. Другая модель обычно может обслужить запрос, который отклоняет Claude Fable 5.1 или Claude Fable 5. То, как вы обрабатываете историю разговора, зависит от того, погашаете ли вы резервный кредит:- Без погашения кредита: вы можете оставить предыдущие блоки
thinkingиredacted_thinkingна месте или удалить их, чтобы сэкономить входные токены. Резервная модель в любом случае не может их использовать: она игнорирует блоки Claude Fable 5, а блоки Claude Fable 5.1 сохраняются только для этой модели или более новой, поэтому API их отбрасывает. - С погашением кредита: отправьте тело без изменений, потому что погашение требует точного совпадения. Сервер обрабатывает блоки мышления предыдущей модели при погашении, поэтому не удаляйте их (см. Поля, которые должны совпадать с отклонённым запросом).
- Без погашения кредита: вы можете оставить предыдущие блоки
Оставайтесь на резервной модели
Для многоходовых разговоров продолжайте использовать резервную модель для последующих ходов, а не переключайтесь обратно.
Ручной повтор записывает кэш подсказок резервной модели с нуля, что стоит дороже, чем чтение существующего кэша. Резервный кредит возмещает эту стоимость; погашайте его при каждом повторе, который вы реализуете самостоятельно.
Отказы в Message Batches
Отклонённый запрос в Message Batch возвращается как result.type: "succeeded" с stop_reason: "refusal". Результаты пакетов содержат тот же объект stop_details, что и синхронные ответы, поэтому вы можете обнаруживать отказы либо через stop_reason, либо через stop_details.type. Одно отличие: пакетные отказы не создают резервных кредитов, поэтому stop_details в результате пакета никогда не включает fallback_credit_token.
Серверная резервная обработка недоступна для пакетов (пакетный запрос, включающий fallbacks, даёт результат с ошибкой для каждого элемента). Чтобы повторить отклонённые элементы пакета:
- Соберите отклонённые элементы из результатов.
- Удалите блоки мышления Claude Fable 5.1 или Claude Fable 5 из любых многоходовых историй.
- Повторно отправьте их на резервную модель как новый пакет или как прямые запросы.
Распространённые ошибки
- Повторяйте на другой модели. Повторная отправка отклонённого запроса той же модели обычно приводит к ещё одному отказу. Направляйте повтор на резервную модель.
- Планируйте бюджет повторов на запрос, а не на ход или сессию. Один ход может породить несколько отказов, например агент плюс его субагенты.
- Настраивайте резервную обработку на каждом пути запроса. Обработчики повторов, ветви восстановления после ошибок и фоновые рабочие процессы — всем она нужна. Обработчик, который повторно выдаёт запрос без резервной обработки, теряет защиту именно на тех запросах, которым она, скорее всего, понадобится.
- Давайте вызовам субагентов собственную резервную обработку. Параметр
fallbacksне распространяется на вызовы моделей, выполняемые изнутри выполнения инструментов. - Делайте резервную обработку свойством запроса, а не окружающего состояния. Общий флаг, кэшированное значение конфигурации или глобальный переключатель могут рассинхронизироваться и незаметно оставить запрос без защиты. Когда вы не можете подтвердить, что резервная обработка активна, настройте её, а не предполагайте, что она включена.
- Инструментируйте отказы как отдельный сигнал. Отказ — это HTTP 200, поэтому мониторинг, построенный на частоте ошибок или ответах 5xx, никогда его не увидит. Генерируйте одно событие на каждый отказ и одно на каждый ответ, обслуженный резервной моделью (запись
fallback_messageвusage.iterationsотмечает последний), затем настройте оповещение о разнице между двумя счётчиками. - Ветвитесь по
stop_reasonилиstop_details.type, а не поcontentили внутренним полямstop_details. Объектstop_detailsвсегда присутствует при отказе, но его поляcategoryиexplanationмогут бытьnull. Проверяйте напрямую, чтоstop_reasonравен"refusal".
Следующие шаги
Избегайте двойной оплаты стоимости кэша подсказок, когда реализуете повтор самостоятельно.
Каждое значение stop_reason и как его обрабатывать.
Как работает промежуточное ПО SDK, включая вспомогательный компонент резервной обработки отказов.
Перенесите существующее приложение на Claude Fable 5.1.
Was this page helpful?