Get started
How Tenms works
The pieces of Tenms, how audio and summaries flow between them, and where the latency goes.
How the pieces fit: the in-process SDK, Tenms Edge, the ElevenLabs bridge and the control plane, and the measured latency of each stage.
Your voice agent (Pipecat, LiveKit, custom)
├─ in-process SDK (Python wheel, C library) ── call summary ──► control plane
└─ WebSocket ──► Tenms Edge /v1/stream ──────── call summary ──► control plane
Browser or device (ElevenLabs client)
└─ WebSocket + session token ──► Tenms Edge /v1/elevenlabs/stream ──► ElevenLabs Agents
Your backend (holds the license)
└─ POST /v1/session-tokens ──► control plane (https://app.tenms.cloud)
control plane ──► dashboard: calls, failure causes, interruptions, regions
System
| Crate | Role | Depends on |
|---|---|---|
tenms-proto | Wire types: Module, ModuleSet, Claims + sign/verify, CallSummary, CallBatch, Edge ClientMessage/ServerEvent | — |
tenms-core | Engine, DSP, model runtime, vendor licensing, C ABI | proto |
tenms-edge | Streaming service, ElevenLabs bridge, telemetry, revocation | core, proto |
tenms-control | Licenses, session tokens, ingest, reads, stats, dashboard | proto |
tenms-models | Open-model assist layer: AssistedEngine = Engine + Silero VAD / Smart Turn / CAM++ via ONNX Runtime, fed through the engine’s assist API | core, proto, ort |
tenms-cli | Offline WAV runner and benchmark (process --models) | core, proto, models (feature, default on) |
tenms-py | Python extension tenms._native | core, proto |
Audio never waits on the network inside Tenms: licenses are verified offline (Ed25519), summaries are uploaded asynchronously, and the revocation list is polled in the background.
Latency budget
| Stage | Budget / target | Measured | Source |
|---|---|---|---|
| Frame size | 10 ms | — | SPEC |
| Algorithmic delay (Focus) | ≤ 10 ms total, target 5 ms at 16 kHz | 5 ms at 16 kHz; 7 ms at 24/48 kHz; 8 ms at 8 kHz; 0 without Focus | core README (tests/focus.rs) |
| Chunk buffering (SDK / Edge) | — | 0 for whole 10 ms chunks, else < 10 ms once | python README, elevenlabs.md |
| Engine compute per frame, p99 | < 1 ms (product target < 150 µs) | 46 µs DSP with reference, 95 µs DSP + GRU H=128 (16 kHz, offline) | core README |
| 100 µs p99 (p50 21 µs) live Pipecat-over-Daily | python/tests/live_reports/pipecat_daily_latest.json | ||
| ~50-65 µs p99 on production Edge | deployment smoke test | ||
| ElevenLabs bridge processing | — | p99 ≤ 150 µs per chunk | elevenlabs.md |
| Network to Edge | deploy near callers | ~118 ms RTT India → Singapore | deployment smoke test |
turn_prediction after caller stops | — | ~150-300 ms | python README |
turn_end after caller stops | — | live p50 360 ms, p95 610 ms | live report |
| Barge-in decision, no transcripts | — | ~1.0-1.3 s from onset; one continuous burst needs 800 ms of voicing | core README (tests/verify.rs), deployment facts |
| Barge-in decision, interim transcripts | — | ~355 ms from onset | core README |
| Bridge gate decision after onset | — | other speaker ≈ +90 ms, noise ≈ +160 ms, barge-in ≈ +260 ms | elevenlabs.md |