Skip to main content
A VoiceGateway deployment is single-tenant by default: every record belongs to one operator, no tenant wiring required. Reach for tenant_id only when you need per-call attribution within one deployment: an agency splitting cost per end-user, or a SaaS product fanning usage out to the hosted cloud for per-tenant billing.
tenant_id and project are separate and composable: project groups calls by agent/team/customer at the config level (see Projects); tenant_id stamps an individual end-user on top of that, on the wire. Pass both to attach() when you need both levels. Per-tenant billing and margin rollups run on the hosted cloud.

Prerequisites

  • VoiceGateway installed (voicegw --version).
  • A running gateway daemon (voicegw serve or voicegw onboard).
  • voicegw.yaml with storage.path pointing at your SQLite database.

How it works

attach() accepts a tenant_id keyword argument. Passing it sets a context variable for that call; every STT, LLM, and TTS record written during the session reads it back and stores it. The id is capped at 128 UTF-8 characters. attach() raises ValueError above that; it does not truncate. Sessions where tenant_id is never set store NULL and appear as “unattributed” downstream.

Wire it into attach()

Sub-tenants

Some deployments nest a sub-tenant below the top-level tenant (an agency serving clients that each have end users). Stamp it into metadata.tenant_id on the record; the top-level tenant_id is unchanged.
Sending to the VoiceGateway Cloud collector? Pass metadata.tenant_id in the ingest payload: the collector routes it alongside the top-level tenant_id so both appear in the hosted dashboard. See Hosted quickstart.

Reading per-tenant costs

Per-tenant rollups (revenue, cost, margin) run on the hosted cloud, which resolves the tenant from the verified vk_ ingest key. In an OSS deployment tenant_id is stored but not exposed in a dashboard filter: read it back with SQL. The sessions, requests, and turns tables all carry tenant_id:
For a managed per-tenant billing view (rated revenue, recorded cost, margin), send your fleet to the hosted cloud and read GET /v1/billing/usage. See Rating and the HTTP API reference.

Known limitations

Deliberate scope decisions, not bugs.
  • No dashboard tenant selector. The OSS dashboard renders one deployment’s totals; per-tenant slicing lives on the hosted cloud.
  • No re-tag. Once a session has a non-NULL tenant_id, it can’t be changed after the fact.
  • Virtual keys carry no RBAC scopes. A verified virtual key grants the same access as a wildcard static key.

See also

attach()

Full signature and wiring reference for LiveKit and Pipecat.

Projects

Group cost by agent, team, or client at the config level.

Multi-project example

Code example using multiple projects and tenants side by side.