fix(router): register model info under responses/-stripped variant - #27531
Conversation
[Infra] Promote Internal Staging to main
- _create_deployment: register shared model_info under stripped backend key when litellm_params.model contains responses/ (matches post-bridge lookup names). - add_deployment: mirror OLD MODEL REGISTRATION + stripped alias inside model_id block so runtime-loaded deployments match YAML bootstrap. - Tests for model_list init and add_deployment paths. Co-authored-by: Cursor <cursoragent@cursor.com>
Greptile SummaryThis PR fixes a lookup miss in
Confidence Score: 4/5Safe to merge; the fix is narrow and well-tested, with only a minor guard condition that could be tightened. The core logic is correct and both changed code paths are covered by the new tests. The only concern is the guard The two alias-registration blocks in
|
| Filename | Overview |
|---|---|
| litellm/router.py | Registers a stripped alias (without responses/ prefix) in litellm.model_cost for both _create_deployment and add_deployment. The guard condition "responses/" in _model_name is broader than intended — it operates on the fully-formed provider/model string rather than on litellm_params.model directly, which could cause false-positive alias creation for non-responses-API models that happen to contain that substring. |
| tests/test_litellm/test_router_model_cost_isolation.py | Adds two new unit tests verifying that the stripped alias is registered for both model-list and add_deployment paths. Tests use fake API keys and only inspect litellm.model_cost in memory — no real network calls are made, consistent with the mock-only rule for this test directory. |
Reviews (1): Last reviewed commit: "fix(router): register model info under r..." | Re-trigger Greptile
| _backend_alias_cost = {_model_name: _shared_model_info} | ||
| if "responses/" in _model_name: | ||
| _stripped_model_name = _model_name.replace("responses/", "") | ||
| _backend_alias_cost[_stripped_model_name] = _shared_model_info | ||
| litellm.register_model(model_cost=_backend_alias_cost) | ||
|
|
||
| ## Check if LLM Deployment is allowed for this deployment |
There was a problem hiding this comment.
The check
"responses/" in _model_name operates on the fully-constructed provider/model string, so a model named something like azure/custom-responses/v2 (where "responses/" is not a prefix of the model field) would also trigger the alias stripping and produce azure/custom-v2 — a potentially incorrect or conflicting key. A tighter guard that checks only the litellm_params.model field (before prepending the provider) avoids this false-positive. str.replace without count=1 would also replace multiple occurrences of "responses/" if they exist.
| _backend_alias_cost = {_model_name: _shared_model_info} | |
| if "responses/" in _model_name: | |
| _stripped_model_name = _model_name.replace("responses/", "") | |
| _backend_alias_cost[_stripped_model_name] = _shared_model_info | |
| litellm.register_model(model_cost=_backend_alias_cost) | |
| ## Check if LLM Deployment is allowed for this deployment | |
| _backend_alias_cost = {_model_name: _shared_model_info} | |
| if deployment.litellm_params.model.startswith("responses/"): | |
| _stripped_model_name = _model_name.replace("responses/", "", 1) | |
| _backend_alias_cost[_stripped_model_name] = _shared_model_info | |
| litellm.register_model(model_cost=_backend_alias_cost) | |
| ## Check if LLM Deployment is allowed for this deployment |
| _backend_alias_cost = {_model_name: _shared_model_info} | ||
| if "responses/" in _model_name: | ||
| _stripped_model_name = _model_name.replace("responses/", "") | ||
| _backend_alias_cost[_stripped_model_name] = _shared_model_info | ||
| litellm.register_model(model_cost=_backend_alias_cost) | ||
|
|
||
| # add to model names |
There was a problem hiding this comment.
Same overly-broad guard in
add_deployment: "responses/" in _model_name can match a model whose name happens to contain that substring in a non-prefix position. Checking deployment.litellm_params.model.startswith("responses/") is the precise equivalent of what responses_api_bridge_check actually tests, and passing count=1 to replace keeps the replacement bounded.
| _backend_alias_cost = {_model_name: _shared_model_info} | |
| if "responses/" in _model_name: | |
| _stripped_model_name = _model_name.replace("responses/", "") | |
| _backend_alias_cost[_stripped_model_name] = _shared_model_info | |
| litellm.register_model(model_cost=_backend_alias_cost) | |
| # add to model names | |
| _backend_alias_cost = {_model_name: _shared_model_info} | |
| if deployment.litellm_params.model.startswith("responses/"): | |
| _stripped_model_name = _model_name.replace("responses/", "", 1) | |
| _backend_alias_cost[_stripped_model_name] = _shared_model_info | |
| litellm.register_model(model_cost=_backend_alias_cost) | |
| # add to model names |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
d1d2400
into
BerriAI:shin_agent_oss_staging_05_09_2026
|
🤖 litellm-agent: Squash-merged into staging branch Triage Summary 101 lines across 2 files (+91 / -10) Merge Confidence: 5/5 ✅ READY All checks green. Greptile 4/5, no blocking pattern findings, no CircleCI runs (OSS-typical). |
…erriAI#27531) Squash-merged by litellm-agent from krisxia0506's PR.
Relevant issues
When the Router registers a deployment into
litellm.model_cost, the downstreamresponses_api_bridge_check()strips theresponses/prefix from the model name. If a deployment is only registered underazure/responses/..., lookups forazure/...miss, which can affect flags likesupports_native_streaming(e.g. falsely triggering fake streaming).Linear ticket
N/A
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
tests/test_litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unit@greptileaiand received a Confidence Score of at least 4/5 before requesting a maintainer reviewDelays in PR merge?
If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).
CI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Screenshots / Proof of Fix
Unit tests covering both registration paths:
test_responses_prefix_stripped_alias_registered_for_model_listtest_responses_prefix_stripped_alias_registered_for_add_deploymentType
🐛 Bug Fix
✅ Test
Changes
Bug Fix
_create_deployment: after registering the shared backend key, if the deployment'slitellm_params.modelcontainsresponses/, additionally register an alias with that prefix stripped, so post-bridge lookups resolve correctly.add_deployment: on top of the existingmodel_id-level custom pricing registration, mirror the OLD MODEL REGISTRATION and the stripped alias from_create_deployment, so runtime-added deployments match the behavior of YAML-bootstrapped ones.Affected files
litellm/router.pytests/test_litellm/test_router_model_cost_isolation.py