diff --git a/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py b/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py index 8ec0a89e77d..1e701c9c0d5 100644 --- a/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py +++ b/litellm/proxy/pass_through_endpoints/pass_through_endpoints.py @@ -54,6 +54,7 @@ from litellm.constants import ( ) from litellm.integrations.custom_guardrail import ( CustomGuardrail, + guardrail_entry_names, guardrail_request_data_with_streaming, without_server_streaming_classification, ) @@ -886,14 +887,14 @@ async def _inherit_auth_guardrails( user_api_key_dict=user_api_key_dict, ) merged: Final = (as_str_mapping(parsed_body["metadata"]) or {}).get("guardrails") - if not isinstance(merged, list) or not merged or not _named_guardrail_runs_post_call(parsed_body): - return None - return _GUARDRAIL_ENTRIES.validate_python(merged) + entries: Final = _GUARDRAIL_ENTRIES.validate_python(merged) if isinstance(merged, list) else [] + return entries if entries and _named_guardrail_runs_post_call(parsed_body, entries) else None -def _named_guardrail_runs_post_call(data: Mapping[str, object]) -> bool: +def _named_guardrail_runs_post_call(data: Mapping[str, object], entries: Sequence[object]) -> bool: + names: Final = frozenset(chain.from_iterable(map(guardrail_entry_names, entries))) return any( - guardrail.default_on is not True + guardrail.guardrail_name in names and guardrail.should_run_guardrail( # pyright: ignore[reportUnknownMemberType] # takes the untyped request dict data=data, event_type=GuardrailEventHooks.post_call ) diff --git a/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py b/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py index 2f2955d063f..3cac8a87c9f 100644 --- a/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py +++ b/tests/unit/proxy/pass_through_endpoints/test_pass_through_endpoints.py @@ -11861,6 +11861,20 @@ class TestInheritAuthGuardrails: post_call.assert_not_awaited() assert response.body == b'{\n "id":"chatcmpl-1"\n}' + @pytest.mark.asyncio + async def test_a_named_default_on_post_call_guardrail_still_checks_the_response(self): + auth: Final = UserAPIKeyAuth(api_key="sk-test", metadata={"guardrails": ["global-post"]}) + + _, post_call = await self._run( + self._chat_body(), + inherit=True, + user_api_key_dict=auth, + guardrails=(self._guardrail("global-post", GuardrailEventHooks.post_call, default_on=True),), + ) + + post_call.assert_awaited_once() + assert post_call.call_args.kwargs["data"]["metadata"]["guardrails"] == ["global-post"] + @pytest.mark.asyncio async def test_request_body_guardrails_are_added_to_the_key_guardrails(self): auth: Final = UserAPIKeyAuth(api_key="sk-test", metadata={"guardrails": ["key-guard"]})