From 55a641e2584d14c2dfff6fe65561331b08229646 Mon Sep 17 00:00:00 2001 From: dhruvladia-sarvam Date: Sun, 1 Mar 2026 22:10:27 +0530 Subject: [PATCH 1/3] fix(sarvam): standardize STT/TTS User-Agent headers --- src/pipecat/services/sarvam/stt.py | 34 +++++++++++++++++------------- src/pipecat/services/sarvam/tts.py | 11 ++++++---- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/pipecat/services/sarvam/stt.py b/src/pipecat/services/sarvam/stt.py index 379473c6f..f4ebf7574 100644 --- a/src/pipecat/services/sarvam/stt.py +++ b/src/pipecat/services/sarvam/stt.py @@ -266,15 +266,10 @@ class SarvamSTTService(STTService): # Initialize Sarvam SDK client self._sdk_headers = sdk_headers() - # NOTE: We avoid passing non-standard kwargs here because different sarvamai - # versions expose different constructor signatures (static type checkers - # complain otherwise). We instead inject headers best-effort below. - self._sarvam_client = AsyncSarvamAI(api_subscription_key=api_key) - for attr in ("default_headers", "_default_headers", "headers", "_headers"): - d = getattr(self._sarvam_client, attr, None) - if isinstance(d, dict): - d.update(self._sdk_headers) - break + # Pass Pipecat SDK headers directly at client construction time so they are + # merged by the Sarvam SDK's client wrapper and consistently applied to + # WebSocket handshake requests. + self._sarvam_client = AsyncSarvamAI(api_subscription_key=api_key, headers=self._sdk_headers) self._websocket_context = None self._socket_client = None self._receive_task = None @@ -517,20 +512,29 @@ class SarvamSTTService(STTService): connect_kwargs["prompt"] = self._settings.prompt def _connect_with_sdk_headers(connect_fn, **kwargs): - # Different SDK versions may use different kwarg names. # If prompt is unsupported at connect-time, retry without it. + # Headers are supplied through request_options because this is a + # documented SDK parameter that survives SDK signature changes. + request_options = {"additional_headers": self._sdk_headers} + logger.debug( + f"Sarvam STT connect request_options.additional_headers: " + f"{request_options['additional_headers']}" + ) attempts = [kwargs] if "prompt" in kwargs: attempts.append({k: v for k, v in kwargs.items() if k != "prompt"}) last_type_error = None for attempt_kwargs in attempts: - for header_kw in ("headers", "additional_headers", "extra_headers"): - try: - return connect_fn(**attempt_kwargs, **{header_kw: self._sdk_headers}) - except TypeError as e: - last_type_error = e try: + return connect_fn( + **attempt_kwargs, + request_options=request_options, + ) + except TypeError as e: + last_type_error = e + try: + # Fallback for SDK builds that don't expose request_options. return connect_fn(**attempt_kwargs) except TypeError as e: last_type_error = e diff --git a/src/pipecat/services/sarvam/tts.py b/src/pipecat/services/sarvam/tts.py index 87604a9f9..e92ade2e5 100644 --- a/src/pipecat/services/sarvam/tts.py +++ b/src/pipecat/services/sarvam/tts.py @@ -1013,12 +1013,15 @@ class SarvamTTSService(InterruptibleTTSService): if self._websocket and self._websocket.state is State.OPEN: return + ws_additional_headers = { + "api-subscription-key": self._api_key, + **sdk_headers(), + } + self._websocket = await websocket_connect( self._websocket_url, - additional_headers={ - "api-subscription-key": self._api_key, - **sdk_headers(), - }, + additional_headers=ws_additional_headers, + user_agent_header=None, ) logger.debug("Connected to Sarvam TTS Websocket") await self._send_config() From 1242f1c10ef0404a03346c0489eceac749548732 Mon Sep 17 00:00:00 2001 From: dhruvladia-sarvam Date: Mon, 2 Mar 2026 17:29:03 +0530 Subject: [PATCH 2/3] changelog entry --- changelog/3886.other.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog/3886.other.md diff --git a/changelog/3886.other.md b/changelog/3886.other.md new file mode 100644 index 000000000..0e9fdafed --- /dev/null +++ b/changelog/3886.other.md @@ -0,0 +1 @@ +- Standardized Sarvam STT/TTS User-Agent header handling to consistently send Pipecat SDK identity in websocket requests. \ No newline at end of file From f386722ef9dfd038ae1fe4100b7671086cd02023 Mon Sep 17 00:00:00 2001 From: dhruvladia-sarvam Date: Mon, 2 Mar 2026 20:38:39 +0530 Subject: [PATCH 3/3] removing unnecessary logs --- src/pipecat/services/sarvam/stt.py | 5 +---- src/pipecat/services/sarvam/tts.py | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/pipecat/services/sarvam/stt.py b/src/pipecat/services/sarvam/stt.py index f4ebf7574..9e245aece 100644 --- a/src/pipecat/services/sarvam/stt.py +++ b/src/pipecat/services/sarvam/stt.py @@ -516,10 +516,7 @@ class SarvamSTTService(STTService): # Headers are supplied through request_options because this is a # documented SDK parameter that survives SDK signature changes. request_options = {"additional_headers": self._sdk_headers} - logger.debug( - f"Sarvam STT connect request_options.additional_headers: " - f"{request_options['additional_headers']}" - ) + attempts = [kwargs] if "prompt" in kwargs: attempts.append({k: v for k, v in kwargs.items() if k != "prompt"}) diff --git a/src/pipecat/services/sarvam/tts.py b/src/pipecat/services/sarvam/tts.py index e92ade2e5..c18933407 100644 --- a/src/pipecat/services/sarvam/tts.py +++ b/src/pipecat/services/sarvam/tts.py @@ -1021,7 +1021,6 @@ class SarvamTTSService(InterruptibleTTSService): self._websocket = await websocket_connect( self._websocket_url, additional_headers=ws_additional_headers, - user_agent_header=None, ) logger.debug("Connected to Sarvam TTS Websocket") await self._send_config()