Metrics & Cost Tracking
Patter automatically tracks cost and latency for every call, broken down by provider component (STT, TTS, LLM, telephony).How It Works
Metrics are collected automatically during calls. When a call ends, theonCallEnd callback receives a CallMetrics object with the full breakdown:
Cost Breakdown
TheCostBreakdown object provides per-component costs in USD:
Latency Breakdown
TheLatencyBreakdown object provides per-component latency in milliseconds:
CallMetrics exposes the full distribution: latency_avg, latency_p50 (median / typical UX), latency_p90 (steady-state outliers), latency_p95 (SLA), and latency_p99 (cold-start outliers).
Per-Turn Metrics
Each conversation turn is tracked individually:Custom Pricing
Override default provider pricing estimates:PricingUnit
The pricing tables expose aPricingUnit constant so overrides don’t depend on raw strings:
const object plus value-union type so it is tree-shakeable. Mirrored byte-for-byte by the Python PricingUnit StrEnum.
Model-Aware Pricing
Patter’s pricing tables are model-aware: every entry inDEFAULT_PRICING carries provider-level defaults plus an optional models map keyed by model identifier. When the agent’s adapter exposes a model field, the metrics layer threads it through the cost-calc functions and the dashboard bills with model accuracy out of the box — no manual override required.
How resolution works
The cost-calc helpers (calculateSttCost, calculateTtsCost, calculateRealtimeCost, calculateRealtimeCachedSavings) accept an optional final model parameter. The exported resolveProviderRates(config, model) helper merges per-model overrides on top of provider defaults using:
- Exact match in the provider’s
modelsmap. - Longest-prefix match —
gpt-realtime-2-2026-05-08resolves againstgpt-realtime-2. - Provider defaults — fallback when the model is unknown or omitted.
CallMetricsAccumulator auto-tracks sttModel, ttsModel, and realtimeModel from the agent’s adapter model field (agent.stt.model, agent.tts.model, agent.model for Realtime). On every recordRealtimeUsage(usage) call the realtime model is also pulled from the response.done payload itself, overriding the call-level default — so mid-call model switches are billed correctly.
The optional
model argument defaults to undefined, which preserves the legacy provider-rate behaviour. Existing callers compile and run unchanged.Example A — Just select a model
The most common case: pick a model on your adapter, and Patter bills the right rate automatically.Example B — Override one model, keep siblings intact
mergePricing overlays the nested models map shallowly. Overriding a single model leaves the other rates inside the same provider untouched.
Example C — Register a brand-new model rate
Add a model that isn’t in the built-in table without touching SDK source.Default Pricing (2026.3)
Provider-level defaults are listed below. Per-model rates live underDEFAULT_PRICING[provider].models and are auto-resolved when the adapter exposes its model identifier.
STT — per-model rates
TTS — per-model rates
OpenAI Realtime — per-model rates
xAI Realtime — rates
Unlike OpenAI Realtime (token-based), the xAI Grok Voice Agent is billed per minute of session audio, so Patter meters it from the call’sdurationSeconds rather than token counts.
Twilio defaults match US inbound local. Override
pricing.twilio.price for US toll-free inbound (~0.014/min). Default pricing is based on publicly listed provider rates and may become stale — check the provider’s pricing page or pass your own overrides for authoritative numbers.Real-Time Metrics
Use theonMetrics callback for live cost updates during a call:

