Skip to content

fix: anthropic fallbacks and refusal - #5367

Merged
akshaydeo merged 1 commit into
devfrom
07-20-fix_anthropic_fallbacks_and_refusal
Jul 20, 2026
Merged

fix: anthropic fallbacks and refusal#5367
akshaydeo merged 1 commit into
devfrom
07-20-fix_anthropic_fallbacks_and_refusal

Conversation

@TejasGhatte

@TejasGhatte TejasGhatte commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Anthropic's native server-side fallback feature (server-side-fallback-2026-06-01) uses a "fallbacks" request field containing JSON objects ({"model": "..."}) — the same wire key that Bifrost uses for cross-provider fallback strings ("provider/model"). Previously, Bifrost unconditionally deleted the entire "fallbacks" field before forwarding requests to Anthropic, which broke native server-side fallbacks. This PR disambiguates the two by shape, preserving native fallback objects while still stripping Bifrost cross-provider strings.

Changes

  • Replaced []string on AnthropicMessageRequest.Fallbacks with []AnthropicFallbackEntry, a union type that unmarshals JSON strings as Bifrost cross-provider fallbacks and JSON objects as Anthropic native server-side fallbacks.
  • Added AnthropicNativeFallback struct representing one entry of Anthropic's native "fallbacks" list, with optional max_tokens and thinking overrides.
  • Replaced the blanket DeleteJSONField("fallbacks") call in both BuildAnthropicResponsesRequestBody and BuildAnthropicChatRequestBody with stripBifrostFallbacksFromBody, which removes only string entries and deletes the field entirely when no native objects remain.
  • Added bifrostFallbackModels() and nativeFallbacks() helpers on AnthropicMessageRequest to separate the two entry kinds cleanly.
  • Updated ToBifrostResponsesRequest to route native fallback objects into ExtraParams["fallbacks"] for verbatim forwarding, while Bifrost strings continue to populate BifrostResponsesRequest.Fallbacks.
  • Updated ToAnthropicResponsesRequest to reconstruct the typed Fallbacks field from ExtraParams["fallbacks"] when native entries are present.
  • Added ServerSideFallback bool to ProviderFeatureSupport, enabled only for the Anthropic provider (not Bedrock, Vertex, or Azure), and wired it into AddMissingBetaHeadersToContext so the server-side-fallback-2026-06-01 beta header is auto-injected when native fallbacks are present.
  • Registered AnthropicServerSideFallbackBetaHeaderPrefix in the known-prefix lists used for beta header deduplication and provider-feature gating.

Type of change

  • Bug fix
  • Feature

Affected areas

  • Core (Go)
  • Providers/Integrations

How to test

go test ./core/providers/anthropic/...

Key test cases added:

  • TestAnthropicFallbackEntry_UnmarshalJSON — verifies string vs. object dispatch and round-trip marshalling.
  • TestAnthropicMessageRequest_NativeFallbacksParse — regression for the "Invalid JSON" error when a request carries native {"model": ...} fallback objects.
  • TestToBifrostResponsesRequest_FallbacksRouting — verifies native objects go to ExtraParams and Bifrost strings go to Fallbacks.
  • TestAddMissingBetaHeadersToContext_ServerSideFallback — verifies the beta header is injected on Anthropic and suppressed on Vertex.
  • TestBuildAnthropicResponsesRequestBody_NativeFallbacks — end-to-end body assembly for both raw-passthrough and typed paths, covering native preservation, Bifrost stripping, and beta header injection.

Breaking changes

  • No

The Fallbacks []string field on AnthropicMessageRequest is an internal type not part of the public Bifrost API surface. Existing Bifrost cross-provider fallback behaviour is unchanged.

Security considerations

No auth, secrets, or PII implications. The change only affects how the "fallbacks" JSON field is forwarded to the Anthropic API.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


tejas ghatte seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@TejasGhatte
TejasGhatte marked this pull request as ready for review July 19, 2026 20:36

TejasGhatte commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added Anthropic native server-side fallback support (including fallback boundary handling) and full stop_details propagation across streaming and non-streaming.
    • Added beta support for fallback credit, including request/response round-tripping and per-attempt model usage.
  • Bug Fixes
    • Improved fallback request shaping to preserve native fallback objects only when supported, while stripping cross-provider fallback markers/strings elsewhere.
    • Ensured unsupported fallback boundary blocks are dropped when converting to OpenAI, Bedrock, Cohere, and Gemini.
  • Tests
    • Expanded unit and end-to-end coverage for fallback shapes, beta header behavior, stop_details, and fallback credit behavior.

Walkthrough

Anthropic now supports native server-side fallback objects, fallback boundary content blocks, stop details, fallback-credit fields, and usage model metadata across request construction and Bifrost conversions. Unsupported providers filter Anthropic-specific fields and boundary markers.

Changes

Anthropic server-side fallback support

Layer / File(s) Summary
Fallback contracts and feature gating
core/providers/anthropic/types.go, core/schemas/responses.go
Schemas define native fallback entries, fallback boundary blocks, stop details, usage model metadata, beta headers, and provider capabilities.
Fallback request routing and assembly
core/providers/anthropic/chat.go, core/providers/anthropic/responses.go, core/providers/anthropic/utils.go, core/providers/anthropic/requestbuilder.go
Native fallbacks and fallback-credit tokens are routed through typed and extra parameters, feature-gated headers are added, and request bodies retain supported native objects while removing Bifrost fallback strings.
Response conversion
core/providers/anthropic/responses.go
Fallback boundaries, stop details, fallback-credit metadata, and usage model values round-trip through streaming and non-streaming conversions.
Unsupported-provider filtering
core/providers/openai/responses.go, core/providers/bedrock/responses.go, core/providers/cohere/responses.go, core/providers/gemini/responses.go
Fallback boundary markers are dropped from provider request or response content when unsupported.
Validation and end-to-end coverage
core/providers/anthropic/*_test.go, core/providers/openai/responses_test.go, tests/e2e/api/collections/provider-harness.json
Tests cover fallback shapes, routing, headers, body construction, provider filtering, boundary events, stop details, fallback credit, usage metadata, and API scenarios.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AnthropicRequest
  participant BifrostRequest
  participant AnthropicRequestBuilder
  participant AnthropicResponseStream
  participant BifrostResponseStream
  AnthropicRequest->>BifrostRequest: route native fallbacks and credit token
  BifrostRequest->>AnthropicRequestBuilder: pass typed and extra fallback parameters
  AnthropicRequestBuilder->>AnthropicRequestBuilder: inject headers and filter request fields
  AnthropicResponseStream->>BifrostResponseStream: convert fallback boundaries and stop details
  BifrostResponseStream->>AnthropicResponseStream: reconstruct Anthropic stream events
Loading

Suggested reviewers: akshaydeo, danpiths, pratham-mishra04, sammaji, roroghost17

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title concisely describes the main change: Anthropic fallbacks and refusal metadata handling.
Description check ✅ Passed The description matches the template well and includes summary, changes, testing, breaking changes, security, and checklist sections.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 07-20-fix_anthropic_fallbacks_and_refusal

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.12.2)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

This looks safe to merge.

  • The updated chat path promotes native fallback objects before beta-header detection.
  • Unsupported provider paths strip Anthropic-only fallback fields.
  • The new request and response behavior has focused test coverage.
  • No blocking issues were found in the changed code.

Important Files Changed

Filename Overview
core/providers/anthropic/chat.go Promotes native fallbacks and fallback credit tokens from extra parameters into typed Anthropic chat requests.
core/providers/anthropic/requestbuilder.go Preserves supported native fallback objects while stripping Bifrost strings and unsupported fields.
core/providers/anthropic/responses.go Carries fallback boundaries, refusal details, credit data, and usage models through response conversions.
core/providers/anthropic/types.go Adds typed wire representations for native fallbacks, refusal details, and related provider features.
core/providers/anthropic/utils.go Adds provider-aware fallback filtering and beta-header injection.
core/providers/anthropic/serversidefallback_test.go Tests fallback routing, provider gating, headers, refusal metadata, credits, and stream conversions.

Reviews (4): Last reviewed commit: "fix: anthropic fallbacks and refusal" | Re-trigger Greptile

Comment thread core/providers/anthropic/utils.go
Comment thread core/providers/anthropic/utils.go Outdated
Comment thread core/providers/anthropic/types.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/providers/anthropic/responses.go (1)

3438-3446: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Mirror native fallback handling in core/providers/anthropic/chat.go. ToAnthropicChatRequest should carry ExtraParams["fallbacks"] into AnthropicMessageRequest.Fallbacks like the responses path does, so Chat requests preserve Anthropic-native fallbacks and trigger the beta header.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/providers/anthropic/responses.go` around lines 3438 - 3446, The chat
request conversion in ToAnthropicChatRequest does not propagate native
fallbacks. Mirror the responses conversion by reading ExtraParams["fallbacks"],
assigning it to AnthropicMessageRequest.Fallbacks, and preserving the existing
behavior that triggers the beta header when fallbacks are present.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/providers/anthropic/utils.go`:
- Around line 1285-1317: Gate native fallback preservation on the target
provider’s ServerSideFallback capability. Update stripBifrostFallbacksFromBody
in core/providers/anthropic/utils.go and both call sites in
core/providers/anthropic/requestbuilder.go at lines 379-384 and 602-607 to pass
or apply cfg.Provider, ensuring native JSON-object fallbacks are stripped when
!ProviderFeatures[cfg.Provider].ServerSideFallback while retaining current
behavior for supported providers.

---

Outside diff comments:
In `@core/providers/anthropic/responses.go`:
- Around line 3438-3446: The chat request conversion in ToAnthropicChatRequest
does not propagate native fallbacks. Mirror the responses conversion by reading
ExtraParams["fallbacks"], assigning it to AnthropicMessageRequest.Fallbacks, and
preserving the existing behavior that triggers the beta header when fallbacks
are present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 80227888-d6a2-45ef-900a-99c806c457bb

📥 Commits

Reviewing files that changed from the base of the PR and between e1550bf and 83571c1.

📒 Files selected for processing (5)
  • core/providers/anthropic/requestbuilder.go
  • core/providers/anthropic/responses.go
  • core/providers/anthropic/types.go
  • core/providers/anthropic/utils.go
  • core/providers/anthropic/utils_test.go

Comment thread core/providers/anthropic/utils.go
@TejasGhatte
TejasGhatte force-pushed the 07-20-fix_anthropic_fallbacks_and_refusal branch from 83571c1 to db9bd25 Compare July 20, 2026 07:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
core/providers/anthropic/responses.go (1)

3315-3334: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Strip Anthropic-native fallbacks before cross-provider fallback. Params.ExtraParams is reused on fallback attempts, and providers like Bedrock forward ExtraParams verbatim, so this raw Anthropic field can reach a non-Anthropic upstream and break the request. core/providers/anthropic/responses.go:3315-3334

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/providers/anthropic/responses.go` around lines 3315 - 3334, Update
AnthropicMessageRequest.ToBifrostResponsesRequest so Anthropic-native fallbacks
are not retained in Params.ExtraParams when cross-provider fallback requests may
reuse it; only forward the native “fallbacks” field for the Anthropic upstream,
preventing providers such as Bedrock from receiving it verbatim.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@core/providers/anthropic/responses.go`:
- Around line 3315-3334: Update
AnthropicMessageRequest.ToBifrostResponsesRequest so Anthropic-native fallbacks
are not retained in Params.ExtraParams when cross-provider fallback requests may
reuse it; only forward the native “fallbacks” field for the Anthropic upstream,
preventing providers such as Bedrock from receiving it verbatim.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a138295d-cc1b-44f6-bd0e-a8e3a0bcf9b2

📥 Commits

Reviewing files that changed from the base of the PR and between 83571c1 and db9bd25.

📒 Files selected for processing (8)
  • core/providers/anthropic/chat.go
  • core/providers/anthropic/requestbuilder.go
  • core/providers/anthropic/responses.go
  • core/providers/anthropic/serversidefallback_test.go
  • core/providers/anthropic/types.go
  • core/providers/anthropic/utils.go
  • core/providers/anthropic/utils_test.go
  • core/schemas/responses.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • core/providers/anthropic/requestbuilder.go
  • core/providers/anthropic/utils.go

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 20, 2026
@TejasGhatte
TejasGhatte force-pushed the 07-20-fix_anthropic_fallbacks_and_refusal branch from db9bd25 to 42ad071 Compare July 20, 2026 08:18
@TejasGhatte TejasGhatte mentioned this pull request Jul 20, 2026
18 tasks

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/e2e/api/collections/provider-harness.json`:
- Around line 40994-41044: Update the request model in the test named
“anthropic/claude-fable-5 · native object fallbacks forwarded with
server-side-fallback beta” to use a currently live Anthropic model documented
elsewhere in the harness, such as claude-opus-4-8 or claude-sonnet-5. Keep the
fallback payload and beta-header assertions unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 43d38f3d-ef17-490b-b5e5-935004ed23e8

📥 Commits

Reviewing files that changed from the base of the PR and between db9bd25 and 42ad071.

📒 Files selected for processing (14)
  • core/providers/anthropic/chat.go
  • core/providers/anthropic/requestbuilder.go
  • core/providers/anthropic/responses.go
  • core/providers/anthropic/serversidefallback_test.go
  • core/providers/anthropic/types.go
  • core/providers/anthropic/utils.go
  • core/providers/anthropic/utils_test.go
  • core/providers/bedrock/responses.go
  • core/providers/cohere/responses.go
  • core/providers/gemini/responses.go
  • core/providers/openai/responses.go
  • core/providers/openai/responses_test.go
  • core/schemas/responses.go
  • tests/e2e/api/collections/provider-harness.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • core/providers/anthropic/chat.go
  • core/schemas/responses.go
  • core/providers/anthropic/responses.go
  • core/providers/anthropic/types.go
  • core/providers/anthropic/utils_test.go

Comment thread tests/e2e/api/collections/provider-harness.json
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 20, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
core/providers/anthropic/utils.go (1)

504-512: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: inconsistent error handling for the fallback_credit_token strip.

Every other strip in this function wraps the error with descriptive context (fmt.Errorf("strip raw <field>: %w", err)) and reuses the outer err. This branch shadows the outer err with a fresh var err error and returns it unwrapped, losing the "which strip failed" context.

♻️ Align with sibling strips
 	if !features.FallbackCredit {
-		var err error
 		jsonBody, err = providerUtils.DeleteJSONField(jsonBody, "fallback_credit_token")
 		if err != nil {
-			return nil, err
+			return nil, fmt.Errorf("strip raw fallback_credit_token: %w", err)
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@core/providers/anthropic/utils.go` around lines 504 - 512, Update the
fallback_credit_token removal branch in the surrounding function to reuse the
existing outer err variable instead of declaring a shadowing local error, and
wrap DeleteJSONField failures with descriptive context consistent with the
sibling field-stripping branches before returning.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@core/providers/anthropic/utils.go`:
- Around line 504-512: Update the fallback_credit_token removal branch in the
surrounding function to reuse the existing outer err variable instead of
declaring a shadowing local error, and wrap DeleteJSONField failures with
descriptive context consistent with the sibling field-stripping branches before
returning.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f0a88200-000a-49f6-bd7b-4239e44ac7f1

📥 Commits

Reviewing files that changed from the base of the PR and between 42ad071 and b587562.

📒 Files selected for processing (14)
  • core/providers/anthropic/chat.go
  • core/providers/anthropic/requestbuilder.go
  • core/providers/anthropic/responses.go
  • core/providers/anthropic/serversidefallback_test.go
  • core/providers/anthropic/types.go
  • core/providers/anthropic/utils.go
  • core/providers/anthropic/utils_test.go
  • core/providers/bedrock/responses.go
  • core/providers/cohere/responses.go
  • core/providers/gemini/responses.go
  • core/providers/openai/responses.go
  • core/providers/openai/responses_test.go
  • core/schemas/responses.go
  • tests/e2e/api/collections/provider-harness.json
🚧 Files skipped from review as they are similar to previous changes (10)
  • core/providers/anthropic/chat.go
  • core/providers/bedrock/responses.go
  • core/providers/openai/responses.go
  • core/providers/openai/responses_test.go
  • tests/e2e/api/collections/provider-harness.json
  • core/providers/cohere/responses.go
  • core/schemas/responses.go
  • core/providers/anthropic/requestbuilder.go
  • core/providers/anthropic/responses.go
  • core/providers/anthropic/types.go

This was referenced Jul 24, 2026
This was referenced Aug 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants