From 36f6d84c2203fea5a10bdc86a70e84b3326edf38 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Fri, 22 May 2026 20:44:58 +0000 Subject: [PATCH] fix(realtime): avoid double-serialization and normalize non-dict turn_detection in guardrail override - Skip the force-override block when the injection block already ran for the same session.update to avoid redundant JSON re-serialization. - Normalize non-dict client-provided turn_detection values (flat and nested audio.input.turn_detection) to a dict before enforcing create_response=False, matching the injection block's behavior and preventing potential bypass on backends that accept non-dict values. Co-authored-by: Yassin Kortam --- .../litellm_core_utils/realtime_streaming.py | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/litellm/litellm_core_utils/realtime_streaming.py b/litellm/litellm_core_utils/realtime_streaming.py index 2c29c454101..1d3528832df 100644 --- a/litellm/litellm_core_utils/realtime_streaming.py +++ b/litellm/litellm_core_utils/realtime_streaming.py @@ -917,33 +917,40 @@ class RealTimeStreaming: # and bypass the transcription guardrail after the # initial disable. Covers both the flat beta key and the # nested GA ``audio.input.turn_detection`` shape, since - # the GA remap below also accepts either form. + # the GA remap below also accepts either form. Skipped + # when the injection block above already ran for this + # message, to avoid redundant double-serialization. if ( msg_type == "session.update" + and not guardrail_turn_detection_injected and self._has_audio_transcription_guardrails() ): session = msg_obj.get("session") if isinstance(session, dict): td_overridden = False flat_td = session.get("turn_detection") - if ( - isinstance(flat_td, dict) - and flat_td.get("create_response") is not False - ): - flat_td["create_response"] = False - td_overridden = True + if flat_td is not None: + if not isinstance(flat_td, dict): + flat_td = {} + if flat_td.get("create_response") is not False: + flat_td["create_response"] = False + session["turn_detection"] = flat_td + td_overridden = True audio = session.get("audio") if isinstance(audio, dict): audio_input = audio.get("input") if isinstance(audio_input, dict): nested_td = audio_input.get("turn_detection") - if ( - isinstance(nested_td, dict) - and nested_td.get("create_response") - is not False - ): - nested_td["create_response"] = False - td_overridden = True + if nested_td is not None: + if not isinstance(nested_td, dict): + nested_td = {} + if ( + nested_td.get("create_response") + is not False + ): + nested_td["create_response"] = False + audio_input["turn_detection"] = nested_td + td_overridden = True if td_overridden: message = json.dumps(msg_obj)