[Re-issue: Fix] Keys and Teams Router Setting + Allow Override of Router Settings#20205
[Re-issue: Fix] Keys and Teams Router Setting + Allow Override of Router Settings#20205yuneng-jiang merged 5 commits intomainfrom
Conversation
**Root Cause:** When API keys or teams have router_settings configured, the proxy creates per-request Router instances from user_config. These new routers were missing search_tools from the main router, causing "search tool not found" errors despite search_tools being configured. **The Fix:** 1. **common_request_processing.py (lines 554-556):** Pass search_tools from main router to user_config so per-request routers inherit them 2. **proxy_server.py (line 3171):** Remove `if len(_model_list) > 0` check to allow router creation with empty model list (needed for search-tools-only use case) 3. **proxy_server.py (line 746):** Remove redundant search_tools loading code (already handled by _init_search_tools_in_db() called during startup)
fix: search tools not found when using per-request routers
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile OverviewGreptile SummaryThis PR fixes a critical performance issue where Key Changes:
Performance Impact: Confidence Score: 5/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/common_request_processing.py | Replaced per-request Router instantiation with router_settings_override to avoid expensive object creation, following performance guidelines |
| litellm/proxy/route_llm_request.py | Replaced user_config Router instantiation with router_settings_override merging, respecting request-level precedence |
| litellm/router.py | Added per-request model_group_retry_policy override support and updated retry logic to use helper function |
Sequence Diagram
sequenceDiagram
participant Client
participant ProxyServer
participant CommonRequestProcessing
participant RouteRequest
participant Router
participant LLMProvider
Client->>ProxyServer: POST /chat/completions
ProxyServer->>CommonRequestProcessing: process_request()
Note over CommonRequestProcessing: Get hierarchical router settings<br/>(from key/team/global config)
alt Router settings found
CommonRequestProcessing->>CommonRequestProcessing: Store as router_settings_override
Note over CommonRequestProcessing: OLD: Created new Router instance<br/>NEW: Store settings for later merge
end
CommonRequestProcessing->>RouteRequest: route_request(data, router, ...)
alt router_settings_override exists
RouteRequest->>RouteRequest: Extract override_settings
loop For each per_request_setting
RouteRequest->>RouteRequest: Merge into data if not already set
end
Note over RouteRequest: Settings: fallbacks, num_retries,<br/>timeout, model_group_retry_policy, etc.
RouteRequest->>Router: acompletion(**data)
Note over Router: Uses main router with<br/>merged override settings
else No override
RouteRequest->>Router: acompletion(**data)
end
Router->>Router: async_function_with_retries()
Note over Router: Extract per-request overrides:<br/>- fallbacks<br/>- model_group_retry_policy<br/>- timeout, num_retries
Router->>LLMProvider: Make API call
alt Success
LLMProvider-->>Router: Response
Router-->>RouteRequest: Response
RouteRequest-->>ProxyServer: Response
ProxyServer-->>Client: 200 OK
else Error with retry policy
LLMProvider-->>Router: Error
Router->>Router: _get_num_retries_from_retry_policy()
Note over Router: Uses per-request<br/>model_group_retry_policy<br/>if provided
Router->>LLMProvider: Retry with fallback
LLMProvider-->>Router: Response
Router-->>RouteRequest: Response
RouteRequest-->>ProxyServer: Response
ProxyServer-->>Client: 200 OK
end
|
@greptile |
Greptile OverviewGreptile SummaryThis PR optimizes router settings handling to avoid expensive per-request Router instantiation. Previously, when keys or teams had custom router settings, a new Router object was created for each request, which was costly and lost Key changes:
The implementation correctly merges only supported per-request settings ( Confidence Score: 4/5
|
| Filename | Overview |
|---|---|
| litellm/proxy/common_request_processing.py | Retrieves hierarchical router settings (key > team) and passes them as router_settings_override instead of creating new Router |
| litellm/proxy/proxy_server.py | Added _parse_router_settings_value and _get_hierarchical_router_settings methods, removed empty model_list check for Router creation |
| litellm/proxy/route_llm_request.py | Replaced expensive per-request Router instantiation with settings merge into kwargs for main router |
| litellm/router.py | Added per-request model_group_retry_policy override support in retry logic using existing helper function |
Sequence Diagram
sequenceDiagram
participant Client
participant ProxyBaseLLMRequestProcessing
participant ProxyConfig
participant UserAPIKeyCache
participant TeamCache
participant RouteRequest
participant Router
Client->>ProxyBaseLLMRequestProcessing: Request with API Key
ProxyBaseLLMRequestProcessing->>ProxyConfig: _get_hierarchical_router_settings()
ProxyConfig->>UserAPIKeyCache: Get key object (cached)
UserAPIKeyCache-->>ProxyConfig: user_api_key_dict with router_settings
alt Key has router_settings
ProxyConfig-->>ProxyBaseLLMRequestProcessing: Return key-level settings
else No key settings, check team
ProxyConfig->>TeamCache: get_team_object() (cached)
TeamCache-->>ProxyConfig: team object with router_settings
ProxyConfig-->>ProxyBaseLLMRequestProcessing: Return team-level settings
end
ProxyBaseLLMRequestProcessing->>ProxyBaseLLMRequestProcessing: Add router_settings_override to data
ProxyBaseLLMRequestProcessing->>RouteRequest: route_request(data, router)
RouteRequest->>RouteRequest: Extract router_settings_override
RouteRequest->>RouteRequest: Merge allowed settings into data kwargs
Note over RouteRequest: Only merge: fallbacks, context_window_fallbacks,<br/>content_policy_fallbacks, num_retries,<br/>timeout, model_group_retry_policy
RouteRequest->>Router: router.acompletion(**data)
Note over Router: Uses main Router with<br/>per-request overrides<br/>(no new Router created)
Router-->>RouteRequest: Response
RouteRequest-->>Client: Response
|
|
||
| try: | ||
| parsed = yaml.safe_load(value) | ||
| except (yaml.YAMLError, json.JSONDecodeError): |
There was a problem hiding this comment.
yaml.safe_load() doesn't raise JSONDecodeError, only YAMLError. The json.JSONDecodeError in the except clause won't catch yaml parsing failures.
| except (yaml.YAMLError, json.JSONDecodeError): | |
| except yaml.YAMLError: |
Previously, PR #19818 (via #20205) removed the model_list check entirely, causing Router to be created even with no models AND no search_tools. This fix adds back a conditional check that creates the Router only when: - There are models to route, OR - There are search_tools configured This preserves the PR #19818 goal (search-tools-only deployments) while avoiding unnecessary Router creation when there's nothing to route. Fixes test_add_and_delete_deployments[0-None]
) Previously, PR #19818 (via #20205) removed the model_list check entirely, causing Router to be created even with no models AND no search_tools. This fix adds back a conditional check that creates the Router only when: - There are models to route, OR - There are search_tools configured This preserves the PR #19818 goal (search-tools-only deployments) while avoiding unnecessary Router creation when there's nothing to route. Fixes test_add_and_delete_deployments[0-None]
Relevant issues
Fixes #19693
Pre-Submission checklist
Please complete all items before asking a LiteLLM maintainer to review your PR
tests/litellm/directory, Adding at least 1 test is a hard requirement - see detailsmake test-unitCI (LiteLLM team)
Branch creation CI run
Link:
CI run for the last commit
Link:
Merge / cherry-pick CI run
Links:
Type
🐛 Bug Fix
✅ Test
Changes
This PR fixes search tools not being found when using per-request routers by:
Avoiding per-request Router instantiation: Instead of creating a new
Routerinstance when a key/team hasrouter_settings(which is expensive and losessearch_tools), settings are now passed asrouter_settings_overridekwargs to the main router.Creating router even with empty model list: The router is now created even when
model_listis empty ifsearch_toolsare configured, since the router can function with only search tools.Supporting per-request
model_group_retry_policy: Added support formodel_group_retry_policyas a per-request override in the Router's retry logic.Using cached key/team objects for router settings:
_get_hierarchical_router_settingsreads from the already-authenticated key object and the cached team lookup (get_team_object) instead of making direct DB queries on the hot path.The affected settings that can be overridden per-request are:
fallbacks,context_window_fallbacks,content_policy_fallbacks,num_retries,timeout, andmodel_group_retry_policy.Added
router_settingsfield toLiteLLM_VerificationTokento support key-level router settings.Screenshots
Testing
Testing was done mainly with fallbacks with these 3 mappings:
Key: claude-haiku-4-5 will fallback to gpt-4o
Team: claude-haiku-4-5 will fallback to claude-sonnet-4-5
Global: claude-haiku-4-5 will fallback to grok-4-fast-non-reasoning
Team only fallback (key without router settings):

Key and team with router settings:
