Skip to main content

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, the onCallEnd callback receives a CallMetrics object with the full breakdown:
await phone.serve(agent, {
  port: 8000,
  onCallEnd: async (event) => {
    const metrics = event.metrics;
    if (metrics) {
      console.log(`Duration: ${metrics.durationSeconds}s`);
      console.log(`Total cost: $${metrics.cost.total.toFixed(4)}`);
      console.log(`  STT: $${metrics.cost.stt.toFixed(4)}`);
      console.log(`  TTS: $${metrics.cost.tts.toFixed(4)}`);
      console.log(`  LLM: $${metrics.cost.llm.toFixed(4)}`);
      console.log(`  Telephony: $${metrics.cost.telephony.toFixed(4)}`);
      console.log(`Avg latency: ${metrics.latencyAvg.totalMs}ms`);
      console.log(`P95 latency: ${metrics.latencyP95.totalMs}ms`);
    }
  },
});

Cost Breakdown

The CostBreakdown object provides per-component costs in USD:
FieldDescription
sttSpeech-to-text cost (Deepgram, Whisper).
ttsText-to-speech cost (ElevenLabs, OpenAI TTS).
llmLLM cost (OpenAI Realtime tokens).
telephonyTelephony cost (Twilio, Telnyx per-minute).
totalSum of all components.

Latency Breakdown

The LatencyBreakdown object provides per-component latency in milliseconds:
FieldDescription
sttMsTime from user speech to transcript.
llmMsTime from transcript to LLM response.
ttsMsTime from LLM response to first audio byte.
totalMsEnd-to-end latency (user speech to first audio).
Both latencyAvg and latencyP95 are available on CallMetrics.

Per-Turn Metrics

Each conversation turn is tracked individually:
await phone.serve(agent, {
  port: 8000,
  onCallEnd: async (event) => {
    const metrics = event.metrics;
    if (metrics) {
      for (const turn of metrics.turns) {
        console.log(`Turn ${turn.turnIndex}:`);
        console.log(`  User: ${turn.userText}`);
        console.log(`  Agent: ${turn.agentText}`);
        console.log(`  Latency: ${turn.latency.totalMs}ms`);
      }
    }
  },
});

Custom Pricing

Override default provider pricing estimates:
const phone = new Patter({
  openaiKey: "sk-...",
  mode: "local",
  pricing: {
    deepgram: { price: 0.005 },      // Override STT price per minute
    elevenlabs: { price: 0.15 },      // Override TTS price per 1k chars
    twilio: { price: 0.015 },         // Override telephony price per minute
  },
});

Default Pricing

ProviderUnitDefault Price
Deepgramper minute$0.0043
Whisperper minute$0.006
ElevenLabsper 1k chars$0.18
OpenAI TTSper 1k chars$0.015
OpenAI Realtimeper tokenvaries by type
Twilioper minute$0.013
Telnyxper minute$0.007
Default pricing is based on publicly listed provider rates and may become stale. Pass your own overrides for accurate cost tracking, or check the provider’s pricing page.

Real-Time Metrics

Use the onMetrics callback for live cost updates during a call:
await phone.serve(agent, {
  port: 8000,
  onMetrics: async (data) => {
    const cost = data.costSoFar;
    if (cost) {
      console.log(`Running cost: $${cost.total.toFixed(4)}`);
    }
  },
});

Data Types

import type {
  CallMetrics,
  CostBreakdown,
  LatencyBreakdown,
  TurnMetrics,
} from "@patter-dev/sdk";

CallMetrics

FieldTypeDescription
callIdstringUnique call identifier.
durationSecondsnumberTotal call duration.
turnsTurnMetrics[]Per-turn metrics.
costCostBreakdownCost breakdown.
latencyAvgLatencyBreakdownAverage latency.
latencyP95LatencyBreakdown95th percentile latency.
providerModestringVoice mode used.
sttProviderstringSTT provider name.
ttsProviderstringTTS provider name.
telephonyProviderstringTelephony provider name.

TurnMetrics

FieldTypeDescription
turnIndexnumberZero-based turn index.
userTextstringWhat the user said.
agentTextstringWhat the agent replied.
latencyLatencyBreakdownLatency for this turn.
sttAudioSecondsnumberAudio duration processed by STT.
ttsCharactersnumberCharacters synthesized by TTS.
timestampnumberUnix timestamp.