diff --git a/litellm/proxy/guardrails/guardrail_hooks/singulr/singulr.py b/litellm/proxy/guardrails/guardrail_hooks/singulr/singulr.py index 9bb5efd1844..1400ce1cef8 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/singulr/singulr.py +++ b/litellm/proxy/guardrails/guardrail_hooks/singulr/singulr.py @@ -82,7 +82,6 @@ class SingulrGuardrail(CustomGuardrail): if "supported_event_hooks" not in kwargs: kwargs["supported_event_hooks"] = [ GuardrailEventHooks.pre_call, - GuardrailEventHooks.post_call, ] super().__init__(**kwargs) @@ -98,7 +97,7 @@ class SingulrGuardrail(CustomGuardrail): def _build_payload( self, request_data: dict[str, Any], - input_type: Literal["request", "response"], + input_type: str, ) -> dict[str, Any]: request = SingulrGuardrailRequest.model_validate(request_data) if not request.model_dump(exclude_none=True): @@ -178,7 +177,7 @@ class SingulrGuardrail(CustomGuardrail): self, inputs: GenericGuardrailAPIInputs, request_data: dict, - input_type: Literal["request", "response"], + input_type: str, logging_obj: Optional["LiteLLMLoggingObj"] = None, ) -> GenericGuardrailAPIInputs: payload = self._build_payload(cast(dict[str, Any], request_data), input_type) diff --git a/litellm/types/proxy/guardrails/guardrail_hooks/singulr.py b/litellm/types/proxy/guardrails/guardrail_hooks/singulr.py index 74de6017176..b5324a58def 100644 --- a/litellm/types/proxy/guardrails/guardrail_hooks/singulr.py +++ b/litellm/types/proxy/guardrails/guardrail_hooks/singulr.py @@ -39,7 +39,7 @@ class SingulrGuardrailPayload(BaseModel): """Payload sent to the Singulr guardrail API.""" request: SingulrGuardrailRequest - input_type: Literal["request", "response"] + input_type: str class SingulrGuardrailConfigModel(GuardrailConfigModel): diff --git a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_singulr.py b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_singulr.py index 2243cae1e3b..c30105d8aa3 100644 --- a/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_singulr.py +++ b/tests/test_litellm/proxy/guardrails/guardrail_hooks/test_singulr.py @@ -11,6 +11,7 @@ import pytest from litellm.exceptions import GuardrailRaisedException from litellm.proxy.guardrails.guardrail_hooks.singulr.singulr import SingulrGuardrail +from litellm.types.guardrails import GuardrailEventHooks from litellm.types.proxy.guardrails.guardrail_hooks.singulr import ( SingulrGuardrailConfigModel, ) @@ -104,6 +105,13 @@ class TestSingulrConfiguration: SingulrGuardrail(api_key="test_key", api_base="https://remote.singulr.ai") mock_logger.warning.assert_not_called() + def test_only_supports_pre_call_hook(self): + """Singulr only forwards the original request; there is no response + text available to scan on the post_call path, so post_call must not + be registered as a supported event hook.""" + guardrail = SingulrGuardrail(api_key="test_key") + assert guardrail.supported_event_hooks == [GuardrailEventHooks.pre_call] + # --------------------------------------------------------------------------- # Allow decision @@ -314,18 +322,6 @@ class TestSingulrBuildPayload: def test_empty_request_returns_empty_payload(self, singulr_guardrail): assert singulr_guardrail._build_payload({}, "request") == {} - def test_response_input_type_forwards_request_messages(self, singulr_guardrail): - """input_type="response" currently forwards the same request payload - shape as input_type="request" -- no separate response body is sent.""" - request_data = {"messages": [{"role": "user", "content": "hi"}]} - payload = singulr_guardrail._build_payload(request_data, "response") - assert payload["input_type"] == "response" - assert payload["request"]["messages"] == [{"role": "user", "content": "hi"}] - assert "response" not in payload - - def test_response_returns_empty_payload_when_no_messages(self, singulr_guardrail): - assert singulr_guardrail._build_payload({}, "response") == {} - # --------------------------------------------------------------------------- # Tool definition scanning