feat(messages): route native Anthropic /messages through Rust behind LITELLM_RUST env var - #33848
Conversation
…RUST env var Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
|
|
Greptile SummaryThis PR extends the existing Rust-backed
Confidence Score: 4/5Safe to merge; the Rust path is off by default and falls back to Python on any error, so existing traffic is not disrupted. The core routing logic is a one-line Rust match arm backed by a pre-existing config, and the Python gate preserves the existing fallback contract. The two concerns — the generic
|
| Filename | Overview |
|---|---|
| litellm-rust/crates/ai-gateway/src/messages/common_utils.rs | Adds anthropic to the provider match in messages_provider_config, wiring it to the pre-existing ANTHROPIC_MESSAGES_CONFIG; minimal and correct. |
| litellm-rust/crates/ai-gateway/src/messages/tests.rs | Existing unsupported-provider test updated from anthropic to openai (correct since anthropic is now supported); new round-trip test validates path, x-api-key, and anthropic-version headers. |
| litellm/llms/custom_httpx/llm_http_handler.py | Adds _rust_env_enabled() (reads RUST env var) and expands _maybe_rust_anthropic_messages to accept both azure_ai and anthropic; the generic env var name and its interaction with pre-existing tests deserve attention. |
| tests/test_litellm/anthropic_interface/test_rust_bridge_messages.py | New tests for native-anthropic routing and RUST env var are well-structured; however, two pre-existing tests do not unset the new RUST env var and would fail if it is set externally. |
Comments Outside Diff (1)
-
tests/test_litellm/anthropic_interface/test_rust_bridge_messages.py, line 265-284 (link)Pre-existing tests are now sensitive to the new
RUSTenv vartest_gate_skips_rust_when_flag_absentandtest_gate_skips_rust_when_flag_falseboth useExplodingAsyncMessagesand assert the bridge is never called — but neither unsetsRUSTviamonkeypatch. If the test runner's environment hasRUST=1(or any truthy value),_rust_env_enabled()returnsTrue, the gate no longer short-circuits, and both tests will hitAssertionError("bridge must not be called"). The autouse_reset_rust_flagfixture only resets the litellm bridge state, not the process environment. Addingmonkeypatch.delenv("RUST", raising=False)at the top of both tests would make them robust against the new env var.
Reviews (1): Last reviewed commit: "feat(messages): route native Anthropic /..." | Re-trigger Greptile
| @staticmethod | ||
| def _rust_env_enabled() -> bool: | ||
| return os.getenv("RUST", "").strip().lower() in {"1", "true", "yes", "on"} |
There was a problem hiding this comment.
The env var name
RUST is very short and generic. While the Rust toolchain itself does not export RUST=1, the name is easy to collide with unrelated CI scripts or deployment automation that happen to export a RUST variable for other reasons. A namespaced name like LITELLM_RUST keeps the intent unambiguous and avoids accidental activation in environments not specifically targeting this feature.
| @staticmethod | |
| def _rust_env_enabled() -> bool: | |
| return os.getenv("RUST", "").strip().lower() in {"1", "true", "yes", "on"} | |
| @staticmethod | |
| def _rust_env_enabled() -> bool: | |
| return os.getenv("LITELLM_RUST", "").strip().lower() in {"1", "true", "yes", "on"} |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Agreed, renamed to LITELLM_RUST to keep it namespaced and avoid accidental activation from unrelated env. Done in a461146 (also updated the doc-flag exclusion, the tests, and the PR title/description)
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>
|
Verified: Claude Code CLI -> LiteLLM Rust core (RUST=1) end to end Drove the real
Note: Claude Code emits occasional sub-requests with a |
Co-Authored-By: Ishaan Jaffer <155045088+ishaan-berri@users.noreply.github.com>




Relevant issues
Linear ticket
Pre-Submission checklist
Screenshots / Proof of Fix
Live proof at commit
a461146af8. Local proxy started withLITELLM_RUST=1against a nativeanthropic/claude-haiku-4-5deployment (dev_config.yaml), then:Response headers (Rust path taken + cost still computed by the Python logging/cost path):
Body:
{"content":[{"text":"Hey there, friend!","type":"text"}],"id":"msg_011CdABh2scKsoaVZo5w2nKK", "model":"anthropic-haiku-4-5","role":"assistant","stop_reason":"end_turn", "type":"message","usage":{"input_tokens":15,"output_tokens":8}}Proxy
--detailed_debuglog confirms the upstream is nativehttps://api.anthropic.com/v1/messagesand the response carries_hidden_params.additional_headers = {'x-litellm-rust': 'true'}. WithLITELLM_RUSTunset the same request takes the existing Python path unchanged. This was also verified end to end by driving the real Claude Code CLI (interactive REPL: code + plan tasks) against theLITELLM_RUST=1proxy, with the resulting spend showing up in the LiteLLM UI Logs (call_type=anthropic_messages)Type
🆕 New Feature
Changes
Extends the existing azure_ai Rust
/messagespath (#33616) to the nativeanthropicprovider, gated by an env var so rollout stays off by default.Rust
ai-gateway: registeranthropic -> ANTHROPIC_MESSAGES_CONFIGin themessages_provider_configmap. Thecoreconfig (native/v1/messages,x-api-key,anthropic-versionheader, identity transforms) already existed; this makes it reachable from the HTTP host. Provider resolution, prepare, and handler stay provider-generic perPROVIDER_CODING_STANDARDS.md.Python gate (
BaseLLMHTTPHandler._maybe_rust_anthropic_messages): acceptcustom_llm_provider in {azure_ai, anthropic}, and enable the Rust path when theLITELLM_RUSTenv var is truthy (1/true/yes/on) OR the existinglitellm_params["rust"] is True. The env var is namespacedLITELLM_RUST(not a bareRUST) to avoid colliding with unrelated CI/deployment env. Fallback to the Python path is unchanged (bridge missing, bridge error, disabled). Logging/cost is untouched: Rust returns the response dict withusage, soStandardLoggingPayload+ cost calculation still run — spend continues to be tracked (see thex-litellm-response-costheader above).Tests: Rust
ai-gatewaygains a native-anthropic round-trip test (assertsPOST /v1/messages,x-api-key,anthropic-version) and the provider-map test now expectsanthropicto resolve (unsupported-provider coverage moved toopenai). Pythontest_rust_bridge_messages.pygains cases for native-anthropic routing,LITELLM_RUSTenv enable,LITELLM_RUST=0no-op, and unsupported-provider skip.Validation:
cargo fmt --check,cargo clippy --workspace --all-targets --locked -D warnings,cargo test --workspace --locked(all green);pytest tests/test_litellm/anthropic_interface/test_rust_bridge_messages.py(19 passed);make pre-commitclean.Final Attestation
Link to Devin session: https://app.devin.ai/sessions/db90b4ee508f4e81b5c19568c03cd157
Requested by: @ishaan-berri