From c9f0fa5af7cba8ceeaac3d6f7b032c40a31de292 Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Mon, 23 Feb 2026 20:44:03 -0800 Subject: [PATCH] refactor(realtime): call apply_guardrail directly, remove dedicated hook method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The async_realtime_input_transcription_hook in CustomGuardrail and ContentFilterGuardrail was just a thin wrapper that called apply_guardrail — the same interface used by /chat and /messages. Remove the wrapper and call apply_guardrail directly from run_realtime_guardrails, keeping the pattern consistent across all endpoints. --- litellm/integrations/custom_guardrail.py | 15 --------------- litellm/litellm_core_utils/realtime_streaming.py | 8 ++++---- .../litellm_content_filter/content_filter.py | 16 ---------------- 3 files changed, 4 insertions(+), 35 deletions(-) diff --git a/litellm/integrations/custom_guardrail.py b/litellm/integrations/custom_guardrail.py index 18590a6b73b..bf330944ef8 100644 --- a/litellm/integrations/custom_guardrail.py +++ b/litellm/integrations/custom_guardrail.py @@ -334,21 +334,6 @@ class CustomGuardrail(CustomLogger): return kwargs - async def async_realtime_input_transcription_hook( - self, - transcription: str, - user_api_key_dict: Optional[Any], - session_id: Optional[str] = None, - ) -> None: - """ - Called when a user's voice transcription completes in a Realtime API session, - before the LLM generates a response. - - Raise an exception to block the response. - Return None to allow the LLM to respond. - """ - return None - async def async_post_call_success_deployment_hook( self, request_data: dict, diff --git a/litellm/litellm_core_utils/realtime_streaming.py b/litellm/litellm_core_utils/realtime_streaming.py index e8f04901f7c..1599420f20a 100644 --- a/litellm/litellm_core_utils/realtime_streaming.py +++ b/litellm/litellm_core_utils/realtime_streaming.py @@ -155,10 +155,10 @@ class RealTimeStreaming: ): continue try: - await callback.async_realtime_input_transcription_hook( - transcription=transcript, - user_api_key_dict=self.user_api_key_dict, - session_id=item_id, + await callback.apply_guardrail( + inputs={"texts": [transcript], "images": []}, + request_data={"user_api_key_dict": self.user_api_key_dict}, + input_type="request", ) except Exception as e: # Extract the human-readable error from HTTPException detail dict, diff --git a/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py b/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py index abdc1482c43..f653d4602d9 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py +++ b/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py @@ -1921,22 +1921,6 @@ class ContentFilterGuardrail(CustomGuardrail): # We already reached the end of the generator pass - async def async_realtime_input_transcription_hook( - self, - transcription: str, - user_api_key_dict, - session_id=None, - ) -> None: - """ - Run content filter checks on a Realtime API speech transcription. - Raises ValueError if the transcription contains blocked content. - """ - await self.apply_guardrail( - inputs={"texts": [transcription], "images": []}, - request_data={}, - input_type="request", - ) - @staticmethod def get_config_model(): from litellm.types.proxy.guardrails.guardrail_hooks.litellm_content_filter import (