From 74afe43b920c2b0bfd046f8e5e02392cdeec489c Mon Sep 17 00:00:00 2001 From: mateo-berri <277851410+mateo-berri@users.noreply.github.com> Date: Sat, 5 Sep 2026 21:12:03 -0700 Subject: [PATCH] fix(guardrails): name the call type by value in the post-call skip warning The post-call hook passed the CallTypes member into the warning, so it printed call type 'CallTypes.aresponses' while the pre-call, during-call, and streaming paths printed 'aresponses'. Pass the value like the other three do. Also fixes the pre-call unresolvable-call-type test, which passed a call type that is in the enum, and adds the during-call twin. --- .../unified_guardrail/unified_guardrail.py | 2 +- .../test_unified_guardrail.py | 44 ++++++++++++++++++- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/litellm/proxy/guardrails/guardrail_hooks/unified_guardrail/unified_guardrail.py b/litellm/proxy/guardrails/guardrail_hooks/unified_guardrail/unified_guardrail.py index f17674f3e3a..07573158950 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/unified_guardrail/unified_guardrail.py +++ b/litellm/proxy/guardrails/guardrail_hooks/unified_guardrail/unified_guardrail.py @@ -323,7 +323,7 @@ class UnifiedLLMGuardrails(CustomLogger): if user_api_key_dict.request_route is not None: call_types: Final = get_call_types_for_route(user_api_key_dict.request_route) if call_types is not None and len(call_types) > 0: - call_type = call_types[0] + call_type = call_types[0].value if call_type is None: call_type = _infer_call_type(call_type=None, completion_response=response) diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/unified_guardrails/test_unified_guardrail.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/unified_guardrails/test_unified_guardrail.py index f09ecfa392d..9f4a0d8683f 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/unified_guardrails/test_unified_guardrail.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/unified_guardrails/test_unified_guardrail.py @@ -2452,12 +2452,52 @@ class TestUnscannedRequestIsAnnounced: user_api_key_dict=UserAPIKeyAuth(api_key="test-key", request_route="/v1/moderations"), cache=DualCache(), data=data, - call_type="moderation", + call_type="not_a_call_type", ) assert guardrail.apply_calls == [] assert returned["messages"] == [{"role": "user", "content": "hello world"}] assert any( - "moderation" in message and "skipping pre-call scanning" in message + "call type 'not_a_call_type' has no guardrail translation handler" in message + and "skipping pre-call scanning" in message for message in self._warnings(caplog) ), self._warnings(caplog) + + @pytest.mark.asyncio + async def test_during_call_warns_instead_of_raising_on_a_call_type_outside_the_enum(self, caplog, monkeypatch): + _patch_translation_mappings(monkeypatch, load_guardrail_translation_mappings()) + guardrail = RecordingGuardrail() + data = self._request(guardrail) + + with self._capturing(caplog): + returned = await UnifiedLLMGuardrails().async_moderation_hook( + data=data, + user_api_key_dict=UserAPIKeyAuth(api_key="test-key", request_route="/v1/moderations"), + call_type="not_a_call_type", + ) + + assert guardrail.apply_calls == [] + assert returned["messages"] == [{"role": "user", "content": "hello world"}] + assert any( + "call type 'not_a_call_type' has no guardrail translation handler" in message + and "skipping during-call scanning" in message + for message in self._warnings(caplog) + ), self._warnings(caplog) + + @pytest.mark.asyncio + async def test_post_call_names_the_call_type_the_route_maps_to(self, caplog, monkeypatch): + _patch_translation_mappings(monkeypatch, {CallTypes.aembedding: _NoopTranslation}) + guardrail = RecordingGuardrail() + + with self._capturing(caplog): + await UnifiedLLMGuardrails().async_post_call_success_hook( + data={"guardrail_to_apply": guardrail, "model": "gpt-4o"}, + user_api_key_dict=UserAPIKeyAuth(api_key="test-key", request_route="/v1/responses"), + response=litellm.ModelResponse(), + ) + + assert guardrail.apply_calls == [] + unscanned = [message for message in self._warnings(caplog) if "skipping post-call scanning" in message] + assert unscanned, self._warnings(caplog) + assert "call type 'aresponses'" in unscanned[0], unscanned[0] + assert "CallTypes." not in unscanned[0], unscanned[0]