Add Claude Fable 5.1 (`claude-fable-5-1`) and Claude Mythos 5.1 (`claude-mythos-5-1`) support
- Closes #7984
Why we make these changes
Pydantic AI now recognizes Claude Fable 5.1 and Claude Mythos 5.1. Fable 5.1 rejects replayed thinking blocks when the conversation prefix changes, as reported in #7984.
Pydantic AI preserves Anthropic’s account default, then retries a rejected Fable 5.1 replay once with drop_block. It also corrects forced tool choice: only the two 5.1 models reject it.
New public surface
- Recognized direct, Gateway, and supported Bedrock Fable 5.1 model identifiers.
AnthropicStaleThinkingBlockWarningandAnthropicModelProfile.anthropic_binds_thinking_blocks.
User-visible behavior
- A stale Fable 5.1 thinking block could end the request with Anthropic's 400.
+ Pydantic AI retries once without that block, warns, and records the drop in `provider_details`.
Verification
- Known model names and model-profile / forced-tool-choice coverage.
- Recorded legacy-account replay and sync / streaming retry tests.
Deliberate decisions
Choices a reviewer could mistake for an oversight. Each was made on evidence, not convenience.
Decision log
Default sends no block_binding at all; a rejection is retried once. Not a drop_block default. For accounts created before 2026-08-31 Anthropic records the prefix mismatch but acts on it only when the request sets prefix_mismatch_behavior — so defaulting to drop_block would discard reasoning on accounts the check never touches, to fix a failure only newer accounts have. The carve-out is pinned by its own recorded cassette rather than resting on the docs sentence.
anthropic_binds_thinking_blocks is Fable 5.1 only — Mythos 5.1 is deliberately excluded. Mythos 5.1 mirrors Fable 5.1 elsewhere in this PR, so the omission looks like a miss. Anthropic's Fable 5.1 release notes state outright that Mythos 5.1 does not run the check; including it would put a field plus a beta header on the wire of the one model we cannot probe, for a check that never fires.
The binding narrowing is a client-class boundary, not a base-URL one. anthropic_binds_thinking_blocks is cleared for the Bedrock, Bedrock Mantle, Foundry and Vertex clients, which leaves a proxied or Gateway AsyncAnthropic inside it. That reads as an accidental hole and is not one. The beta follows thinking.block_binding, which is unset by default, and the retry needs a 400 whose body carries Anthropic's own The block is bound to a different conversation — so nothing extra reaches the wire for those clients unless Anthropic itself rejects a replay. Measured through the Pydantic AI Gateway rather than assumed: claude-fable-5-1 reaches Anthropic, the profile binds, and a forced prefix_mismatch_behavior='error' returns that byte-identical 400. Gateway behavior therefore matches the direct API, and gating on the api.anthropic.com host would have been the change that broke that parity.
The container-500 fallback classifies its own error, not the 500 that caused it. A [500, stale-thinking-400] sequence on a history-resolved container previously sent two requests and propagated the 400 with no retry, so this PR's own recovery never fired. The fallback's error is now rebound and classified, and the dropped container is carried forward so the drop-block retry does not resend an id the 500 disowned.
A model add touching .github/scripts/ and the add-new-model skill is mechanical, not scope creep. check_http_dependencies.py mirrors the declared floors exactly, so raising the anthropic extra to >=1.3.0 made its contains('1.0.0') assertion false and reddened quality checks. pydantic-ai-runner.lock needed regenerating because the shim smoke step imports BetaThinkingBlockBindingParam, which anthropic 1.0.0 does not carry. The skill's forced-tool-choice guidance named Fable 5 as the model that rejects forcing, which this PR's own correction falsified.
The anthropic.input_transformations span event is a requirement, not decoration. A dropped thinking block is otherwise silent. provider_details never reaches the span — messages_to_otel_messages emits role + parts, and response_attributes lifts only provider_response_id and finish_reason — and the warning is not trace-visible either, since nothing bridges warnings to telemetry. The name is provider-scoped because the transformation is Anthropic's own field, reported verbatim; a pydantic_ai.* name would promise a cross-provider shape that has not been designed.
block_binding rides in extra_body, not the typed thinking param. Fable 5.1 emits thinking blocks whether or not the request configured thinking, so the retry usually has no thinking object for the binding to live in, and the SDK's discriminated union always demands a type. Picking one would change how the model thinks; extra_body reaches the same JSON key without inventing a type the caller never asked for. A block_binding the caller set through extra_body is honored and never retried over.
message_delta replaces the transformation array; it does not extend it. The SDK documents that a message_delta carries input_transformations only after a server-side model fallback mid-stream, and then it holds the serving model's whole array — which repeats what message_start already reported. Appending duplicated every request-side entry.
Forced tool choice is corrected for three models beyond the two being added. claude-fable-5, claude-mythos-5 and claude-mythos-preview can force tool choice again. This moves observable behavior for existing users and was a conscious call, re-verified live before changing it: claude-fable-5 returns 200 on both any and tool against the GA and beta endpoints, while claude-fable-5-1 400s on all four. The two Mythos ids 404 on our credentials, so they follow Anthropic's published table.
The narrow warnings.filterwarnings in the sanitizer tests is intentional. simplefilter('error') there overrode the suite's deliberate ResourceWarning ignores, so delayed event-loop GC failed whichever test happened to collect it. The reason is now stated at both call sites.
startswith('claude-fable-5-1') also matches a hypothetical claude-fable-5-10. Left as-is: every sibling flag in the same function uses the bare-startswith convention, no current id resolves incorrectly, and Anthropic's dated-suffix names are handled. Worth revisiting only if such a name appears.
The dated anthropic entry in [tool.uv.exclude-newer-package] is temporary. It admits only the reviewed 1.3.0 release past the repo's supply-chain cooldown. It must be removed after 2026-09-08 17:37 UTC or it stops acting as a floor and becomes a ceiling — tracked in #7985.
What changes for existing users
Users of claude-fable-5, claude-mythos-5, and claude-mythos-preview can force tool choice again. Fable 5.1 stale-thinking replays now complete after dropping the stale reasoning block and emit a warning; other models are unchanged by default.
Checklist
- Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
- No breaking changes in accordance with the version policy.
- PR title is fit for the release changelog.