Skip to main content

Documentation Index

Fetch the complete documentation index at: https://patter-06b046ce-feat-observability-otel-attrs-0-6-1.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Dashboard

Patter ships a built-in web dashboard for monitoring calls in real time. It runs alongside your agent server and gives you a visual interface for live call tracking, latency analysis, cost breakdowns, and historical data export.
The dashboard was rewritten as a Vite + React single-page app in the latest release. The user-facing experience is unchanged — phone.serve() still serves the UI from http://127.0.0.1:8000/, with no extra build step, no CDN dependency, and identical routes. Only the visuals and internal organisation have changed.

Enabling the dashboard

The dashboard is enabled by default whenever you start a server in local mode:
await phone.serve(
    agent,
    port=8000,
    dashboard=True,             # Enable dashboard (default: True)
    dashboard_token="secret",   # Optional: protect with a token
)
Once running, open your browser at http://127.0.0.1:8000/.
When dashboard=True and no dashboard_token is set, the SDK logs a warning at startup. For anything beyond local development, always set a token — the dashboard surfaces transcripts and customer phone numbers.

Authentication

Protect the dashboard with a token:
await phone.serve(
    agent,
    port=8000,
    dashboard_token="my-secret-token",
)
Access via:
  • Browser: http://127.0.0.1:8000/?token=my-secret-token
  • API: Authorization: Bearer my-secret-token header
When no token is set, the dashboard is accessible without authentication (intended for 127.0.0.1 development only).

What you see

The dashboard is a single-page app that consumes the SDK’s existing /api/dashboard/* endpoints and pushes live updates over Server-Sent Events.

Top metrics row

Aggregate counters across the in-memory ring buffer (last 500 calls):
  • Total Calls — completed + active
  • Total Cost — summed across STT, LLM, TTS, and telephony
  • Avg Duration — mean call length
  • Avg Latency — end-to-end response latency
Numerics use JetBrains Mono so columns line up at a glance.

Call table

All completed calls with cost, duration, turn count, latency, provider, and voice mode. Click any row to open the detail panel.

Live-call right rail

When a call is active, the right rail shows it in real time:
  • Caller / callee numbers (last-4 redacted in logs, full in UI)
  • Live duration counter
  • Streaming transcript with speaker labels
  • Per-call latency waterfall — STT, LLM first-token, TTS first-byte, total turn latency
  • Cost breakdown — running totals per component as the call progresses
When the call ends, it moves into the call table and the right rail clears.

Call detail

Click any historical call to see the full transcript, the same latency waterfall (averaged + P95), and the same cost breakdown for that single call.

Real-time updates

All views subscribe to GET /api/dashboard/events (SSE). New calls, transcript turns, and metric updates appear without polling or refresh.

Data export

Export the call ring buffer in CSV or JSON:
FormatEndpointShape
CSVGET /api/dashboard/export/calls?format=csvOne row per call, flat columns
JSONGET /api/dashboard/export/calls?format=jsonFull nested data including per-turn metrics

API endpoints

The dashboard UI is a thin client over a stable REST + SSE API. Use these directly to integrate with your own tooling.
EndpointDescription
GET /Dashboard web UI (single self-contained HTML file).
GET /api/dashboard/callsPaginated call history.
GET /api/dashboard/calls/{call_id}Single call detail with full transcript.
GET /api/dashboard/activeCurrently active calls.
GET /api/dashboard/aggregatesAggregate statistics.
GET /api/dashboard/eventsSSE event stream for live updates.
GET /api/dashboard/export/callsExport calls as CSV (?format=csv) or JSON.

Example: fetch call history

import httpx

resp = httpx.get(
    "http://127.0.0.1:8000/api/dashboard/calls",
    headers={"Authorization": "Bearer my-secret-token"},
    params={"limit": 10, "offset": 0},
)
calls = resp.json()

Example: subscribe to live events

import httpx

with httpx.stream(
    "GET",
    "http://127.0.0.1:8000/api/dashboard/events",
    headers={"Authorization": "Bearer my-secret-token"},
) as response:
    for line in response.iter_lines():
        if line.startswith("data:"):
            print(line)
The dashboard stores metrics in an in-memory 500-call ring buffer. Data persists across restarts via the on-disk hydration layer (see dashboard/persistence.py), but for long-term analytics use the on_call_end callback to write metrics to your own database.