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)