From ccb4792ce0cea0660390ecc4aa1ba2799326fdd2 Mon Sep 17 00:00:00 2001 From: Joshua Valluru <326636767+joshua-berri@users.noreply.github.com> Date: Sat, 26 Sep 2026 15:43:28 -0700 Subject: [PATCH] fix(agents): recognize versioned A2A invocation routes --- litellm/proxy/_types.py | 1 + .../auth/test_managed_authorization.py | 15 ++++++++++++- .../common_utils/test_http_parsing_utils.py | 21 ++++++++++++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index 0cf6d34bd6e..a08b132a322 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -569,6 +569,7 @@ class LiteLLMRoutes(enum.Enum): "/agents", "/a2a/{agent_id}", "/a2a/{agent_id}/message/send", + "/v1/a2a/{agent_id}/message/send", "/a2a/{agent_id}/message/stream", "/a2a/{agent_id}/.well-known/agent-card.json", ) diff --git a/tests/test_litellm/proxy/agent_endpoints/auth/test_managed_authorization.py b/tests/test_litellm/proxy/agent_endpoints/auth/test_managed_authorization.py index 7e1e4e6c51f..75259ece614 100644 --- a/tests/test_litellm/proxy/agent_endpoints/auth/test_managed_authorization.py +++ b/tests/test_litellm/proxy/agent_endpoints/auth/test_managed_authorization.py @@ -1,3 +1,4 @@ +from collections.abc import Mapping from typing import Final import pytest @@ -112,6 +113,11 @@ def test_matching_identity_revision_and_execution_mode_pass_admission(mode: str, ("/v1/realtime/client_secrets", "POST", False), ("/mcp/tools/call", "POST", True), ("/a2a/target/message/send", "POST", True), + ("/v1/a2a/target/message/send", "POST", True), + ("/v1/videos", "POST", False), + ("/v1/videos/other-video", "GET", False), + ("/v1/search", "POST", False), + ("/search", "POST", False), ("/v1/agents/target", "PATCH", False), ("/v1/responses/other-response", "GET", False), ("/v1/files", "GET", False), @@ -142,7 +148,14 @@ def test_managed_route_scope_excludes_provider_resources(route: str, method: str ("/v1beta/models/path:countTokens", {"model": "body"}, {"completion_model": "text"}, "cli", "path", "path"), ], ) -def test_managed_inference_resolves_dispatch_precedence(route, body, settings, cli_model, path_model, expected): +def test_managed_inference_resolves_dispatch_precedence( + route: str, + body: Mapping[str, object], + settings: Mapping[str, object], + cli_model: str | None, + path_model: str | None, + expected: str | None, +) -> None: from litellm.proxy.agent_endpoints.auth.managed_authorization import managed_inference_request assert managed_inference_request(route, body, settings, cli_model, path_model).get("model") == expected diff --git a/tests/test_litellm/proxy/common_utils/test_http_parsing_utils.py b/tests/test_litellm/proxy/common_utils/test_http_parsing_utils.py index d11d0ee3a58..6087aa1f570 100644 --- a/tests/test_litellm/proxy/common_utils/test_http_parsing_utils.py +++ b/tests/test_litellm/proxy/common_utils/test_http_parsing_utils.py @@ -1,6 +1,7 @@ import io import json -from typing import get_type_hints +from collections.abc import Mapping +from typing import Literal, get_type_hints from unittest.mock import AsyncMock, MagicMock, patch import orjson @@ -1219,7 +1220,14 @@ class TestCoerceNumericFormFields: ("completion", {}, "cli", "path", "body", "cli"), ("completion", {}, None, "path", "body", "path"), ("completion", {}, None, None, "body", "body"), - ("image_generation", {"completion_model": "text", "image_generation_model": "image"}, None, None, "body", "image"), + ( + "image_generation", + {"completion_model": "text", "image_generation_model": "image"}, + None, + None, + "body", + "image", + ), ("image_generation", {"image_generation_model": "image"}, "cli", "path", "body", "cli"), ("image_generation", {"image_generation_model": "image"}, None, "path", "body", "path"), ("image_edit", {"completion_model": "text", "image_generation_model": "image"}, None, None, "body", "text"), @@ -1231,7 +1239,14 @@ class TestCoerceNumericFormFields: ("path", {"completion_model": "text"}, "cli", "path", "body", "path"), ], ) -def test_shared_inference_model_selection_preserves_handler_precedence(kind, settings, cli, path, body, expected): +def test_shared_inference_model_selection_preserves_handler_precedence( + kind: Literal["completion", "image_generation", "image_edit", "moderation", "speech", "body", "path"], + settings: Mapping[str, object], + cli: str | None, + path: str | None, + body: str, + expected: str, +) -> None: from litellm.proxy.common_utils.http_parsing_utils import resolve_inference_model assert resolve_inference_model(body, settings, cli, path, kind=kind) == expected