Follow Discord
Sweep 22 Oct 2026 · 21:04Z Build v2.1.309 528 read Stable v2.1.308 Latest v2.1.309 Next v2.1.309 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One change · api

refusals-and-fallback changedbuild-with-claude/refusals-and-fallback

Nearest release: v2.1.309, published 3 hours before this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.

Recorded here
Lines+23added
Lines−18removed
From line 121 where the diff opens
First seen 14 Aug 2026 this site's first read of the page
Recorded edits27to this page, all time

The whole hunk

from line 121, old and new numbered
/
lines
from line 121
121121 $client = new Client();
122122 
123123 $response = $client->beta->messages->create(
124 model: 'claude-fable-5',
124 model: Model::CLAUDE_FABLE_5,
125125 maxTokens: 1024,
126126 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
127127 fallbacks: 'default',
from line 184
184184| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------ |
185185| `"cyber"` | The request could enable cyber harm, such as malware or exploit development. Benign cybersecurity work can also trigger this category. | No |
186186| `"bio"` | The request could enable biological harm, such as dangerous lab methods. Beneficial life sciences work can also trigger this category. | Yes |
187| `"frontier_llm"` | The request could assist the development of competing AI models, which is restricted under [Anthropic's commercial terms](https://www.anthropic.com/legal/commercial-terms). Benign machine learning work can also trigger this category. | Yes |
187| `"frontier_llm"` | The request could help with the development of competing AI models, which is restricted under [Anthropic's commercial terms](https://www.anthropic.com/legal/commercial-terms). Benign machine learning work can also trigger this category. | Yes |
188188| `"reasoning_extraction"` | The request asks the model to reproduce its internal reasoning in the response text. To get reasoning in a structured form instead, use [adaptive thinking](https://platform.claude.com/docs/en/build-with-claude/thinking). See [Keep reasoning in thinking blocks](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#keep-reasoning-in-thinking-blocks). | Yes |
189189| `"general_harms"` | The request falls under a usage-policy area outside the four named categories. Benign work can also trigger this category. | No |
190190 
from line 219
219219 
220220There are three ways to retry a refused request on another model. The right one depends on where you are running and how much control you need.
221221 
222| Your situation | Use | Why |
223| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
224| Claude API or Claude Models on Google Cloud (Anthropic managed), simplest setup | [Server-side fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#server-side-fallback) | One request, one response. The API handles the retry. |
225| Any platform, using an Anthropic SDK | [The SDK middleware](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#client-side-fallback) | Configure once on the client. Retries happen automatically. |
226| Raw HTTP or custom retry logic | [A manual retry](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#manual-retry) with [fallback credit](https://platform.claude.com/docs/en/build-with-claude/fallback-credit) | Full control. Fallback credit keeps the cost down. |
222| Your situation | Use | Why |
223| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
224| Claude API or Claude Models on Google Cloud (Anthropic managed), simplest setup | [Server-side fallback](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#server-side-fallback) | One request, one response. The API handles the retry. |
225| Any platform, using an Anthropic SDK | [Client-side fallback with the SDK middleware](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#client-side-fallback) | Configure once on the client. Retries occur automatically. |
226| Raw HTTP or custom retry logic | [A manual retry](https://platform.claude.com/docs/en/build-with-claude/refusals-and-fallback#manual-retry) with [fallback credit](https://platform.claude.com/docs/en/build-with-claude/fallback-credit) | Full control. Fallback credit keeps the cost down. |
227227 
228228Server-side fallback and the SDK middleware apply fallback credit for you. You only need the [Fallback credit](https://platform.claude.com/docs/en/build-with-claude/fallback-credit) page when you build the retry yourself. Claude Haiku 5.5 has neither server-side fallback nor fallback credit, so use the SDK middleware or a manual retry.
229229 
from line 418
418418 IO.println("""
419419 {"stop_reason":"%s","model":"%s","served_by_fallback":%b}\
420420 """.formatted(
421 response.stopReason().map(BetaStopReason::asString).orElse("null"),
422 response.model().asString(),
423 servedByFallback));
421 response.stopReason().map(BetaStopReason::asString).orElse("null"),
422 response.model().asString(),
423 servedByFallback));
424424 ```
425425 
426426 ```php PHP
from line 429
429429 $response = $client->beta->messages->create(
430430 maxTokens: 1024,
431431 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
432 model: 'claude-fable-5',
432 model: Model::CLAUDE_FABLE_5,
433433 fallbacks: 'default',
434434 betas: ['server-side-fallback-2026-07-01'],
435435 );
from line 596
596596 $client = new Client();
597597 
598598 $response = $client->beta->messages->create(
599 model: 'claude-fable-5',
599 model: Model::CLAUDE_FABLE_5,
600600 maxTokens: 1024,
601601 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
602602 fallbacks: [['model' => 'claude-opus-4-8']],
from line 726
726726 
727727### Non-streaming responses
728728 
729On a non-streaming request, a mid-output decline behaves differently: the response omits the declined model's partial output, and the fallback model answers from the beginning. The result looks like a decline before any output, with the `fallback` block first. The declined attempt and its output tokens still appear in `usage.iterations`.
729On a non-streaming request, a mid-output decline behaves differently: the response omits the declined model's partial output, and the fallback model starts a new answer. The result looks like a decline before any output, with the `fallback` block first. The declined attempt and its output tokens still appear in `usage.iterations`.
730730 
731731<Note>
732732 **Declines during tool use:** completed tool work does not block fallback. When a decline fires after server tools (for example, web search or code execution) have finished executing within a request, the fallback attempt proceeds: the completed tool results carry over, and the fallback model can keep invoking server tools. The one case that does not retry is a streaming decline that fires while a tool-use block of any type (a client tool, a server tool, or an MCP tool call) is still open on the stream: that refusal is returned directly, and if the `fallback-credit-2026-07-01` header is set it still carries a credit token redeemable by continuing the partial response. Non-streaming requests are unaffected; the API clears the partial work and retries before responding.
from line 916
916916 )),
917917 )
918918 
919 // One state per conversation: requests sharing it stay pinned to the
919 // One state for each conversation: requests sharing it stay pinned to the
920920 // model that accepted, so a follow-up never re-asks a model that refused.
921921 state := &betafallback.BetaFallbackState{}
922922 conversation := betafallback.WithBetaFallbackState(state)
from line 997
997997 BetaMessageAccumulator accumulator = BetaMessageAccumulator.create();
998998 try (StreamResponse<BetaRawMessageStreamEvent> streamResponse = client.beta()
999999 .messages()
1000 .createStreaming(params, RequestOptions.builder().fallbackState(state).build())) {
1000 .createStreaming(params, RequestOptions.builder()
1001 .fallbackState(state)
1002 .build())) {
10011003 streamResponse.stream()
10021004 .peek(accumulator::accumulate)
10031005 .forEach(event -> event.contentBlockDelta()
from line 1011
10091011 // Non-streaming: reusing the same state keeps the conversation pinned.
10101012 BetaMessage message = client.beta()
10111013 .messages()
1012 .create(params, RequestOptions.builder().fallbackState(state).build());
1014 .create(params, RequestOptions.builder()
1015 .fallbackState(state)
1016 .build());
10131017 IO.println("served by: " + message.model().asString());
10141018 }
10151019 ```
from line 1025
10211025 use Anthropic\Lib\Middleware\BetaFallbackState;
10221026 use Anthropic\Lib\Middleware\RefusalFallbackMiddleware;
10231027 use Anthropic\Lib\Streaming\MessageAccumulator;
1028 use Anthropic\Messages\Model;
10241029 
10251030 // Configure the fallback chain once. On a refusal, the middleware retries the
10261031 // request down the chain and sends the fallback-credit beta header for you.
from line 1042
10371042 // Streaming: on a refusal the middleware splices the fallback model's events
10381043 // onto the still-open stream. The accumulator's model is the serving model.
10391044 $stream = $client->beta->messages->createStream(
1040 model: 'claude-fable-5',
1045 model: Model::CLAUDE_FABLE_5,
10411046 maxTokens: 1024,
10421047 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
10431048 requestOptions: ['fallbackState' => $state],
from line 1060
10551060 // Non-streaming: same middleware. Reusing the state keeps the conversation
10561061 // pinned to the model that accepted.
10571062 $message = $client->beta->messages->create(
1058 model: 'claude-fable-5',
1063 model: Model::CLAUDE_FABLE_5,
10591064 maxTokens: 1024,
10601065 messages: [['role' => 'user', 'content' => 'Hello, Claude']],
10611066 requestOptions: ['fallbackState' => $state],
Feedback