Repository navigation
Conversation
|
@greptileai can you reply here with a score and why that score? |
|
bugbot run |
|
Confidence score: 5/5 This directly fixes the root cause: strategy lookup now derives registry keys from the same team-first/global/admin deployment resolution used by deployment selection, so team public names resolve to their internally registered marker deployments without changing the caller-facing model name. Marker filtering is applied consistently to both early and normal resolution paths, including a clear failure for marker-only model groups. The shared team-id extraction also removes the previous metadata-bucket inconsistency. The test coverage is strong: all four strategy registries, team isolation, public-name shadowing, tag selection, proxy-admin access, multi-team ambiguity, marker-only rejection, and parity between strategy and deployment resolution are covered. The provided integration evidence additionally validates chat, streaming, Messages, Responses, admin access, and cross-team denial. The documented shadow-eval and sync-SDK caveats are outside this fix’s requested async proxy path. I found no blocking correctness or security concerns. |
Greptile SummaryThis PR resolves team-scoped auto-router strategies by deriving their internal registry names from the deployments visible through a public team model name. It also centralizes team ID extraction and removes strategy markers from early deployment-resolution results.
Confidence Score: 4/5The PR should not merge until teamless proxy-admin calls apply the same team-scoped compression policy as strategy selection The new admin-across-teams strategy path successfully selects the team router, but its configured compression policy resolves through a narrower lookup and is silently skipped Files Needing Attention: litellm/router.py, litellm/proxy/guardrails/auto_router_compression.py
|
| Filename | Overview |
|---|---|
| litellm/router.py | Adds team-public strategy resolution and shared marker filtering, but the teamless-admin path is not mirrored by compression policy lookup |
| litellm/proxy/guardrails/auto_router_compression.py | Reuses centralized team ID extraction while retaining a deployment resolver that cannot find team-public markers for teamless admins |
| litellm/router_utils/common_utils.py | Centralizes validated team ID extraction and applies it to team-based deployment filtering |
| tests/test_litellm/test_router.py | Adds broad team-public auto-router regression coverage, but does not cover configured compression for a teamless proxy admin |
Reviews (1): Last reviewed commit: "fix(router): resolve team-scoped auto-ro..." | Re-trigger Greptile
| deployments: Final = self._get_all_deployments(model_name=model, team_id=team_id) | ||
| if deployments or team_id is not None or not _is_proxy_admin_request(request_kwargs): | ||
| return deployments | ||
| return self._team_deployments_across_teams(model) |
There was a problem hiding this comment.
Teamless proxy admins resolve the team router here, but compression uses a narrower lookup, silently skipping configured routing and model compression.
Knowledge Base Used:
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.
Fixed in 2537ee3 by removing the third resolver rather than mirroring the admin arm into it: policy_for_model now takes the request kwargs and resolves its markers through Router.deployments_for_request, the same alias, team-first, global, admin-across-teams lookup strategy selection and marker param forwarding use, and team_id_from_request is gone. Pinned by test_compression_policy_follows_the_same_resolution_for_every_principal (team key and teamless proxy admin get the team marker's policy, another team and a keyless caller get none), which fails on the previous revision
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
f03a21e to
2537ee3
Compare
|
Pushed 2537ee3: one round for the shared finding. The compression policy resolver was a third resolver of "which markers does this name mean for this caller", so it now goes through @greptileai can you reply here with a score and why that score? |
|
bugbot run |
|
Confidence score: 5/5 The shared finding is fully addressed in The follow-up removes the duplicated I found no remaining blocking correctness or security concerns. |
A team-scoped auto-router is stored under an internal
model_name_{team_id}_{uuid} with the caller-facing name in
model_info.team_public_model_name, and the four pre-routing strategy
registries key on that internal name. A team key asks for the public name,
so the strategy lookup missed, the team early-resolve exit handed back the
marker deployment itself, and every call 400'd with "Unmapped LLM provider".
The strategy lookup now resolves the requested name through the same
team-first, then global, then admin-across-teams deployment resolution the
deployment path uses, and looks the registries up under the model_name of
whatever that resolves to. Both exits of _common_checks_available_deployment
drop strategy markers through one helper, so a marker-only resolution is
rejected as uncallable on every path. The request team id has one reader.
Resolves LIT-7363
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NU97S7d2FUDDvTk59k53Wp
2537ee3 to
1b9c631
Compare
|
Pushed 1b9c631: the one @greptileai can you reply here with a score and why that score? |
|
bugbot run |
|
Score: 4/5 The fix is well-supported, and the latest test-only follow-up addresses the single I’m holding back the fifth point because required CI is still pending, and the PR documents remaining limitations in shadow-eval validation and the sync SDK path. The |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 1b9c631. Configure here.
|
CI has finished on 1b9c631: 83 checks green, 1 skipped, @greptileai can you reply here with a score and why that score? |
|
Greptile confidence score: 5/5 This is a focused and correct fix. Strategy selection and compression-policy lookup now use the same request-scoped, team-first deployment resolution as the actual deployment path, so team-scoped routers consistently resolve their public names. Shared marker filtering also prevents marker-only deployments from being treated as callable on either resolution path. The tests cover all four strategy registries, team isolation, public-name shadowing, tag selection, proxy-admin access, marker-only rejection, marker-parameter forwarding, compression policy, and agreement between strategy and deployment resolution. The reported end-to-end results additionally verify chat, streaming, Messages, Responses, and access-control behavior. The only failing check is the unrelated newly published |
TLDR
Problem this solves:
How it solves it:
User Flow
Before: a team admin creates a complexity router for their team, sees it listed, and every call to it fails
model_name: "team-router",litellm_params.model: "auto_router/complexity_router", tiers over models the team can use, andmodel_info.team_idset to their team; they get 200team-routerin the list"model": "team-router"and gets 400Unmapped LLM provider for this endpoint. You passed model=complexity_router, custom_llm_provider=auto_routermodel_info.team_idanswers with 200 through its cheapest tierAfter: the same router routes the team's requests like the unscoped one does
team-routerin GET https://litellm-domain/v1/modelsx-litellm-model-namenaming the tier model the router picked and a non-zerox-litellm-response-costRelevant issues
model_name_{team}_{uuid}while requests arrive with the team public name, so no strategy was ever selected for themmodel_group_aliaspointing at an auto-router)Linear ticket
Resolves LIT-7363
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
uv run pytest tests/test_litellm/<your_test_file>.py -v. Leave the suites (make test-unit-*,make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more@greptileaito re-request a review after pushing changes)Screenshots / Proof of Fix
Rig: proxy from this worktree on
127.0.0.1:4737, fresh Postgres,store_model_in_db: true, two tier deployments (haiku-direct,sonnet-direct) pointing at a real upstream gateway, so every 200 below is a billed model call. Setup shared by both runs,$SFXis a per-run suffix so prompts are unique upstream:Both runs listed
["haiku-direct","sonnet-direct","team-router-$SFX"]for the team key and returned 200 to both/model/newcallsBefore (ea0851d)
Team key, POST /v1/chat/completions to the team router
curl -s -D - -X POST $BASE/v1/chat/completions -H "Authorization: Bearer $TEAM_KEY" -H 'Content-Type: application/json' -d '{"model":"team-router-5491","messages":[{"role":"user","content":"Say hi in one word. Reference 5491-1"}]}'(sent three times)HTTP 400,x-litellm-response-cost: 0, body{"error":{"message":"litellm.BadRequestError: Unmapped LLM provider for this endpoint. You passed model=complexity_router, custom_llm_provider=auto_router. ... Received Model Group=team-router-5491\nAvailable Model Group Fallbacks=None","type":"invalid_request_error","code":"400"}}Control: master key, POST /v1/chat/completions to the unscoped twin
"model":"global-router-5491"and the master keyHTTP 200,x-litellm-model-name: anthropic/claude-haiku-4-5,x-litellm-response-cost: 8.900000000000001e-05,x-litellm-model-group: global-router-5491, content"Hey\n\n(Reference: 5491-g)"After (1b9c631)
Team key, POST /v1/chat/completions to the team router
"model":"team-router-0051", sent three timesHTTP 200,x-litellm-model-name: anthropic/claude-haiku-4-5,x-litellm-model-group: team-router-0051,x-litellm-response-cost: 3.9e-05/7.900000000000001e-05/3.9e-05, content"Hi","Hi\n\nReference: 0051-2","Hi"Control: master key, POST /v1/chat/completions to the unscoped twin
"model":"global-router-0051"and the master keyHTTP 200,x-litellm-model-name: anthropic/claude-haiku-4-5,x-litellm-response-cost: 7.900000000000001e-05, content"Hi\n\nReference: 0051-g"Team key, POST /v1/messages to the team router
curl -s -D - -X POST $BASE/v1/messages -H "Authorization: Bearer $TEAM_KEY" -H 'Content-Type: application/json' -d '{"model":"team-router-0051","max_tokens":32,"messages":[{"role":"user","content":"Say hi in one word. Reference 0051-msg"}]}'HTTP 200,x-litellm-model-name: anthropic/claude-haiku-4-5,x-litellm-response-cost: 3.9e-05, body{"model":"team-router-0051","id":"msg_011CetbHnyjB2fuA9PDcQGMa","type":"message","role":"assistant","content":[{"type":"text","text":"Hey"}],...}Team key, POST /v1/responses to the team router
curl -s -D - -X POST $BASE/v1/responses -H "Authorization: Bearer $TEAM_KEY" -H 'Content-Type: application/json' -d '{"model":"team-router-0051","input":"Say hi in one word. Reference 0051-resp"}'HTTP 200,x-litellm-model-name: anthropic/claude-haiku-4-5,x-litellm-response-cost: 3.9e-05, body{"id":"resp_qmppnSVCrPHHBWBzq_HEIaL7BuNQ...Team key, streaming POST /v1/chat/completions to the team router
"stream": trueHTTP 200,x-litellm-model-name: anthropic/claude-haiku-4-5, 3data:chunks, first chunk{"id":"chatcmpl-21cda7e6-7a48-4f1f-9aa5-636690682623","object":"chat.completion.chunk","model":"team-router-0051",...}Proxy admin without a team, POST /v1/chat/completions to the team router by its public name
"model":"team-router-0051"HTTP 200,x-litellm-model-name: anthropic/claude-haiku-4-5,x-litellm-response-cost: 8.900000000000001e-05, content"Hey\n\n(Reference: 0051-admin)"A second team's key, POST /v1/chat/completions to the team router
POST /team/newfor a second team allowed onlyhaiku-direct,POST /key/generateon it, then the same chat body with that keyHTTP 403,{"error":{"message":"team not allowed to access model. This team can only access models=['haiku-direct']. Tried to access team-router-0051","type":"team_model_access_denied","code":"403"}}Type
🐛 Bug Fix
Caveats (if any)
Low
osv-scanis red on GHSA-7w5x-hrqm-74c2 (smol-toml, a dashboard dev dependency this PR does not touch); the advisory published 2026-09-09 18:07 UTC and reds every open PR, fix(ui): bump smol-toml to 1.8.0 to clear GHSA-7w5x-hrqm-74c2 in osv-scan #40442 bumps the lock file_is_configured_pre_routing_strategystill keys on internal names, so it cannot name a team router by its public name; follow-upRouter.get_available_deploymentpath runs no pre-routing hook at all, which predates this PR and only affects SDK-sync callersFinal Attestation
🤖 Generated with Claude Code
https://claude.ai/code/session_01NU97S7d2FUDDvTk59k53Wp