litellm/litellm-rust/crates
Nate Armstrong 9752869d84
feat(router): add the Rust router core with the host as its only boundary (#49513)
Adds the litellm-router-core crate, its step-driven PyO3 bridge
(RouterCoreHandle / RouterCall) and RustCore (litellm/router_rust/),
served behind LITELLM_RUST through the ROUTER route rule. The host
call-out is the only boundary: every attempt goes through Host::invoke,
there is no native executor path, and RustCore never builds, wraps or
forwards to PythonCore, so router_python_core.py stays deletable.
Attempt preparation lives in litellm/router_attempt.py so it outlives
router_python_core.py.

RustCore matches PythonCore's behavior, including its known bugs (fixed
in follow-up PRs). Routing decisions (strategy picks, routing groups,
PTU, pre-routing, pre-call checks, fallback walk, health routing, access
groups, weights, cooldowns, allowed fails, usage) live in the crate;
work that needs live Python objects (request shaping, endpoints,
streaming, model info facts, callbacks, alerting, prompt management)
lives in the host-side litellm/router_rust/ package (steps/, invoke/,
surface/) driven by Rust steps.

The crate owns the registry. It runs the deployment build loop (secret
references, ids, organization fan-out, install order) and asks the host
for what needs Python, one deployment at a time so errors surface where
Python raised them: secrets, validate, provider and added steps. It
holds the model list, the index maps and the pattern routers with the
Python core's history rules (host_index.rs), and answers the registry
lookups (lookup.rs). The Python views of that state in
litellm/router_rust/surface/ (model_list, index(), names(), patterns())
read the handle, and every write to them becomes a changeset. Model
info, deployment model info, configured limits and model group info are
merged in the crate (model_info.rs, group_info.rs) from catalog rows and
facts the host answers on a model_info step asked at query time, so
price reloads and register_model stay visible. The usage cache key
format is defined once, in the crate.

The crate records each attempt's outcome itself rather than through
litellm callbacks. A streamed attempt is deferred: it counts its
request when the stream opens, and the host's stream wrappers report
the success with the final usage, or a failure after the first chunk,
when the stream ends, as the Python core's callbacks do.

tests/unit/test_router/core characterizes PythonCore's public behavior
and runs every test on both cores, with nothing pending; only the names
of the Python core's own outcome callbacks are asserted on Python alone.

litellm.Router is now final: subclassing it raises TypeError at the class statement, and the
machinery that kept subclass overrides working is gone. The Rust core never honoured subclass
overrides, so they would have silently stopped running there. Custom routing goes through
register_plugin(), settings through apply() and outcomes through observe(). This is a breaking
change for anyone subclassing Router.

Fuzz parity fixes on top of the rebase: the Rust core keeps num_retries,
max_fallbacks, allowed_fails, retry_after, timeout, the tag settings,
routing_strategy_args and the fallback lists as given (the crate reads
them as numbers, update_settings casts as Python does); a deprecated
`model_list = [...]` write reaches the Rust core; a failed set_model_list
is all or nothing on both cores (the deployments served before the call
are put back and the error raised); config_deployments() is a generator and `del` of a plain
attribute works on the Rust core. Least-busy pick reservations from
main now work on the Rust core: its selectors share one reservation
store, routed calls reserve and free their unstarted picks, and
select() and batch cancel do not reserve. On the Python core a dropped
upsert takes its name back off deployment_names, and
get_deployment_order reads every numeric spelling as one int so mixed
orders no longer raise TypeError.

Rulings on the remaining differences, the Python core changed where it
was the odd one out: sync picks and picks by deployment id apply the
team filter as async picks do, so another team's deployment is refused;
the fallback lists and default_litellm_params in RouterSettings are
copies, so an in-place edit is ignored and settings change only through
apply(); one health record with an unreadable timestamp drops out alone;
an empty fallback entry is skipped; a bool cooldown_time is refused at
construction, a bool or string cooldown_time on a deployment or a call
falls back to the router default, and a failure status that no HTTP
status can be is recorded as 500; an infinite or NaN cost and a whole
number wider than 64 bits (ptu_shares) are refused on both cores with
the same error (litellm/router_utils/deployment_numbers.py); and a
/v1/messages stream whose provider iterator raises cools the deployment
and retries like a non-stream call, with the Rust core waiting for that
cooldown before its retry picks.

Differences the proxy parity fuzz and its regression tests found on the
Rust core: a file upload or a batch on an uploaded file falls back only
within its own model group, as on the Python core, since the file lives
with one provider (the host sends same_group_fallbacks_only and the walk
skips targets in other groups); Decisions calls drop deployments whose
provider has no Decisions config, and deployments that refuse the audio
or videos a call carries, unless that would leave none, as the Python
core does, while the retry count still reads the whole group; a file
upload that fails on one order level is created on the next level's
deployments rather than the first level again; and a response that
cannot be converted (a text_completion body without a message) reports
only its own traceback, so a rate limit handled by the attempt before it
no longer turns the error into a 429, and both cores return 500.
2026-11-04 21:47:58 -08:00
..
auth refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
auth-aws fix(auth): align cloud credential loading and expiry with the Python SDKs (#49589) 2026-11-05 07:18:19 +09:00
auth-azure fix(auth): align cloud credential loading and expiry with the Python SDKs (#49589) 2026-11-05 07:18:19 +09:00
auth-gcp fix(auth): align cloud credential loading and expiry with the Python SDKs (#49589) 2026-11-05 07:18:19 +09:00
auth-types fix(auth): align cloud credential loading and expiry with the Python SDKs (#49589) 2026-11-05 07:18:19 +09:00
cache refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
cache-azure-blob refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
cache-disk refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
cache-gcs fix(auth): align cloud credential loading and expiry with the Python SDKs (#49589) 2026-11-05 07:18:19 +09:00
cache-memory refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
cache-qdrant-semantic refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
cache-response refactor(cache): remove experimental Redis and v2 caches (#50005) 2026-11-04 04:54:08 +00:00
cache-s3 fix(auth): align cloud credential loading and expiry with the Python SDKs (#49589) 2026-11-05 07:18:19 +09:00
cache-testing refactor(rust): align the cache crates with Python and wire every native backend (#42530) 2026-09-22 13:13:02 -07:00
callbacks-legacy-python fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
circuit-breaker feat(rust): add circuit-breaker crate and guard redis-client with it (#48277) 2026-10-26 18:41:47 -07:00
config refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
core-utils fix(anthropic): map pause_turn and return refusal explanations on chat and responses (#49192) 2026-10-31 02:53:59 -07:00
coroutine refactor(rust-bridge): return an unstarted Execution from native entrypoints and drive it in Python (#46299) 2026-10-14 17:50:44 -07:00
cost feat(model-catalog): add fedramp_uplift_multiplier (#49950) 2026-11-03 14:55:51 -08:00
db feat(db): add typed daily end-user spend upsert (#48237) 2026-10-26 17:05:08 -07:00
db-testing feat(rust): add redis-client crate for standalone Redis (#48269) 2026-10-26 18:41:46 -07:00
error refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
framer refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
gateway refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
gateway-auth refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
gateway-inference refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
gateway-management refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
gateway-mcp refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
gateway-ui refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
host fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
host-http fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
host-native fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
host-python fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
http fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
inference fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
inference-chat fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
inference-messages fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
inference-ocr fix(auth): align cloud credential loading and expiry with the Python SDKs (#49589) 2026-11-05 07:18:19 +09:00
inference-responses fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
inference-testing refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
inference-transcription feat(rust): one typed decline from core up to each host (#47772) 2026-10-28 09:22:11 -07:00
litellm refactor(rust): expand logging and test coverage across gateway and Anthropic messages (#43295) 2026-09-26 08:04:19 +00:00
llms fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
llms-types fix(messages): make rust messages copy python messages behaviour (#49611) 2026-11-02 21:02:52 -08:00
model-catalog feat(model-catalog): add fedramp_uplift_multiplier (#49950) 2026-11-03 14:55:51 -08:00
model-catalog-refresh refactor(model-catalog): parse, lower and validate the catalog into typed prices (#48853) 2026-10-28 18:24:40 -07:00
python-bridge feat(router): add the Rust router core with the host as its only boundary (#49513) 2026-11-04 21:47:58 -08:00
python-compat refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
redis-client refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
redis-testing feat(gateway): connect to Redis from config.yaml (#48284) 2026-10-26 18:41:47 -07:00
router fix(vertex_ai)!: send the caller's anthropic-version in the Vertex Claude /v1/messages body, not the header (#48814) 2026-10-28 18:06:58 -07:00
router-core feat(router): add the Rust router core with the host as its only boundary (#49513) 2026-11-04 21:47:58 -08:00
router-types refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
secret-value fix(auth): align cloud credential loading and expiry with the Python SDKs (#49589) 2026-11-05 07:18:19 +09:00
secrets refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
secrets-aws fix(auth): align cloud credential loading and expiry with the Python SDKs (#49589) 2026-11-05 07:18:19 +09:00
secrets-azure refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
secrets-cyberark refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
secrets-google refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
secrets-hashicorp refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
secrets-types refactor(rust): extract SecretValue and use it for Redis credentials (#49186) 2026-10-30 11:31:04 -07:00
spend-clickhouse refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
storage-clickhouse refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
testkit refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
token-counter refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
token-counter-fast refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
token-counter-huggingface refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
token-counter-tiktoken refactor(rust): adopt one error discipline across litellm-rust with source chains and Report (#48042) 2026-10-28 09:22:11 -07:00
tracing feat(rust): add structured route lifecycle tracing (#43466) 2026-09-27 19:18:58 -07:00