Skip to content

feat: add Anthropic OAuth passthrough support and gzip response decoding in all providers - #729

Closed
Pratham-Mishra04 wants to merge 1 commit into
10-31-feat_added_ctx_level_support_for_extra_headers_and_url_pathfrom
10-31-feat-http-response-decoding-and-ctx-level-req-control-added
Closed

feat: add Anthropic OAuth passthrough support and gzip response decoding in all providers#729
Pratham-Mishra04 wants to merge 1 commit into
10-31-feat_added_ctx_level_support_for_extra_headers_and_url_pathfrom
10-31-feat-http-response-decoding-and-ctx-level-req-control-added

Conversation

@Pratham-Mishra04

Copy link
Copy Markdown
Collaborator

Summary

Add support for Anthropic OAuth authentication to enable Claude Code integration. This PR allows Bifrost to handle both API key and OAuth authentication methods for Anthropic models.

Changes

  • Added support for Anthropic OAuth authentication (Bearer tokens starting with sk-ant-oat)
  • Made API key header optional when using passthrough mode
  • Added path wildcard support for Anthropic messages endpoint to handle subpaths
  • Implemented a pre-callback function to detect Anthropic models and set appropriate context values
  • Refactored Anthropic route configuration creation for better maintainability

Type of change

  • Feature
  • Refactor

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations

How to test

  1. Test with standard Anthropic API key:
curl -X POST http://localhost:8000/anthropic/v1/messages \
  -H "x-api-key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-3-opus-20240229","messages":[{"role":"user","content":"Hello"}]}'
  1. Test with Anthropic OAuth token:
curl -X POST http://localhost:8000/anthropic/v1/messages \
  -H "Authorization: Bearer sk-ant-oat-your-token" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-3-opus-20240229","messages":[{"role":"user","content":"Hello"}]}'
  1. Test Claude Code endpoint:
curl -X POST http://localhost:8000/anthropic/v1/messages/code \
  -H "Authorization: Bearer sk-ant-oat-your-token" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-3-opus-20240229","messages":[{"role":"user","content":"Write a Python function to sort a list"}]}'

Breaking changes

  • No

Related issues

Enables Claude Code integration

Security considerations

This PR handles authentication tokens securely by passing them through to the Anthropic API without modification.

Checklist

  • I added/updated tests where appropriate
  • I verified builds succeed (Go and UI)

@coderabbitai

coderabbitai Bot commented Nov 2, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Summary by CodeRabbit

  • Bug Fixes

    • API key header is now conditionally sent only when provided, enabling seamless passthrough behavior for scenarios without explicit authentication keys.
  • New Features

    • Added support for Anthropic and Claude model passthrough functionality with improved routing configuration for complete and messages endpoints.
    • Enhanced authentication detection to properly distinguish between API key and OAuth bearer token authentication methods.

Walkthrough

Implements Anthropic passthrough behavior by conditionally setting API keys, introducing modular route configuration builders, adding model-detection and context-augmentation logic for Claude models, and refactoring utility functions for authentication mode detection and path extraction.

Changes

Cohort / File(s) Summary
Core API key conditional setting
core/providers/anthropic.go
Modified completeRequest to conditionally set x-api-key header only when the provided key is non-empty, enabling passthrough when no key is supplied.
Bifrost HTTP integration routing and passthrough
transports/bifrost-http/integrations/anthropic.go
Introduced modular route config builders (createAnthropicCompleteRouteConfig, createAnthropicMessagesRouteConfig). Added internal checkAnthropicPassthrough pre-callback to detect Claude/Anthropic models, strip anthropic/ prefix, and augment bifrost context with raw headers, URL path, and skip-key-selection flag. Extended messages route handling with StreamConfig and added PreCallback to list models route.
Authentication and path utility functions
transports/bifrost-http/integrations/utils.go
Renamed getExactPath to extractExactPath. Added new isAnthropicAPIKeyAuth helper to detect authentication mode based on x-api-key and Authorization Bearer token headers.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Bifrost as Bifrost HTTP
    participant Passthrough as checkAnthropicPassthrough
    participant Core as Core Provider
    participant Anthropic as Anthropic API

    Client->>Bifrost: POST /messages (Claude model)
    Bifrost->>Passthrough: PreCallback triggered
    
    rect rgb(240, 248, 255)
        note over Passthrough: Detect Claude model<br/>Check auth mode
        alt x-api-key present
            Passthrough->>Passthrough: Skip key selection
        else Bearer token present
            Passthrough->>Passthrough: OAuth mode detected
        end
    end
    
    Passthrough->>Passthrough: Strip anthropic/ prefix<br/>Augment bifrost context
    Passthrough-->>Bifrost: Context updated with headers & path
    Bifrost->>Core: Forward request
    Core->>Core: Conditionally set x-api-key<br/>(only if non-empty)
    Core->>Anthropic: Send request
    Anthropic-->>Core: Response
    Core-->>Bifrost: Response
    Bifrost-->>Client: Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Extra attention areas:
    • Logic in checkAnthropicPassthrough callback for model detection and context augmentation, particularly the model string prefix stripping and conditional flag handling
    • Interaction between the new modular builders in CreateAnthropicRouteConfigs and their composition order
    • Authentication mode detection logic in isAnthropicAPIKeyAuth, especially case-insensitive Bearer token matching
    • Ensure passthrough context flags correctly prevent key selection when needed

Poem

🐰 A rabbit hops through routes so bright,
Passthrough magic, headers set just right—
No empty keys shall pass our way,
Claude flows free throughout the day!
OAuth or key, we intelligently choose,
Modular configs that the code can't lose. 🚀

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The pull request title mentions two main features: "Anthropic OAuth passthrough support" and "gzip response decoding in all providers." The raw summary shows clear evidence of the Anthropic OAuth passthrough work through the new checkAnthropicPassthrough function, isAnthropicAPIKeyAuth helper, and conditional x-api-key header logic. However, the gzip response decoding feature mentioned in the title is not substantiated in any of the provided file summaries (core/providers/anthropic.go, transports/bifrost-http/integrations/anthropic.go, or transports/bifrost-http/integrations/utils.go), though it is referenced in the PR objectives. This discrepancy creates ambiguity about whether the gzip changes actually exist in this PR or if the title overstates the scope. To resolve this, clarify whether gzip response decoding changes are included in this PR by providing file summaries for any additional modified files or updating the title to accurately reflect the actual changes. If gzip decoding is out of scope, the title should be narrowed to focus on "Anthropic OAuth passthrough support and API key header optimization" to accurately represent the evident changes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed The pull request description follows the repository template well and includes all major required sections: a clear summary explaining the OAuth support for Claude Code integration, detailed changes explaining what was modified and why, proper type of change selection (Feature and Refactor), affected areas checkboxes (Core, Transports, Providers/Integrations), and comprehensive how-to-test instructions with curl examples for different authentication methods. Security considerations are addressed regarding token handling, and breaking changes are appropriately marked as "No." While some checklist items remain unchecked (such as reading the contributing guidelines and updating documentation), the description is substantially complete with the most critical information present.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch 10-31-feat-http-response-decoding-and-ctx-level-req-control-added

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

Pratham-Mishra04 commented Nov 2, 2025

Copy link
Copy Markdown
Collaborator Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

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

@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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f6a7aa3 and 376d868.

📒 Files selected for processing (3)
  • core/providers/anthropic.go (1 hunks)
  • transports/bifrost-http/integrations/anthropic.go (4 hunks)
  • transports/bifrost-http/integrations/utils.go (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
transports/bifrost-http/integrations/anthropic.go (6)
transports/bifrost-http/integrations/router.go (5)
  • RouteConfig (190-207)
  • RouteConfigTypeAnthropic (184-184)
  • RequestConverter (80-80)
  • TextResponseConverter (88-88)
  • ErrorConverter (128-128)
core/schemas/providers/anthropic/types.go (2)
  • AnthropicTextRequest (19-28)
  • AnthropicMessageRequest (36-49)
core/schemas/bifrost.go (9)
  • BifrostRequest (134-144)
  • TextCompletionRequest (83-83)
  • BifrostError (326-335)
  • ModelProvider (32-32)
  • Anthropic (37-37)
  • BifrostContextKeyExtraHeaders (108-108)
  • BifrostContextKeyURLPath (109-109)
  • BifrostContextKeySkipKeySelection (107-107)
  • BifrostContextKeyRequestBody (110-110)
core/schemas/providers/anthropic/text.go (1)
  • ToAnthropicTextCompletionResponse (110-137)
core/schemas/providers/anthropic/chat.go (1)
  • ToAnthropicChatCompletionError (991-1012)
core/schemas/utils.go (1)
  • ParseModelString (21-34)
⏰ Context from checks skipped due to timeout of 900000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check
  • GitHub Check: Graphite / mergeability_check

Comment on lines +133 to +147
case *anthropic.AnthropicTextRequest:
provider, model = schemas.ParseModelString(r.Model, "")
// Check if model parameter explicitly has `anthropic/` prefix
if after, ok := strings.CutPrefix(model, "anthropic/"); ok {
r.Model = after
}

case *anthropic.AnthropicMessageRequest:
provider, model = schemas.ParseModelString(r.Model, "")
// Check if model parameter explicitly has `anthropic/` prefix
if after, ok := strings.CutPrefix(model, "anthropic/"); ok {
r.Model = after
}
}

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.

⚠️ Potential issue | 🟠 Major

Prefix trimming never executes

schemas.ParseModelString already strips the provider prefix from model, so this CutPrefix guard is always false and r.Model keeps values like anthropic/claude-3.5-sonnet. Those provider-qualified names are forwarded unchanged and Anthropic rejects them. Trim r.Model directly (and keep the local model variable in sync) so passthrough requests receive the bare model name they expect.

-		if after, ok := strings.CutPrefix(model, "anthropic/"); ok {
-			r.Model = after
+		if after, ok := strings.CutPrefix(r.Model, "anthropic/"); ok {
+			r.Model = after
+			model = after
		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case *anthropic.AnthropicTextRequest:
provider, model = schemas.ParseModelString(r.Model, "")
// Check if model parameter explicitly has `anthropic/` prefix
if after, ok := strings.CutPrefix(model, "anthropic/"); ok {
r.Model = after
}
case *anthropic.AnthropicMessageRequest:
provider, model = schemas.ParseModelString(r.Model, "")
// Check if model parameter explicitly has `anthropic/` prefix
if after, ok := strings.CutPrefix(model, "anthropic/"); ok {
r.Model = after
}
}
case *anthropic.AnthropicTextRequest:
provider, model = schemas.ParseModelString(r.Model, "")
// Check if model parameter explicitly has `anthropic/` prefix
if after, ok := strings.CutPrefix(r.Model, "anthropic/"); ok {
r.Model = after
model = after
}
case *anthropic.AnthropicMessageRequest:
provider, model = schemas.ParseModelString(r.Model, "")
// Check if model parameter explicitly has `anthropic/` prefix
if after, ok := strings.CutPrefix(r.Model, "anthropic/"); ok {
r.Model = after
model = after
}
}
🤖 Prompt for AI Agents
In transports/bifrost-http/integrations/anthropic.go around lines 133 to 147,
the current CutPrefix check never runs because schemas.ParseModelString already
removed the provider prefix; as a result r.Model can remain as "anthropic/..."
and be forwarded to Anthropic. Fix by trimming the "anthropic/" prefix directly
on r.Model (e.g. use strings.CutPrefix on r.Model and set r.Model = after when
ok) and then update the local model variable to match (model = r.Model) in both
the AnthropicTextRequest and AnthropicMessageRequest cases so passthrough
requests send the bare model name.

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.

1 participant