litellm/litellm/proxy/hooks
Krish Dholakia 12c4876891
Agents - assign tools (#22064)
* feat(proxy): add max_iterations limiter for agent session loops (#22058)

Adds a new proxy hook that enforces a per-session cap on the number of
LLM calls an agentic loop can make. Callers send a session_id with each
request, and the hook counts calls per session, returning 429 when the
configured max_iterations limit is exceeded.

- Uses Redis Lua script for atomic increment (multi-instance safe)
- Falls back to in-memory cache when Redis unavailable
- Follows parallel_request_limiter_v3 pattern
- Configurable via key metadata: {"max_iterations": 25}
- Session counters auto-expire via TTL (default 1hr)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add new code execution dataset

* feat(agent_endpoints/): allow giving agents keys

* fix: ui fixes

* feat: allow assigning mcp servers to agents

* fix: eliminate duplicate DB queries in MCP agent auth and N+1 in agent listing (#22110)

- Extract _get_agent_object_permission helper so _get_allowed_mcp_servers_for_agent
  and _get_agent_tool_permissions_for_server share a single DB fetch instead of
  each independently querying the same agent row (was 1+N queries per MCP request)
- Use include={"object_permission": True} on find_many in get_all_agents_from_db
  to eagerly load permissions in one query instead of N+1
- Use include={"object_permission": True} on create/update/find_unique in all
  agent CRUD operations, removing attach_object_permission_to_dict follow-up calls

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:44:30 -08:00
..
litellm_skills
mcp_semantic_filter [Feat] - MCP Semantic Filtering Support (#20296) 2026-02-02 18:28:53 -08:00
__init__.py
azure_content_safety.py
batch_rate_limiter.py Add comments 2026-02-14 19:46:56 -05:00
batch_redis_get.py
cache_control_check.py
dynamic_rate_limiter_v3.py
dynamic_rate_limiter.py
example_presidio_ad_hoc_recognizer.json
key_management_event_hooks.py Fix authorization issues, same alias; verified working 2026-02-05 14:14:20 +05:30
max_budget_limiter.py
max_iterations_limiter.py Agents - assign tools (#22064) 2026-02-25 11:44:30 -08:00
model_max_budget_limiter.py fix(proxy): return early instead of raising ValueError when standard_logging_payload is missing (#20851) 2026-02-11 15:45:46 +05:30
parallel_request_limiter_v3.py
parallel_request_limiter.py
prompt_injection_detection.py
proxy_track_cost_callback.py Allow DB fallback for failure metadata enrichment lookups 2026-02-24 19:43:55 -08:00
rate_limiter_utils.py
README.dynamic_rate_limiter_v3.md
responses_id_security.py
user_management_event_hooks.py

Dynamic Rate Limiter v3 - Saturation-Aware Priority-Based Rate Limiting

Overview

The v3 dynamic rate limiter implements saturation-aware rate limiting with priority-based allocation. It balances resource efficiency (allowing unused capacity to be borrowed) with fairness guarantees (enforcing priorities during high load).

Key Behavior:

  • When system is under 80% capacity: Generous mode - allows priority borrowing
  • When system is at/above 80% capacity: Strict mode - enforces normalized priority limits

How It Works

Flow Diagram

┌─────────────────────────────────────────────────────────────┐
│                    Incoming Request                          │
└────────────────────────┬────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────┐
│  1. Check Model Saturation                                   │
│     - Query v3 limiter's Redis counters                      │
│     - Calculate: current_usage / capacity                    │
│     - Returns: 0.0 (empty) to 1.0+ (saturated)              │
└────────────────────────┬────────────────────────────────────┘
                         │
                         ▼
                ┌────────┴────────┐
                │  Saturation?    │
                └────────┬────────┘
                         │
         ┌───────────────┴───────────────┐
         │                               │
         ▼                               ▼
   < 80% (Generous)                >= 80% (Strict)
         │                               │
         ▼                               ▼
┌─────────────────────┐         ┌─────────────────────┐
│  Generous Mode      │         │  Strict Mode        │
│                     │         │                     │
│  - Enforce model-   │         │  - Normalize        │
│    wide capacity    │         │    priority weights │
│  - No priority      │         │    (if over 1.0)    │
│    restrictions     │         │                     │
│  - Allows borrowing │         │  - Create priority- │
│                     │         │    specific         │
│  - First-come-      │         │    descriptors      │
│    first-served     │         │                     │
│    until capacity   │         │  - Enforce strict   │
│                     │         │    limits per       │
│                     │         │    priority         │
└──────────┬──────────┘         └──────────┬──────────┘
           │                               │
           │                               ▼
           │                    ┌──────────────────────┐
           │                    │  Track model usage   │
           │                    │  for future          │
           │                    │  saturation checks   │
           │                    └──────────┬───────────┘
           │                               │
           └───────────────┬───────────────┘
                           │
                           ▼
                    ┌──────────────┐
                    │  v3 Limiter  │
                    │  Check       │
                    └──────┬───────┘
                           │
           ┌───────────────┴───────────────┐
           │                               │
           ▼                               ▼
     OVER_LIMIT                        OK
           │                               │
           ▼                               ▼
   Return 429 Error              Allow Request

Configuration

Priority Reservation

Set priority weights in your proxy configuration:

litellm.priority_reservation = {
    "premium": 0.75,    # 75% of capacity
    "standard": 0.25    # 25% of capacity
}

Priority Reservation Settings

Configure saturation-aware behavior:

litellm.priority_reservation_settings = PriorityReservationSettings(
    default_priority=0.5,           # Default weight for users without explicit priority
    saturation_threshold=0.80,      # 80% - threshold for strict mode enforcement
    tracking_multiplier=10          # 10x - multiplier for non-blocking tracking in strict mode
)

Settings:

  • default_priority (default: 0.5) - Priority weight for users without explicit priority metadata
  • saturation_threshold (default: 0.80) - Saturation level (0.0-1.0) at which strict priority enforcement begins
  • tracking_multiplier (default: 10) - Multiplier for model-wide tracking limits in strict mode

User Priority Assignment

Set priority in user metadata:

user_api_key_dict.metadata = {"priority": "premium"}

Priority Weight Normalization

If priorities sum to > 1.0, they are automatically normalized:

Input:  {key_a: 0.60, key_b: 0.80} = 1.40 total
Output: {key_a: 0.43, key_b: 0.57} = 1.00 total

This ensures total allocation never exceeds model capacity.

Implementation Details

Saturation Detection

  • Queries v3 limiter's Redis counters for model-wide usage
  • Checks both RPM and TPM, returns higher saturation value
  • Non-blocking reads (doesn't increment counters)

Mode Selection

Generous Mode (< 80% saturation):

  • Creates single model-wide descriptor
  • Enforces total capacity only
  • Allows any priority to use available capacity
  • Prevents over-subscription via model-wide limit

Strict Mode (>= 80% saturation):

  • Creates priority-specific descriptors with normalized weights
  • Each priority gets its reserved allocation
  • Tracks model-wide usage separately (non-blocking, 10x multiplier)
  • Ensures fairness under load

Test scenarios covered:

  1. No rate limiting when under capacity
  2. Priority queue behavior during saturation
  3. Spillover capacity for default keys
  4. Over-allocated priorities with normalization
  5. Default priority value handling

_PROXY_DynamicRateLimitHandlerV3

Main handler class inheriting from CustomLogger.

Key Methods:

  • async_pre_call_hook() - Main entry point, routes to generous/strict mode
  • _check_model_saturation() - Queries Redis for current usage
  • _handle_generous_mode() - Enforces model-wide capacity only
  • _handle_strict_mode() - Enforces normalized priority limits
  • _normalize_priority_weights() - Handles over-allocation
  • _create_priority_based_descriptors() - Creates rate limit descriptors