From 89330cdac6e3b103421114e1385efe719e417534 Mon Sep 17 00:00:00 2001 From: yassin Date: Thu, 17 Sep 2026 20:34:06 +0000 Subject: [PATCH] refactor(agents): exhaust the agent access match and drop routine comments Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../mcp_server/auth/user_api_key_auth_mcp.py | 3 --- .../auth/agent_permission_handler.py | 14 ++++---------- litellm/proxy/auth/auth_checks.py | 5 +---- 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py index 05661584a6b..4bca15190cf 100644 --- a/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py +++ b/litellm/proxy/_experimental/mcp_server/auth/user_api_key_auth_mcp.py @@ -193,9 +193,6 @@ def _agent_capped_servers( agent_servers: Sequence[str], agent_access_group_servers: frozenset[str] | None, ) -> tuple[str, ...] | None: - """Servers left once the agent's object_permission and attached access groups both cap the - key/team result, or None when the agent restricts nothing. An attached group set naming no - server is an empty ceiling, not an absent one, so it denies every server.""" if not agent_servers and agent_access_group_servers is None: return None return tuple( diff --git a/litellm/proxy/agent_endpoints/auth/agent_permission_handler.py b/litellm/proxy/agent_endpoints/auth/agent_permission_handler.py index 1759090a29a..ea73d4634e3 100644 --- a/litellm/proxy/agent_endpoints/auth/agent_permission_handler.py +++ b/litellm/proxy/agent_endpoints/auth/agent_permission_handler.py @@ -8,7 +8,7 @@ Follows the same pattern as MCP permission handling. import asyncio from collections.abc import Awaitable, Callable, Sequence from dataclasses import dataclass -from typing import Final, TypeAlias +from typing import Final, TypeAlias, assert_never from litellm._logging import verbose_logger from litellm.proxy._experimental.mcp_server.ui_session_utils import build_effective_auth_contexts @@ -67,14 +67,7 @@ class AgentRequestHandler: user_api_key_auth: UserAPIKeyAuth | None = None, resolve_ceiling: CeilingResolver = resolve_agent_access_group_ceiling, ) -> AgentAccess: - """ - Resolve the agents the given user/key may reach. - - ``UnrestrictedAgentAccess`` is only returned when neither the key nor its team - carries any grant and the agent behind the key has no access groups attached. - Grants that intersect to nothing stay restricted, so narrowing a caller can - never widen what it reaches. - """ + """Agents the key may reach: key and team grants intersected with the agent's access group ceiling.""" key_team_access: Final = await AgentRequestHandler._resolve_key_team_agent_access(user_api_key_auth) agent_ceiling: Final = await AgentRequestHandler._agent_access_group_ceiling(user_api_key_auth, resolve_ceiling) if agent_ceiling is None: @@ -84,6 +77,8 @@ class AgentRequestHandler: return RestrictedAgentAccess(agent_ceiling) case RestrictedAgentAccess(key_team_ids): return RestrictedAgentAccess(key_team_ids & agent_ceiling) + case _: + assert_never(key_team_access) @staticmethod async def _resolve_key_team_agent_access( @@ -111,7 +106,6 @@ class AgentRequestHandler: user_api_key_auth: UserAPIKeyAuth | None, resolve_ceiling: CeilingResolver, ) -> frozenset[str] | None: - """Stable IDs of the agents the calling agent's attached access groups allow; None when none attached.""" if user_api_key_auth is None or not user_api_key_auth.agent_id: return None ceiling: Final = await resolve_ceiling(user_api_key_auth.agent_id) diff --git a/litellm/proxy/auth/auth_checks.py b/litellm/proxy/auth/auth_checks.py index 137cf849389..df20358bcce 100644 --- a/litellm/proxy/auth/auth_checks.py +++ b/litellm/proxy/auth/auth_checks.py @@ -1007,7 +1007,6 @@ async def common_checks( code=status.HTTP_400_BAD_REQUEST, ) - # 2.4 If the agent behind the key has access groups attached, they cap the models it can call await _check_agent_access_group_model_access(model=_model, valid_token=valid_token, llm_router=llm_router) ## 2.1 If user can call model (if personal key) @@ -4205,9 +4204,7 @@ async def _check_agent_access_group_model_access( llm_router: Router | None, resolve_ceiling: CeilingResolver = resolve_agent_access_group_ceiling, ) -> Literal[True]: - """Raises when the key's agent has access groups attached and none of them names the model. - Attached groups that name no model deny every model; ``_can_object_call_model`` would read - an empty allowlist as unrestricted.""" + """Attached groups naming no model deny every model, unlike the empty allowlist ``_can_object_call_model`` allows.""" if not model or valid_token is None or not valid_token.agent_id: return True ceiling: Final = await resolve_ceiling(valid_token.agent_id)