Added
-
Added
PerplexityAgentHttpLLMServicefor Perplexity's Agent API, which answers with web search and supports function calling. It defaults toopenai/gpt-5.6-lunawith web search on.Settingsaddspreset,web_searchandmax_steps.presetandmodelare independent, and at least one must be set.- With neither
presetnorreasoningset, each request sends Perplexity'sfastpreset, its lowest-latency setup, and the first request for each model logs it. Withuse_provider_thinking_defaultset, no preset is sent. - Answers can include citation markers such as
[1], and Anthropic models needmax_completion_tokensset.
(PR #5985)
-
NvidiaSTTServicenow exposes speaker diarization in transcription frames. Whenspeaker_diarizationis enabled, each contiguous speaker run of a final result is emitted as its own frame with the NVIDIA speaker tag inuser_id. The newspeaker_formatsetting optionally adds speaker labels to the transcript text:settings=NvidiaSTTService.Settings(speaker_diarization=True, speaker_format="Speaker {speaker}: {text}").
(PR #6076) -
Added
NvidiaOmniLLMServicefor NVIDIA Nemotron Omni models, which take speech, images, and video as well as text. In audio input mode (the default, set with theaudio_inputconstructor argument), Omni hears the user directly and replaces the STT service: it transcribes and answers each spoken turn in a single request, and pushes the user's transcript upstream for the context. In this mode it behaves like a realtime service that still needs a TTS. It announces itself as a realtime service, which switches the user aggregator into realtime mode, so read the user's text fromon_user_turn_message_addedrather thanon_user_turn_stopped. Withaudio_input=False, it is a text LLM for a cascaded pipeline. Audio and video files in the context, fromLLMContext.create_file_message()orcreate_audio_message(), are sent in the form Omni reads by the newNvidiaOmniLLMAdapter.run_multimodal_inference()runs a one-off request outside the conversation, for example to describe a video clip, with optional streaming callbacks for text and reasoning. Seeexamples/voice/voice-nvidia-omni.py.
(PR #6085) -
SpeechmaticsSTTServicenow supports 8 kHz audio, alongside 16 kHz. Any other sample rate is reported as a permanent error when the service connects.
(PR #6235) -
Added
emit_sentencestoSpeechmaticsSTTService.Settings. When enabled, Speechmatics closes a segment at every end of sentence, so each sentence is emitted as its own final transcription.
(PR #6235) -
Added
text_transformstoLLMTextProcessor, withadd_text_transformer()andremove_text_transformer(). The same(text_type | "*", transform)pairs a TTS service takes can now rewrite each aggregation before it splits toward the TTS, the context and the client, so a habit the LLM keeps repeating (emoji, stage directions), a name it should not use, or a pattern to redact can be rewritten for everyone. A transform registered on the TTS service still rewrites only what is spoken. A transform that leaves nothing but whitespace drops the aggregation.TextTransforminpipecat.utils.text.transformsnames the callable type.
(PR #6264) -
Added
api_key_sidandapi_key_secrettoTwilioFrameSerializer, so auto hang-up can authenticate with a Twilio API key instead of the account's Auth Token. Credentials must belong to the configured region.
(PR #6270) -
Added
ZoomAISTTService, streaming speech-to-text with Zoom Scribe Live. Install it withpipecat-ai[zoom-ai].pipecat initoffers it as "Zoom AI".- Scribe's voice activity detection ends each turn, so the service recommends
ExternalUserTurnStrategies.Settings.silence_duration_ms(default 350, tuned for voice agents) sets how much silence ends a turn. Settings.diarization(off by default) labels speakers; the labels are inTranscriptionFrame.result.
(PR #6280)
- Scribe's voice activity detection ends each turn, so the service recommends
-
The development runner's Twilio serializer now reads
TWILIO_API_KEYandTWILIO_API_SECRET, so auto hang-up can authenticate with a Twilio API key instead of the Auth Token, andTWILIO_REGIONandTWILIO_EDGE, so it hangs up calls in a non-US1 region such asie1/dublin. SetTWILIO_AUTH_TOKENor the API key pair, not both.
(PR #6293) -
Added
SmallestLLMService, connecting to Smallest AI's Electron model via the OpenAI-compatible Waves API.pipecat initoffers it as "Smallest".
(PR #6339) -
pipecat initnow offers Smallest as an STT service (--stt smallest_stt).
(PR #6339) -
OpenAIResponsesLLMServiceandOpenAIResponsesHttpLLMServicenow log a warning and push a non-fatalErrorFramewhen a response completes with no text and no function call. Nothing reaches the TTS for such a response, so the bot stays silent until the user speaks again; the error lets the application react inon_pipeline_error, for example by running the LLM again. The warning lists the response's output items, such as['reasoning']or['message[refusal]'], and the WebSocket service also logs whether the request sent the full context or only the items added since the previous response.
(PR #6348) -
Added
output_typeto the RTVIbot-outputmessage, the counterpart ofinput_typeonuser-input. It says what kind of text the message holds: a sentence, a word, a backchannel, or a custom type such as"code".
(PR #6351)
Changed
-
pipecat initscaffoldsPerplexityAgentHttpLLMServicefor Perplexity, withopenai/gpt-5.6-lunawhenPERPLEXITY_MODELisn't set.
(PR #5985) -
⚠️
RimeV1TTSServicerequires an explicitsettings.model. Thecodaandmistv3models default towss://coda.api.rime.ai/wsandwss://mist.api.rime.ai/ws. Setwebsocket_urlto override the public endpoint for a custom deployment; URL paths do not select the model.
(PR #6245) -
DeepgramFluxSTTServicenow reports Deepgram's reason when it refuses the connection, so an out-of-range setting or a bad API key is named in the error (for example,Deepgram refused the connection (HTTP 400): eot_threshold must be between 0.5 and 1, inclusive.) rather than a bareserver rejected WebSocket connection: HTTP 400. Theon_connection_errorevent receives the same message.
(PR #6246) -
DeepgramFluxTTSServiceandDeepgramTTSServicenow report Deepgram's reason when it refuses the connection (for example,Deepgram refused the connection (HTTP 400): 'speed' must be within documented range.) rather than a bareserver rejected WebSocket connection: HTTP 400. Theon_connection_errorevent receives the same message.
(PR #6248) -
Changed the default model of
GoogleVertexLLMServicefromgemini-3.6-flashtogemini-3.8-flash, because Vertex AI retiresgemini-3.6-flashon 2026-11-19. The default thinking level for the new model islow; passsettings=GoogleVertexLLMService.Settings(model="gemini-3.6-flash")to keep the previous model until then.
(PR #6259) -
A TTS
text_transformsentry whose output is only whitespace now leaves its text unspoken, instead of sending a lone space to the synthesizer.
(PR #6264) -
Updated the Pillow dependency range to allow Pillow 13.
(PR #6286) -
strip_markdownreduces a Markdown link or image to its label or alt text, so the URL is no longer read out. To keep the syntax as it was, registerStripMarkdown(strip_urls=False)instead, or passstrip_urls=FalsetoVoiceFormatter.
(PR #6295) -
SpeechifyHttpTTSServicenow defaults to thesimba-3.5model, which covers 48 languages under one model id. Setsettings.modelto keep usingsimba-3.2orsimba-3.0.
(PR #6298) -
Raised the
pipecat-ai[cli]Context Hub floor topipecat-ai-context-hub0.9.0, which addspipecat context-hub reposfor adding and removing indexed repos, and lets hub queries wait out a runningrefreshinstead of failing.
(PR #6305) -
LemonSliceTransportnow default to using 24kHz audio for input and output audio. User can set the audio input/output sample rate via theaudio_sample_rateparameter.
(PR #6310) -
LemonSliceTransportnow takes inmodelparameter to specify LemonSlice models. Default model is used if left unspecified.
(PR #6310) -
Widened the
onnxruntimedependency from~=1.24.3to>=1.24.3,<2, so pipecat-ai can be installed next to packages that require a newer onnxruntime.
(PR #6312) -
pipecat.services.openai.realtime.events.parse_server_eventreturnsNonefor a server event type it has no model for, instead of raising, and theResponseandUsagefields are optional, matching the GA Realtime spec.
(PR #6329) -
NvidiaLLMServicenow defaults tonvidia/nemotron-3.5-super-vl-120b-a12b. NVIDIA's NIM cloud endpoint can answer requests for the previous default,nvidia/nemotron-3-super-120b-a12b, with HTTP 404 ("Not found for account") while still listing the model. To keep the previous model, setsettings=NvidiaLLMService.Settings(model="nvidia/nemotron-3-super-120b-a12b").
(PR #6354)
Deprecated
-
PerplexityLLMServiceis deprecated in favor ofPerplexityAgentHttpLLMService. Perplexity has ended support for the Sonar chat completions API it uses.
(PR #5985) -
Deprecated
text_filtersonTTSService, along withBaseTextFilterandMarkdownTextFilter. Usetext_transformsinstead:strip_markdownfrompipecat.utils.text.transformsreplacesMarkdownTextFilter, and a transform registered onLLMTextProcessorrewrites the context as well as the speech. In place offilter_codeandfilter_tables, give the block its own text type withPatternPairAggregatorand list it in the TTS service'sskip_text_types, which keeps it in the context and out of the audio. Will be removed in 2.0.0.
(PR #6264) -
WebsocketService.send_with_retryis deprecated and will be removed in 2.0.0. No replacement: send on the websocket directly and leave reconnecting to the receive loop.
(PR #6300) -
pipecat.adapters.base_llm_adapter,pipecat.adapters.schemas.*andpipecat.adapters.services.*are deprecated. Usepipecat.adapters.llm.base_llm_adapter,pipecat.adapters.llm.schemas.*andpipecat.adapters.llm.services.*instead (for example,from pipecat.adapters.llm.schemas.function_schema import FunctionSchema). The module names are unchanged, and the old paths still work, with a deprecation warning, until 2.0.0.
(PR #6331) -
Workers on a shared bus send tool schemas under their new module path, so a worker on an earlier Pipecat version can't read the tool schemas a worker on this version sends. Upgrade the workers that share a bus together.
(PR #6331) -
Deprecated the
text_typefield of the RTVIbot-outputmessage. Readoutput_typeinstead, which carries the same value. The bot sendsoutput_type,text_typeand the deprecatedaggregated_byuntil 2.0.0.
(PR #6351)
Fixed
-
Fixed
SkipTagsAggregatorandPatternPairAggregator(withMatchAction.KEEP) splitting a sentence at punctuation inside a tag once the tag had closed, andSkipTagsAggregatormissing a tag that started after an earlier sentence was emitted.
(PR #5898) -
Fixed DailyTransport raising an AttributeError for app and prebuilt chat messages sent after a pipeline setup timeout releases its client. App messages sent after cleanup are dropped, and prebuilt chat messages return a not-joined error.
(PR #6191) -
DeepgramFluxSTTServiceretries a connection that opens but never receives Flux'sConnectedmessage, instead of treating it as a rejected request and stopping on the first one. It gives up after three such connections in a row. Unsupported settings are still a permanent error: Flux refuses them with an HTTP 400 during the handshake.
(PR #6219) -
DeepgramFluxSTTServicereconnects in the background, both when its connection drops and when its first connection fails, so audio and other frames keep moving through the pipeline instead of waiting until the reconnect finishes. Audio that arrives while the connection is down isn't transcribed.
(PR #6219) -
When a
DeepgramFluxSTTServiceconnection or aDeepgramFluxSageMakerSTTServicesession ends partway through the user's turn, the turn ends with the transcript received so far, instead of staying open and losing what the user said. IfDeepgramFluxSTTServicereconnects and the user keeps talking, the rest is transcribed as a new turn.
(PR #6219) -
Text filters are reset when an LLM reply ends, so
MarkdownTextFilterwithfilter_code=Trueno longer mutes later replies after one ends inside an open code block.
(PR #6237) -
When a
CartesiaTurnsSTTServiceconnection ends partway through the user's turn, the turn ends with the transcript received so far, instead of staying open and losing what the user said. If the service reconnects and the user keeps talking, the rest is transcribed as a new turn.
(PR #6242) -
CartesiaTurnsSTTServicereports settings Cartesia rejects, such as an unknown model or an out-of-range turn threshold, as a permanent invalid-request error carrying Cartesia's message, instead of waiting 10 seconds for a confirmation that never comes and then retrying. A connection that opens but is never confirmed is retried, and the service gives up after three in a row.
(PR #6242) -
CartesiaTurnsSTTServicereconnects in the background when its connection drops or its first connection fails, so audio and other frames keep moving through the pipeline instead of waiting until the reconnect finishes. Audio that arrives while the connection is down isn't transcribed.
(PR #6242) -
Fixed the MoQ transport silently dropping an outbound audio frame (logged as
Error writing audio frame: unsupported operand type(s) for +=: 'NoneType' and 'float') when an interruption reset the audio pacing clock while a pacedpublish_audiowrite slept. A reset landing mid-sleep now re-anchors the encoder epoch and pacing clock the same way a fresh write does, and a transport teardown landing in the same sleep (the peer leaving while the bot speaks with a full buffer) drops the write quietly instead of erroring on the closed producer.
(PR #6243) -
Fixed
DeepgramFluxTTSServicestaying usable when Deepgram refuses its connection for a setting it won't accept (such as an out-of-rangeexpressivity) or a bad API key. The service retried the same connection on every bot reply, so the bot went silent and a configured failover never took over. Such a refusal now makes the service unusable, as it already did forDeepgramTTSService; a rate limit (429) or a server error (5xx) is still retried.
(PR #6248) -
Fixed websocket-based services stalling when the peer stops reading. A send waited on the full write buffer until TCP gave up, which could take many minutes, holding up the service's processor and every processor after it with no error or reconnect. Each send through
WebsocketServiceis now bounded at 5 seconds; a send that outlasts it drops the connection and fails withConnectionClosedError, so the service's existing reconnect handling takes over. Setws_send_timeoutonWebsocketServiceto change the bound, orNoneto disable it.
(PR #6251) -
FalSTTServicenow closes the HTTP session it creates for itself when the service is cleaned up. Previously the session and its pooled connection tofal.runwere left open after every pipeline run. A session passed in withaiohttp_sessionis still left open for the caller to manage.
(PR #6253) -
Fixed
CartesiaTTSServicewriting a sentence-final punctuation mark to the assistant context twice for Chinese and Japanese (e.g.よろしいでしょうか??). An LLM that sees doubled marks in its earlier replies can copy them, adding more each turn. Cartesia reports these marks as separate word-timestamp tokens; they are now merged into the character before them.
(PR #6261) -
Fixed the MoQ transport treating an audio subscription that closed with code 0 (surfaced as
MOQ transport error: 'moq: no error') as a fatal transport failure that tore down the session mid-call. A code-0 close is graceful by moq convention, so it now follows the normal resubscribe and peer-disconnect paths likecancelledanddroppeddo.
(PR #6262) -
Fixed
text_filtersoutput reaching the assistant context on TTS services without word timestamps. The context now keeps the text as the LLM wrote it on every service, as it already did fortext_transforms.
(PR #6264) -
Fixed
PipelineWorker.flush_pipeline()never draining a pipeline that contains aParallelPipeline(including aServiceSwitcher): it waited until the pipeline went quiet and then returnedFalse. This stalled RTVIsend-textmessages withrun_immediately, which flush the pipeline before adding the user's text. Each of the flush probe's three passes (down, up, down again) is now a newPipelineFlushFramecarrying the same newflush_idfield.
(PR #6268) -
Fixed Cartesia TTS reducing supported regional languages, such as
Language.ES_MX, to their base language.
(PR #6275) -
Fixed
redact_secrets()(and soErrorFrame) raisingRecursionErroron long text made of chainedname:valuepairs such asa:a:a:....
(PR #6282) -
Fixed
redact_secrets()(and soErrorFrame) masking the detail after an exception class name that contains a credential word, such asKeyError: 'audio_content'orInvalidTokenError: signature has expired.
(PR #6283) -
Fixed
bot-outputmissing the last sentence of a speech-to-speech reply when the pipeline uses anLLMTextProcessor(e.g. withOpenAIRealtimeLLMServiceorGeminiLiveLLMService). The bot spoke that sentence, but clients never received it.LLMTextProcessornow flushes the text it holds when it receives aTTSStoppedFrame, so the sentence goes out while the bot is still speaking.
(PR #6290) -
strip_markdownkeeps asterisks that are content (2*3*4,5 * 3,Press * then #,\*), strips list bullets at any indent and spaced horizontal rules (* * *), and drops~~struck~~text instead of speaking the tildes.
(PR #6295) -
Fixed
ElevenLabsTTSServiceword timestamps running early after an alignment message that completes no word, such as trailing punctuation arriving on its own. The words after it, and theTTSTextFrames andbot-tts-textmessages timed by them, now line up with the audio.
(PR #6297) -
PatternPairAggregatorhandles a pattern whose start and end delimiters are the same string, such as a Markdown code fence (```). The text before such a block used to be dropped, and a sentence ending before it could be split inside the delimiter so the block was spoken.
(PR #6299) -
When
InworldTTSServicefails to send a context's create message, it sends it again with the context's text, instead of sending the text to a context the server never opened.
(PR #6300) -
InworldTTSServicenow reconnects only from its receive loop. A send on a dropped connection fails the turn right away, instead of reconnecting inline and retrying a message that the new connection would ignore. A turn that starts while the receive loop is reconnecting reports an error, instead of opening a second connection that nothing reads, which left that turn without audio.
(PR #6300) -
Fixed
MiniMaxHttpTTSServicerejecting thecalmandwhisperemotions passed inInputParams.emotion, which logged "Unsupported emotion" and left the emotion unset. It now accepts every emotion MiniMax documents.
(PR #6302) -
Fixed
DailyTransportstopping all event handling after receiving an inbound DTMF tone A–D. Such tones are now logged and skipped instead of pushed asInputDTMFFrame;on_dtmf_eventhandlers still receive them.
(PR #6321) -
Fixed
OpenAIRealtimeLLMServiceandAzureRealtimeLLMServicestopping server-event processing for the rest of a session after aresponse.donewithoutusageorstatus_details, or a server event type they have no model for.
(PR #6329) -
Fixed
DailyTransportdropping every later Daily event, or incoming audio or video, after a single callback raised an exception. The exception is now logged and processing continues.
(PR #6341) -
SarvamRealtimeSTTServicereports settings Sarvam rejects, such as an unknown model or language, as a permanent invalid-request error carrying Sarvam's reason, instead of retrying the connection.
(PR #6342) -
SarvamRealtimeSTTServicefireson_connectedonce Sarvam confirms the session withsession.begin, not as soon as the socket opens. A connection that opens but is never confirmed is retried, and the service gives up after three in a row.
(PR #6342) -
When a
SarvamRealtimeSTTServiceconnection ends partway through the user's speech, the utterance ends with the latest partial transcript, instead of losing what the user said. If the service reconnects and the user keeps talking, the rest is transcribed as a new utterance.
(PR #6342) -
Fixed a
pipecat evalscenario stalling until its timeout when a vision bot asked for the user's image before any turn had registered one withimage:(e.g. a bot that looks at the user while greeting them). The eval transport now answers the request with an error, as the Daily, LiveKit and SmallWebRTC transports do when there's no video, so the bot's function call finishes and the conversation goes on.
(PR #6350)
Security
-
Fixed
redact_secrets()(and soErrorFrame) leaving a credential unmasked when its pair follows another pair, as inUnknown error occurred: api_key: abc123,ValueError: Authorization: Bearer abc123orerror: headers=Authorization: Bearer abc123. A prefix on an error message no longer changes what it masks.
(PR #6308) -
Raised the
aiohttpminimum version to3.14.4, the first release with fixes for several aiohttp security advisories. Installs that resolvepipecat-aifrom PyPI no longer pick up an earlier, vulnerableaiohttp.
(PR #6325)