fix: address PR review feedback

- Add missing tpm_limit, rpm_limit, session_tpm_limit, session_rpm_limit
  columns to root schema.prisma to match proxy and extras schemas
- Add backwards-compatible fallback to key metadata for max_iterations
  so existing users don't silently lose enforcement

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Krrish Dholakia 2026-03-05 15:19:12 -08:00
parent bea664389b
commit de81674c6a
2 changed files with 22 additions and 13 deletions

View file

@ -4,7 +4,7 @@ Max Iterations Limiter for LiteLLM Proxy.
Enforces a per-session cap on the number of LLM calls an agentic loop can make.
Callers send a `session_id` with each request (via `x-litellm-session-id` header
or `metadata.session_id`), and this hook counts calls per session. When the count
exceeds `max_iterations` (configured in agent litellm_params), returns 429.
exceeds `max_iterations` (configured in agent litellm_params or key metadata), returns 429.
Works across multiple proxy instances via DualCache (in-memory + Redis).
Follows the same pattern as parallel_request_limiter_v3.py.
@ -52,8 +52,9 @@ class _PROXY_MaxIterationsHandler(CustomLogger):
Pre-call hook that enforces max_iterations per session.
Configuration:
- max_iterations: set in agent litellm_params
- max_iterations: set in agent litellm_params (preferred)
e.g. litellm_params={"max_iterations": 25}
Falls back to key metadata max_iterations for backwards compatibility.
- session_id: sent by caller via x-litellm-session-id header or
metadata.session_id in request body
@ -150,20 +151,24 @@ class _PROXY_MaxIterationsHandler(CustomLogger):
def _get_max_iterations(
self, user_api_key_dict: UserAPIKeyAuth
) -> Optional[int]:
"""Extract max_iterations from agent litellm_params."""
"""Extract max_iterations from agent litellm_params, with fallback to key metadata."""
# Try agent litellm_params first
agent_id = user_api_key_dict.agent_id
if agent_id is None:
return None
if agent_id is not None:
from litellm.proxy.agent_endpoints.agent_registry import (
global_agent_registry,
)
from litellm.proxy.agent_endpoints.agent_registry import \
global_agent_registry
agent = global_agent_registry.get_agent_by_id(agent_id=agent_id)
if agent is not None:
litellm_params = agent.litellm_params or {}
max_iterations = litellm_params.get("max_iterations")
if max_iterations is not None:
return int(max_iterations)
agent = global_agent_registry.get_agent_by_id(agent_id=agent_id)
if agent is None:
return None
litellm_params = agent.litellm_params or {}
max_iterations = litellm_params.get("max_iterations")
# Fallback to key metadata for backwards compatibility
metadata = user_api_key_dict.metadata or {}
max_iterations = metadata.get("max_iterations")
if max_iterations is not None:
return int(max_iterations)
return None

View file

@ -67,6 +67,10 @@ model LiteLLM_AgentsTable {
object_permission_id String?
object_permission LiteLLM_ObjectPermissionTable? @relation(fields: [object_permission_id], references: [object_permission_id])
spend Float @default(0.0)
tpm_limit Int?
rpm_limit Int?
session_tpm_limit Int?
session_rpm_limit Int?
created_at DateTime @default(now()) @map("created_at")
created_by String
updated_at DateTime @default(now()) @updatedAt @map("updated_at")