Releases: PatterAI/Patter
v0.6.2 — GA Realtime adapter + 14-bug fix wave + dashboard hardening
Bundled fix wave validated live via PSTN against the inbound and outbound OpenAI Realtime paths. New OpenAIRealtime2 engine + adapter (Python parity with TS) speaks the GA Realtime API (gpt-realtime-2), with bidirectional mulaw 8 kHz ↔ PCM 24 kHz transcoding for Twilio / Telnyx.
Highlights
- New
OpenAIRealtime2engine +OpenAIRealtime2Adapter(Python parity with TS) — speaks the GAsession.updateshape (session.type = "realtime", nestedaudio.{input,output},output_modalities), with bidirectional mulaw ↔ PCM 24 kHz transcoding. - Inbound caller/callee via TwiML
<Parameter>— Twilio strips URL query params before the WS handshake, so caller/callee now travel as<Parameter>children of<Stream>. Inbound calls in the dashboard now show the correct numbers. - Whisper hallucination filter on the Realtime
transcript_inputevent — drops "Thank you for watching.", "[music]", and 13 other YouTube-caption fallbacks that Whisper emits on silence/echo, eliminating phantom user turns. - Deferred
response.createwith newrequest_response()method —turn_detection.create_response: false+interrupt_response: falseso Patter drives the assistant turn ONLY after the hallucination filter accepts the user transcript. - VAD threshold raised 0.1 → 0.5 on the GA Realtime path — kills the phantom barge-in loop where carrier-loopback echo of the agent's own audio tripped server VAD.
Persistence + dashboard
persistdefault flipped OFF → ON in both SDKs. Calls now survive process restarts by default (path:~/Library/Application Support/patteron macOS / XDG dir on Linux /%LOCALAPPDATA%on Windows). Migration: passpersist=Falsefor the old ephemeral-RAM-only behaviour.PATTER_LOG_REDACT_PHONEdefault flippedmask→fullso the dashboard UI reveal toggle works (you can't unmask numbers the SDK never knew). Migration: setPATTER_LOG_REDACT_PHONE=maskfor setups that ship logs off-host.directionnow persisted inmetadata.json— fixes outbound calls rendering as inbound (and top-bar showing the callee instead of the Patter number) after restart.aggregates.sdk_versionfield — SPA top-bar version chip now auto-derives fromgetpatter.__version__/package.json#version.- Python
hydrate()now backfillstranscriptfrom siblingtranscript.jsonlwhenmetadata.jsonhas no array (TS already did). record_call_endpreserves the liveturnsarray + falls back to active/existing transcript when the SDK end-of-call snapshot is empty.- Standalone dashboard (
patter dashboard) now sees outbound dials in real time vianotify_dashboardrelay ofcall_initiated.
Prewarm + adoption hardening
- Liveness check rewritten to handle the current
websocketslibrary (stateenum +close_codechecks; legacyclosedfallback). Pre-fixgetattr(ws, "closed", True)defaulted to "dead" on the new client and silently aborted every adoption. - Application-level keepalive on the parked GA Realtime WS (
session.updateevery 3 s + WS PING every 4 s) — OpenAI's GA edge closes idle sockets within ~6-7 s. cancel_responseis now a no-op when no item is in flight — eliminatesresponse_cancel_not_activeERROR spam on every phantom VADspeech_started.firstMessageno longer truncated by loopback echo VAD — barge-in gate consults_current_response_first_audio_aton the adapter.
TS surface additions
- Top-level re-exports of
OpenAIRealtimeModel,OpenAITranscriptionModel,OpenAIRealtimeAudioFormat,OpenAIVoice,ElevenLabsModel,ElevenLabsOutputFormat,DeepgramModel,CartesiaTTSModel,RimeModel,PricingUnit,PRICING_VERSION, etc. —import { OpenAIRealtimeModel } from "getpatter"now works. engines/openai.tsRealtime.modeldefault flippedgpt-4o-mini-realtime-preview→gpt-realtime-minifor parity with Python.
Docs
31 Mintlify pages updated + 2 new pages (docs/python-sdk/providers/openai-realtime-2.mdx, docs/typescript-sdk/providers/openai-realtime-2.mdx).
Breaking changes
Both flips are opt-out with safe defaults; no API removals or renames.
persist=None→ defaults to ON (persist=Falseto opt out).PATTER_LOG_REDACT_PHONE→ defaults tofull(maskto opt back).
PR
#104 — release/0.6.2 → main (squash-merged)
0.6.1 — pipeline robustness + new providers + dashboard SPA
See PR #102 for the full changelog.
Highlights
- New providers:
OpenAIRealtime2(TS, GAgpt-realtime-2),InworldTTS,SpeechmaticsSTT(TS parity) - Pipeline: one-shot barge-in fix, first-message pacing, EOU/metrics alignment
- Dashboard: rewritten as Vite+React SPA, multi-select delete, dark-mode polish
- ElevenLabs TTS default flipped to WebSocket (TTFB ~265 ms → ~80-100 ms)
- Model-aware pricing across STT/TTS/Realtime
- Observability: OTel spans on Python, no-op stubs on TS
Install
- Python:
pip install getpatter==0.6.1 - TypeScript:
npm install getpatter@0.6.1
Known limitations
OpenAIRealtime2over Twilio: outbound audio works via Patter-side transcoding but GAserver_vadis studio-tuned, so pipeline mode (STT+LLM+TTS) is the recommended production path for Twilio in 0.6.1 until OpenAI ships native g711_ulaw on GA.- Python parity for
OpenAIRealtime2is a follow-up — TS-only in 0.6.1.
0.6.0 — Refactor wave + Phase 3+4 SDK fixes + Mintlify docs parity
Major SDK release validated by 9 rounds of agent-to-agent acceptance testing (Phase 3 R1–R4 + Phase 4 R1–R5). Six real SDK bugs found and fixed. PR: #83.
Highlights
Fixed
- OpenAI Realtime barge-in correctness:
cancel_responsenow capsaudio_end_msby wall-clock elapsed (was byte-counter), eliminating post-barge-in re-greeting and mid-sentence resume. Py + TS parity. - Pipeline mode
on_transcriptfires for assistant turns + tool calls: previously emitted only by Realtime mode. AddsLLMLoop.on_tool_callobserver +_emit_assistant_transcripthelper. Py + TS parity. - AssemblyAI STT (Python): coalesce 20 ms Twilio frames to 60 ms target (above v3 50 ms minimum). Closes parity with TS adapter; new
flush_audio()drains tail. getpatter.tts.elevenlabs.TTSfacade now forwardslanguage_code/voice_settings/chunk_size(the facade had a narrower signature than the underlying provider — multilingual scenarios crashed). Py + TS parity.- Cerebras + Groq LLM pricing — silent under-billing fix:
gpt-oss-120b(Cerebras default since 0.5.4) and 5 Groq models all billed $0. Now per-1M-token rates for every enum value. Py + TS parity. - Pricing tables now model-aware across STT, TTS, and Realtime: was provider-only, so Deepgram nova-3 multilingual users were billed at nova-3 monolingual rate, gpt-realtime-2 users at gpt-realtime-mini rate (4× under-charge on audio out). New
_resolve_provider_rateshelper with longest-prefix fallback. Built-in rates for Deepgram, Whisper/Transcribe, ElevenLabs, OpenAI TTS, Cartesia, Rime, LMNT, Inworld, OpenAI Realtime. PRICING_VERSION 2026.2 → 2026.3. Py + TS parity. - OpenAI Realtime engine wrapper now forwards
reasoning_effortandinput_audio_transcription_model(were silently dropped by the high-level wrapper). Py + TS parity.
Changed
CircuitBreakerOptions.cooldown_s→cooldown_ms(Python aligned to TScooldownMs). Backward-compat shim emitsDeprecationWarning. Scheduled removal in v0.7.0.
Added
- TypeScript
manageWebhookopt-out forserve()— closes a hidden footgun for users running behind a router/gateway (Terraform / edge function) whose Twiliovoice_urlis managed externally. Defaulttruepreserves existing behaviour. - TypeScript SDK now ships
SpeechmaticsSTT(closes long-standing Python-only gap). RT v2 WebSocket protocol direct viaws. 21-test mocked suite. - OpenAI Realtime
gpt-realtime-2andgpt-realtime-whispermodel IDs with model-aware billing. - Python parity for
ConversationStateSnapshot,UserState,AgentState,EouTriggertypes (catches up to TypeScript). - MCP server integration — both SDKs expose
mcp_serversconfig + dedicated docs page. - Inworld TTS provider (TTS-2 default, NDJSON streaming).
Repo restructure
sdk-py/→libraries/python/sdk-ts/→libraries/typescript/- 33 new Mintlify provider reference pages (full Py↔TS parity across 22 providers)
Validation
- 9-round agent-to-agent acceptance matrix (Phase 3 + Phase 4)
- Python: 1707 tests pass, 7 skipped
- TypeScript: 1381 tests pass (78 files)
- All 13 CI blocking checks green on PR #83
Install
```sh
pip install --upgrade getpatter==0.6.0
npm install getpatter@0.6.0
```
Full changelog: CHANGELOG.md
0.5.4 — Cerebras default to gpt-oss-120b
Hotfix: restores gpt-oss-120b as the default Cerebras model.
Install
```bash
pip install getpatter==0.5.4
npm install getpatter@0.5.4
```
What changed
The 0.5.3 merge inadvertently kept llama3.1-8b as the Cerebras default — a regression of an earlier project decision. Bumping back to gpt-oss-120b for both Python and TypeScript SDKs.
Why gpt-oss-120b is the right default
- Throughput on Cerebras WSE-3: ~3000 tok/sec, the highest in the catalog.
- TTS-bottlenecked: voice agents consume LLM output at ~150-300 tok/sec via TTS. Both 8B and 120B models saturate the downstream pipeline, so model size doesn't add realtime latency.
- No deprecation: while
llama3.1-8bretires 2026-05-27 and the preview models (qwen-3-235b-a22b-instruct-2507,zai-glm-4.7) carry no SLA. - Quality: 120B parameters give materially better answer quality at no realtime cost.
Override
Other models remain reachable via model=:
```python
from getpatter import CerebrasLLM
agent = CerebrasLLM(model="llama3.1-8b") # smaller, free-tier
agent = CerebrasLLM(model="qwen-3-235b-a22b-instruct-2507") # preview
```
If your tier returns 404 for gpt-oss-120b, the provider's stream() logs a recovery hint listing override candidates.
Compatibility
- Drop-in replacement for 0.5.3.
- Python ≥ 3.11, Node ≥ 18.
Full changelog
See the v0.5.3 release notes for the full 0.5.x feature set; 0.5.4 is a single-line default-model change on top.
0.5.3 — latency pass + observability + parity
First polishing release of the public SDK. Cost-accuracy, audio-pipeline, and observability hardening across both SDKs, plus opt-in per-call filesystem logging, telephony optimizations, and provider tunings.
Install
```bash
pip install getpatter==0.5.3
npm install getpatter@0.5.3
```
Highlights
Latency
End-to-end P50 (user-stop → first TTS audio byte) reduced by ~1000-2000 ms:
- STT: Python
speech_finalparity with TypeScript (Deepgram fast endpointing, ~300-700 ms saved per turn). Defaultsmart_format=Falsefor telephony. Whisper / OpenAITranscribeSTT always flush on close. - LLM: Anthropic prompt caching enabled by default (
cache_control: ephemeralon system + last tool block). Cerebras hardening: retry + structured outputs + sampling kwargs forwarding. Newbefore_llm/after_llmpipeline hooks for PII redaction, output validation, prompt rewriting. - TTS: Cartesia bumped to
sonic-3(~90 ms TTFB). OpenAI TTS chunk size 4096 → 1024. Sentence chunker emits short greetings immediately. New telephony factories (for_twilio()/for_telnyx()) on ElevenLabs, Cartesia, and ConvAI that negotiate carrier-native codecs (ulaw_8000/ 8 kHz PCM) and skip per-chunk SDK transcoding. - Realtime: OpenAI Realtime
silence_duration_ms500 → 300. - Telephony: Telnyx
answer+streaming_startconsolidated into a single API call (saves one webhook round-trip). TS Twilio outbound switched fromUrl:to inlineTwiml:(parity with Python adapter, saves another round-trip).stream_trackset toinbound_track(halves WS upstream bandwidth). Defaultring_timeoutlowered from 60 s to 25 s. - Infrastructure:
notify_dashboardmade async + fire-and-forget (avoids 1-3 s stall when dashboard is offline). TScall-logswitched tofs.promisesto keep ~75 ms of cumulative blocking off the Node main thread.
Providers
- New first-class
OpenAITranscribeSTTforgpt-4o-transcribe/gpt-4o-mini-transcribe. - Typed ElevenLabs model literal —
eleven_v3/eleven_flash_v2_5/eleven_turbo_v2_5/eleven_multilingual_v2/eleven_monolingual_v1. - Cerebras:
response_format(JSON mode + structured outputs),parallel_tool_calls,tool_choice,seed,top_p,frequency_penalty,presence_penalty,stop,User-Agenttelemetry,max_completion_tokens, gzip compression on by default in TypeScript (parity with Python). - Same OpenAI-spec sampling kwargs lifted to the
OpenAILLMProviderparent so every OpenAI-compat client benefits.
Observability
LatencyBreakdownextended withendpoint_ms,bargein_ms,tts_total_ms, properly splitllm_ttft_ms/llm_total_ms.- New aggregate:
latency_p90alongside P50 / P95 / P99. - New OTel spans
getpatter.endpointandgetpatter.bargein. The pre-existinggetpatter.llmspan is now actually emitted around the pipeline LLM call. - New
EventBusevent types:transcript_partial,transcript_final,llm_chunk,tts_chunk,tool_call_started. - TS span names normalised to
getpatter.*everywhere.
Compatibility
- Python ≥ 3.11.
- Node ≥ 18.
- No public-API breaks. Anything that was deprecated in 0.5.x continues to work; the new factories (
for_twilio()/for_telnyx()) are opt-in.
Full changelog
See CHANGELOG.md and PR #76.
v0.5.2
Fixed
- ElevenLabs default voice: Rachel → Sarah — Rachel (
21m00Tcm4TlvDq8ikWAM) is a library voice that free-tier ElevenLabs accounts cannot use via the API, sonew ElevenLabsTTS()/ElevenLabsTTS()without an explicitvoice_idused to fail on the first synthesis with402 paid_plan_required. The default is now Sarah (EXAVITQu4vr4xnSDxMaL), a premade voice available to every account. alloyalias now resolves to Sarah for the same reason.rachelalias still resolves to her original ID — passvoice="rachel"explicitly to keep using her (requires a paid ElevenLabs plan).- Added
sarahalias alongside the existingbella(same voice ID).
Changed (UX)
- Startup banner now renders at the top of the terminal output (before tunnel / webhook setup logs), with a visually distinct Dashboard section using box-drawing separators.
- Reduced per-frame log noise during calls: removed
WS event:,Telnyx event:,Upgrade request:,WebSocket connected:lines. OnlyCall started/Call endedremain on the happy path.
Install
pip install --upgrade getpatter==0.5.2
npm install getpatter@0.5.2Full changelog: v0.5.1...v0.5.2
v0.5.1 — First-class llm= selector + 5 LLM providers
Patter 0.5.1 adds llm= as a first-class selector on phone.agent(), mirroring the stt= / tts= / engine= pattern shipped in 0.5.0. Five LLM provider classes with env-var fallback ship in both SDKs:
from getpatter import Patter, Twilio, DeepgramSTT, AnthropicLLM, ElevenLabsTTS
phone = Patter(carrier=Twilio(), phone_number="+15550001234")
agent = phone.agent(
stt=DeepgramSTT(), # DEEPGRAM_API_KEY
llm=AnthropicLLM(), # ANTHROPIC_API_KEY
tts=ElevenLabsTTS(voice_id="rachel"), # ELEVENLABS_API_KEY
system_prompt="You are helpful.",
)
await phone.serve(agent)TypeScript mirror uses new AnthropicLLM().
What's new
OpenAILLM,AnthropicLLM,GroqLLM,CerebrasLLM,GoogleLLM— namespaced classes (getpatter.llm.{vendor}.LLMin Python,getpatter/llm/{vendor}in TS) plus flat aliases from the package root.- Env-var fallback per provider —
OPENAI_API_KEY,ANTHROPIC_API_KEY,GROQ_API_KEY,CEREBRAS_API_KEY,GEMINI_API_KEY(falls back toGOOGLE_API_KEY). - Tool calling works across all 5 providers — each adapter normalizes vendor-specific tool formats to Patter's unified chunk protocol.
llm=andon_messageare mutually exclusive — conflict raises a clear error atserve()time;engine + llmlogs a one-time warning (engine owns the LLM).- Clean logging — two INFO lines per call (start + end):
Call started: CAxxx (Twilio, engine=openai_realtime, +15550001 → +15550002)Call ended: CAxxx (42.3s, 8 turns, cost=\$0.0127, p95=612ms)- Everything else (STT transcripts, barge-in, hallucination filter, DTMF, per-turn guardrail triggers) demoted to
debug.
Fixes
- TypeScript bundler (critical) —
tsupwas bundlingcloudflaredinto the ESM dist, and sincecloudflaredis CJS and callsrequire("path")at runtime,serve({ tunnel: true })crashed withDynamic require of "path" is not supported. Fixed by externalizingcloudflaredand@ngrok/ngrokin a newtsup.config.tsso they resolve from the consumer'snode_modules/at runtime. - CI —
anthropic/google-genaioptional-extras tests now skip gracefully on the base Python matrix (they still run end-to-end in thepython-all-extrasjob). - Parity —
provider="pipeline"is now derived in the TypeScript client when the user passes onlyllm=without an engine, matching the Python client.
Install
pip install getpatter # 0.5.1
pip install "getpatter[anthropic]" # + Anthropic adapter
pip install "getpatter[google]" # + Google Gemini
pip install "getpatter[tunnel]" # + cloudflared for dev tunnels
npm install getpatter # 0.5.1
npm install cloudflared # optional, only if using tunnel: trueValidation
- Python: 1350 pytest passed, 8 skipped, 0 failures (1327 baseline + 23 new in
tests/unit/test_llm_api.py) - TypeScript: 1042 vitest passed across 61 files,
tsc --noEmitclean (1013 baseline + 29 new intests/unit/llm-api.test.ts) - 4-line pipeline-mode quickstart with
llm=AnthropicLLM()verified in both SDKs
Unchanged
- Default OpenAI LLMLoop still auto-constructs when
llm=is absent andopenai_keyis present — zero break from 0.5.0. on_messagecallback still works for custom LLM logic (multi-model routing, localllama.cpp, etc.). Mutually exclusive withllm=.
Links
- PR: #69
- Docs: https://docs.getpatter.com
v0.5.0 — Instance-based API refactor
Patter 0.5.0 ships a clean, instance-based public API for both the Python and TypeScript SDKs. The Python module is renamed from patter to getpatter so the install name and import name now match across languages: pip install getpatter / from getpatter import ..., npm install getpatter / import { ... } from "getpatter".
The headline quickstart is four lines:
from getpatter import Patter, Twilio, OpenAIRealtime
phone = Patter(carrier=Twilio(), phone_number="+15550001234")
agent = phone.agent(engine=OpenAIRealtime(), system_prompt="You are a receptionist.")
await phone.serve(agent, tunnel=True)TypeScript mirror:
import { Patter, Twilio, OpenAIRealtime } from "getpatter";
const phone = new Patter({ carrier: new Twilio(), phoneNumber: "+15550001234" });
const agent = phone.agent({ engine: new OpenAIRealtime(), systemPrompt: "You are a receptionist." });
await phone.serve({ agent, tunnel: true });Set TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, OPENAI_API_KEY in your env and these four lines answer real phone calls.
What's new
- Carriers —
patter.carriers.{twilio,telnyx}with flatTwilio/Telnyxaliases; env fallback onTWILIO_ACCOUNT_SID/TELNYX_API_KEYetc. - Engines —
patter.engines.{openai,elevenlabs}with flatOpenAIRealtime/ElevenLabsConvAI; env fallback onOPENAI_API_KEY/ELEVENLABS_API_KEY+ELEVENLABS_AGENT_ID. - STT —
DeepgramSTT,WhisperSTT,CartesiaSTT,SonioxSTT,SpeechmaticsSTT(Python-only),AssemblyAISTT. Each reads<VENDOR>_API_KEYwhen omitted. - TTS —
ElevenLabsTTS,OpenAITTS,CartesiaTTS,RimeTTS,LMNTTTS. Same env-fallback pattern. - Tunnels —
CloudflareTunnel(),Static(hostname=...),Ngrok(hostname=...)instances;serve(tunnel=True)kept as the dev alias. - Tools + Guardrails —
Tool/Guardrailclasses withtool()/guardrail()factories. - Twilio/Telnyx webhook auto-config —
serve()now sets the Twiliovoice_urland associates Telnyx numbers automatically on both SDKs (TS reached parity with Python this release). - Docs rewrite — new
Core Conceptspage explains the five building blocks from scratch;Setting up Patternav group with one page per component;engines.mdx+tracing.mdx(OpenTelemetry) added.
What's removed
- Legacy
Patter(twilio_sid=, twilio_token=, openai_key=, deepgram_key=, ...)kwargs. - Legacy string selectors (
stt="deepgram",tts="elevenlabs",provider="openai_realtime"). - Factory methods
Patter.deepgram(),Patter.whisper(),Patter.elevenlabs(),Patter.openai_tts(),Patter.cartesia(),Patter.rime(),Patter.lmnt(),Patter.guardrail(),Patter.tool(). - Dict-form tool / guardrail definitions (typed instances only).
- MCP Server dev-tools page (out of scope for now).
- ~294 lines of deprecation shim from
sdk-py/patter/client.py; ~251 lines of shim +provider-resolver.tsfrom the TS client.
Install
# Python
pip install getpatter # or pip install "getpatter[tunnel]" for built-in Cloudflare tunnel
# TypeScript
npm install getpatter
npm install cloudflared # if you want phone.serve(tunnel: true)Validation
- Python: 1327 pytest passing, 8 skipped, 0 failures.
- TypeScript: 1013 vitest passing across 60 files;
tsc --noEmitclean. - Both 4-line quickstarts smoke-tested under
-W error::DeprecationWarning(Python) and viatsx(TypeScript).
Line-count delta vs 0.4.4
247 files changed, 4,810 insertions, 9,766 deletions — net −4,956 lines.
Links
- Pull request: #68
- Docs: https://docs.getpatter.com
v0.4.4 — 23 bug fixes + SDK parity + live validation
Patter SDK 0.4.4
Bug-fix sweep + parity release. 23 distinct bugs discovered during the
acceptance suite are now fixed; Python ↔ TypeScript SDKs realigned; 5 new
live-call scenarios validated end-to-end against real Twilio and Telnyx
numbers.
pip install -U getpatter # Python
npm install getpatter@0.4.4 # TypeScriptHighlights
- Telephony stack is now fully reliable on both Twilio and Telnyx —
fixes land across the webhook layer (Requestforward-ref, deps),
Telnyx Call Control (answer flow, WS shape, wire format, track
filtering), and Twilio audio (sample-rate, pass-through sender). - Pipeline mode (STT + LLM + TTS) is barge-in-capable and filters
STT hallucinations (you,.,thank you) so the caller never hears
overlapping turns from a Whisper / Deepgram mis-commit. - Dashboard surfaces every outbound call attempt (including
no-answer / busy / failed) via the new/webhooks/twilio/status
endpoint and astatuscolumn in the UI. - Python ↔ TypeScript parity re-verified by the
sdk-parityagent.
Fixes
Telephony
#08Twilio webhooks returned 422 on every call —Requestimport
lifted to module top.#09Pinnedwebsockets>=14,<16to avoid theadditional_headers
crash on 13.x.#10OpenAI Realtime → Twilio used the wrong sample rate. Realtime
now runs ong711_ulawand the audio sender is pass-through on mulaw.#16Telnyx Call Control rang forever —/webhooks/telnyx/voicenow
POSTsactions/answer+actions/streaming_start.#17Telnyx WebSocket media events were silently dropped because
the bridge matched the wrong event names. Now matches
data.event == "media"withmedia.payloadbase64 frames.#18Telnyx outbound audio was rejected for wire-format mismatch.
The sender now emits{event:"media", media:{payload:b64}}and
streaming_startnegotiatesg711_ulaw.#19Telnyxstream_track=both_tracksfed the agent's own TTS back
into its STT. The bridge now filtersmedia.track != "inbound"and
only forwards the caller leg.
Pipeline
#12Twilio pipeline double-transcoded audio → 0 transcripts. The
pipeline STT now always runs onlinear16@16k; mulaw decode lives in
on_audio_received.#13Deepgram endpointing was hard-coded.endpointing_msand
utterance_end_msare now tunable (defaults 150 ms / 1000 ms).#15PipelineHooks.before_send_to_sttwas declared but never
invoked — the pipeline now runs the hook and honoursNone/raise
semantics (drop chunk / fail-open).#20Barge-in was broken:on_audio_receivedskipped STT during
TTS. The pipeline now forwards caller audio to STT during TTS, and
any transcript-with-text while_is_speaking=Trueclears the
telephony buffer and stops the active sentence loop.#22Whisper on mulaw 8 kHz hallucinated short fillers and
back-to-back finals triggered overlapping LLM+TTS turns. The STT
loop now drops:- known hallucination fillers (
you,.,thank you,yeah, …) - finals that duplicate the previous committed text inside 2 s
- finals that land within 500 ms of the previous turn
- known hallucination fillers (
#23OpenAI TTS 24 kHz → 16 kHz streaming resample lost samples
across chunks. Now usesaudioop.ratecvwith persistent state and a
carry-byte buffer.
API / ergonomics
#01Scheduler extra is documented (pip install getpatter[scheduling]).#02PythonFallbackLLMProvider.complete_streamnow matches the TS
surface.#03Scheduler works across event loops (per-loop registry instead
of a process-global singleton).#04Python ↔ TS parity gaps closed: auto-detect local mode,
Patter.deepgram()/Patter.elevenlabs()/Patter.cartesia()/
Patter.rime()/Patter.lmnt()factories on both sides.#05FallbackLLMProvider.aclose()+ async context manager
support — background probe timers are drained on shutdown.#11Patter.elevenlabs(voice="rachel")resolved to a 404 — the
SDK now maps ~45 common ElevenLabs voice names to their UUIDs.#14Patter.agent()was silently droppinghooks,
text_transforms,vad,audio_filter,background_audio,
barge_in_threshold_ms. All forward to theAgentnow.#21@tool-decorated functions crashed on invocation because the
executor always calledhandler(args, ctx)but typed user functions
take keyword args. The decorator now wraps the function in an async
adapter that unpacksargumentsas kwargs.
Dashboard
#06The dashboard now registers the call as soon asPatter.call()
fires (before any webhook), and tracks status transitions
(initiated → ringing → in-progress → completed | no-answer | busy | failed | canceled) via the new/webhooks/twilio/statusendpoint.
UI adds a status column, filter pills, and SSEcall_initiated/
call_statusevents.
New
Patter.call(..., ring_timeout=60)kwarg — maps to TwilioTimeout
and Telnyxtimeout_secs.Agent.barge_in_threshold_ms— disable barge-in (value0) or tune
the hang-over window.vad_eventsonPatter.deepgram()/patter.providers.deepgram().- Top-level
patter.mix_pcmhelper (Python parity with TS). - Static TTS factories on the Python
Patterclass:cartesia,
rime,lmnt(match TS). - GitHub Actions
audit.ymlworkflow:pip-audit+npm audit+
banditwith SARIF upload on schedule + PR diff. - README "Provider Notes" section documenting ElevenLabs free-tier
voice restriction, Telnyx Outbound Profile requirement, Gemini free
tier quota, and Whisper hallucination filtering.
Test coverage
Full offline suite now runs 749 Python unit tests + 932 TypeScript
tests (soak included). Every bug listed above has a regression test:
| File | Bug | Tests |
|---|---|---|
sdk-py/tests/unit/test_pipeline_dedup.py |
#22 | 13 |
sdk-py/tests/unit/test_openai_tts_resample.py |
#23 | 7 |
sdk-py/tests/unit/test_twilio_status_and_ring_timeout.py |
#6 + ring_timeout | 13 |
sdk-py/tests/unit/test_pipeline_bargein.py |
#20 | 7 |
sdk-py/tests/unit/test_before_send_to_stt_hook.py |
#15 | 9 |
sdk-py/tests/unit/test_telnyx_track_filter.py |
#19 | 5 |
Live-call validation on real Twilio + Telnyx numbers, all PASSED:
transfer_callauto-injected toolserve(recording=True)- Telnyx DTMF (
call.dtmf.received) - WebSocket drop mid-call +
EmbeddedServer.stop()cleanup - Full Italian pipeline (Deepgram
language="it"+ ElevenLabs IT voice)
Breaking changes
None. Every change preserves the existing public API — only additions.
Upgrade notes
- If you pinned
websocketsto 13.x in your own environment, bump to
>=14,<16to avoid theadditional_headerscrash. - Calls placed with
machine_detection=Truenow requirevoicemail_message
to drop a message (previously silently produced empty audio). - If you were using conftest monkey-patches to work around #7/#8/#10/
#12/#13/#16/#17/#18 — they can be removed.
Provider caveats (read before production)
- ElevenLabs free tier: cannot hit the library voice catalog via API
(402 Payment Required). SetELEVENLABS_VOICE_IDto a voice you
own (cloned or generated) beforephone.serve(). - Telnyx outbound: connections must have an "Outbound Profile"
attached in the portal or outbound calls return403 D38. - Google Gemini free tier:
gemini-2.0-flashhas a hardquota=0.
Enable billing before using Gemini as the LLM. - Whisper on mulaw 8 kHz: hallucinates short fillers. The pipeline
drops them automatically — no action needed.
Full changelog: v0.4.3...v0.4.4
Acceptance suite: https://github.com/PatterAI/patter-sdk-acceptance
v0.4.3
Patter v0.4.3 — self-contained install.
Packaging
pip install getpatteralone is now enough to run the SDK end-to-end. The runtime dependencies previously kept behind the[local]extra —fastapi,uvicorn[standard],twilio,audioop-lts(Python 3.13+),openai, andcryptography— are now part of the basedependenciesinsdk-py/pyproject.toml.- The
[local]extra is preserved as an empty alias, so existing guides, scripts, and templates that callpip install getpatter[local]continue to work unchanged. - The TypeScript package already shipped
expressandwsas runtime dependencies, so no structural change was needed on the npm side beyond the version bump.
Docs
- Dropped the now-redundant
[local]marker from the dashboard install snippet indocs/dev-tools/dashboard.mdx.
Install
pip install getpatter==0.4.3
npm install getpatter@0.4.3Full changelog: v0.4.2...v0.4.3