Configuration
ThePatter class is the main entry point for the SDK. Pass a carrier instance and a phone number — everything else flows through environment variables unless you override it.
Minimal config
Constructor parameters
Environment variables
Every credential resolves from an env var when the matching argument is omitted. See.env.example in the repo for a complete list.
Runtime env vars
These tune SDK runtime behaviour (no credential lookup).PATTER_BIND_HOST defaults to loopback on purpose — exposing the embedded server on 0.0.0.0 outside a containerised deployment puts the dashboard and webhook routes on every interface. Pair PATTER_BIND_HOST=0.0.0.0 with the dashboard_token argument on serve() (or skip the dashboard) before going public.PATTER_DASHBOARD_NOTIFY only gates the standalone-dashboard ingest webhook. It does not disable the embedded dashboard you can serve from phone.serve(..., dashboard=True) — that route runs in-process and is unaffected.Examples
OpenAI Realtime on Twilio
OpenAI Realtime on Telnyx
Pipeline mode
Validation
Local mode enforces the following when telephony credentials are present:phone_numberis required- Both
account_sidandauth_tokenare required when using Twilio (either viaTwilio(...)kwargs orTWILIO_*env vars)
Persistent dashboard history
By default the dashboard is an in-memory ring buffer — restart the process and the call list is empty. Passpersist= to keep per-call records (metadata.json, transcript.jsonl, events.jsonl) on disk and rebuild the dashboard on the next startup. No external database required.
When
persist is set explicitly the env var is ignored. When persist is None, PATTER_LOG_DIR continues to work as a deployment-time override.
Platform default location
Simplest opt-in
Custom path
Env-var override (deployment-time)
Leavepersist unset in code and let ops decide per environment:
Programmatic hydration on startup
phone.serve() calls MetricsStore.hydrate(log_root) automatically when persistence is enabled, so the dashboard repopulates from disk before the first call lands. You can call it directly if you build the store yourself:
hydrate() is idempotent — call_ids already in the store are skipped, and unparseable records are logged at debug level rather than aborting.

