Skip to content

feat(llm-client): allow forwarding all Anthropic beta headers - #940

Open
ting-hong-shieh wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
ting-hong-shieh:feature/938-forward-anthropic-beta
Open

ting-hong-shieh wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
ting-hong-shieh:feature/938-forward-anthropic-beta

Conversation

@ting-hong-shieh

@ting-hong-shieh ting-hong-shieh commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

What

When forward_auth = true, a caller can send beta-specific body fields while Switchyard drops their anthropic-beta values. Add forward_beta = "all" on an anthropic_messages client to forward the caller's beta header values unchanged, including repeated headers. Omitted or "oauth" settings keep the existing OAuth-only filtering.

[llm_clients.claude]
format = "anthropic_messages"
base_url = "https://api.anthropic.com"
forward_auth = true
forward_beta = "all"

Why

Claude Code may pair request fields with experimental beta values. Dropping those values can cause upstream HTTP 400 responses. Closes #938.

Notes for reviewers

The policy is applied in the shared HTTP request path for completion and token-counting calls. TOML permits the field only for Anthropic Messages clients with auth forwarding enabled. Static anthropic-beta values in extra_headers remain rejected in both forwarding modes.

The public Rust HttpBackendConfig struct gains forward_beta. Downstream struct literals need to add forward_beta: Default::default() or ForwardBeta::All. Existing TOML files need no edit. No body translation code changes.

Validation at d98ae71b, integrated with main 9ddd4879:

  • Rust workspace: 1,109 passed, 1 ignored (external handoff fixture).
  • Prefill-router runner: 82 passed.
  • Workspace and prefill Clippy with warnings denied, formatting, and strict docs build: passed.
  • Python: 198 passed, 2 integration tests deselected, 2 subtests passed; Ruff and mypy passed.
  • Python bindings rebuilt with maturin on Python 3.12; tests used local mocks.

Live Anthropic acceptance and a Claude subscription session were not tested.

Summary by CodeRabbit

  • New Features
    • Added configurable forwarding of Anthropic beta headers: the default forwards OAuth-related values, while "all" preserves all caller-supplied values, including repeated headers. This option requires Anthropic Messages format and authentication forwarding.
  • Documentation
    • Updated configuration guidance and examples to explain the beta-header forwarding options and requirements.

@ting-hong-shieh
ting-hong-shieh marked this pull request as ready for review October 7, 2026 12:21
@ting-hong-shieh
ting-hong-shieh requested a review from a team as a code owner October 7, 2026 12:21
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: NVIDIA-NeMo/Switchyard/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: b9e306b2-febe-4efd-bba6-ac8e6f70cb19
📥 Commits

Reviewing files that changed from the base of the PR and between a3cdc51 and 1df1dd7.

📒 Files selected for processing (9)
  • crates/libsy-llm-client/README.md
  • crates/libsy-llm-client/src/backend.rs
  • crates/libsy-llm-client/src/client.rs
  • crates/libsy-llm-client/src/lib.rs
  • crates/libsy-llm-client/src/run.rs
  • crates/libsy-llm-client/tests/fallback_credit.rs
  • crates/switchyard-runner/src/config.rs
  • crates/switchyard-server/tests/server.rs
  • docs/reference/toml_schema.md

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Walkthrough

The client backend now supports OAuth-filtered or full forwarding of caller-supplied Anthropic beta headers. Runner configuration exposes the policy for Anthropic Messages clients with forwarded authentication. Tests and documentation cover the option and its request behavior.

Changes

Anthropic beta forwarding

Layer / File(s) Summary
Backend policy and forwarding
crates/libsy-llm-client/src/backend.rs, crates/libsy-llm-client/src/lib.rs, crates/libsy-llm-client/README.md
Adds the public ForwardBeta policy. The default forwards the filtered OAuth value; All forwards every caller-supplied beta value unchanged when auth forwarding is enabled.
Runner configuration and validation
crates/switchyard-runner/src/config.rs, docs/reference/toml_schema.md
Adds the optional forward_beta setting. The runner validates that it is used with anthropic_messages and forward_auth = true, then passes the setting to the backend.
Request tests and fixtures
crates/libsy-llm-client/src/client.rs, crates/libsy-llm-client/src/run.rs, crates/libsy-llm-client/tests/fallback_credit.rs, crates/switchyard-server/tests/server.rs
Tests completion and token-counting requests with repeated beta headers. Updates backend test configurations to set the new field’s default.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Severity of issue fixed: Medium

Merge Risk: Minimal · up to 1df1d

No actionable merge-blocking issue is identified; the change is mergeable after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 68.42% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 19 functions across 7 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Linked Issues check Passed [#938] requests opt-in forwarding of caller anthropic-beta values for anthropic_messages clients with forward_auth = true, while retaining OAuth-only filtering by default. ForwardBeta::All for…
Out of Scope Changes check Passed The code, configuration, tests, and documentation changes support [#938]. Updating HttpBackendConfig fixtures and exporting and documenting ForwardBeta are required to integrate the new option. No…
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: enabling forwarding of all Anthropic beta headers.
Full details: Linked Issues check

Explanation

[#938] requests opt-in forwarding of caller anthropic-beta values for anthropic_messages clients with forward_auth = true, while retaining OAuth-only filtering by default. ForwardBeta::All forwards all matching values unchanged, including repeated headers, and the default remains Oauth. Configuration validation and tests cover the required mode and both completion and token-counting paths.

Full details: Out of Scope Changes check

Explanation

The code, configuration, tests, and documentation changes support [#938]. Updating HttpBackendConfig fixtures and exporting and documenting ForwardBeta are required to integrate the new option. No unrelated changes are identified.

Full details: Docstring Coverage

Explanation

Docstring coverage is 68.42% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 19 functions across 7 files. (2 skipped: 2 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

A rabbit checks the headers twice,
OAuth hops along, then All brings more.
Repeated beta values pass in line,
Completion and token counts arrive.
The config burrows into place.

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

@ting-hong-shieh

Copy link
Copy Markdown
Contributor Author

Resolved the runner import conflict and integrated main 9ddd4879 at d98ae71b. Could a maintainer approve the pending fork workflow runs and review the beta-header forwarding policy?

Local validation passed: Rust workspace (1,109 passed, 1 ignored), prefill runner (82 passed), Python (198 passed, 2 integration tests deselected), Clippy, formatting, Ruff, mypy, and strict docs build. Tests used local mocks; live Anthropic acceptance was not tested.

The latest CI, documentation, getting-started, and package-portability runs show action_required. Commitlint separately reports startup_failure before creating a job; could you also help check that workflow? The PR description contains the updated validation details.

@ayushag-nv
ayushag-nv requested a review from grahamking October 28, 2026 00:01
@ayushag-nv

Copy link
Copy Markdown
Contributor

@grahamking to provide feedback

@ayushag-nv

Copy link
Copy Markdown
Contributor

@ting-hong-shieh Meanwhile can you rebase this one please ?

Signed-off-by: Ting-Hong Shieh <shiehharry@gmail.com>
@ting-hong-shieh
ting-hong-shieh force-pushed the feature/938-forward-anthropic-beta branch from d98ae71 to 907a4dc Compare October 28, 2026 03:12
@grahamking

Copy link
Copy Markdown
Contributor

Can you give some examples of those beta headers?

@ting-hong-shieh

Copy link
Copy Markdown
Contributor Author

Two documented non-OAuth examples are:

  • thinking-display-updates-2026-08-18, paired with thinking.display: "updates". Anthropic documents that omitting the beta causes a 400 for that display value.
  • context-management-2025-06-27, paired with the context_management request field. See the context-editing example.

With OAuth-only forwarding, those values are stripped while the paired body fields remain. forward_beta = "all" lets an operator preserve the pair when routing to api.anthropic.com. Claude Code's gateway guide explicitly recommends forwarding the full header because the values change between releases.

These are documented protocol examples, not live acceptance tests of this PR. The option remains opt-in so deployments whose upstream rejects particular betas can retain the current filtering.

@grahamking

Copy link
Copy Markdown
Contributor

The values we're talking about are all in an HTTP anthropic-beta header I think.

We dropped that anthropic-beta HTTP header in #219 because it was incompatible with Azure hosted Anthropic models.

In #372 we started copying the oauth-* values out of anthropic-beta HTTP header so that Claude's auth would work through Switchyard.

On the one hand I don't want such a niche config setting, especially for something that could break Azure endpoints. On the other hand, we do want to support Claude's beta headers.

What are your thoughts @ting-hong-shieh ?

@grahamking grahamking 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.

Discussing...

@ting-hong-shieh

Copy link
Copy Markdown
Contributor Author

I'd prefer to avoid the extra setting by choosing the forwarding policy from the configured upstream URL:

  • With forward_auth = true, forward the full caller-supplied anthropic-beta values for the first-party HTTPS api.anthropic.com endpoint.
  • Keep the existing OAuth-only filtering for other destinations, including Azure. The decision would use the configured upstream URL, not the incoming request's Host header.

That would address the direct-Anthropic case in #938 without changing the Azure forwarding policy. Custom reverse proxies would retain filtering under this approach; supporting them would need a separate decision.

Would that fit the direction you want? If so, I can remove forward_beta from this PR and add explicit first-party/Azure regression coverage, including repeated beta headers.

This branch has not been deployed

No deployments
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.

[feature] forward_auth: option to forward the caller's full anthropic-beta header to api.anthropic.com

3 participants