- It provisions the tenant’s endpoints and data isolation.
- It mints a scoped key for that tenant.
- It publishes the tenant’s agent config.
- It drives calls with the tenant’s own key.
<orgId>.sip.clutchcall.dev), the analytics row policy, sealed
credentials, and the usage account are all keyed on it. A customer can
therefore rename their workspace without a move of any infrastructure. For the
conceptual model behind this code, read
Building voice agent platforms first.
Two planes, two credentials
The control plane lives atportal.clutchcall.dev. Per-tenant call and audio
traffic goes through the SDK. The SDK talks to engine.clutchcall.dev and the media
relay. Provisioning steps are idempotent. A re-run of the bootstrap
backfills anything that was missed. Onboarding is therefore safe to retry.
1. A thin control-plane client
Provisioning is not in the SDK. It is a privileged control-plane surface that you call from your backend. This small wrapper posts to the control-plane API with your platform credential. Every helper below is a real provisioning route.- TypeScript
- Python
2. Onboard a tenant
One call tobootstrap fans out the per-tenant resources: the DNS labels
(<orgId>.sip / <orgId>.webrtc / <orgId>) that resolve to the engine, the
isolated analytics role with a row policy pinned to tenant_id, the usage
account, and the tenant’s entitlement. Then you do five things:
- Register the tenant’s trunk.
- Map their DIDs.
- Seal any bring-your-own provider keys.
- Publish their agent.
- Mint the scoped key that their backend will use.
1
Bootstrap the org
Creates endpoints + data isolation, keyed on the org id.
2
Register trunk + numbers
Point their SIP trunk at their realm. Map DIDs to it.
3
Seal provider keys
Store BYO keys sealed under the org. This step is optional; tenants can inherit your keys.
4
Publish the agent
Hydrate the saved agent config to the engine.
5
Mint a scoped key
Hand the tenant a key bound to their org id.
- TypeScript
- Python
hydrateAgent publishes an agent that your customer already authored
(prompt, providers, voice, turn-detection, tools). The agent-authoring model is
the pipeline config that each tenant edits. It lives in
runtime configuration.
BYO ASR/LLM/TTS covers the
provider-key resolution order (per-agent → per-tenant → platform fallback).3. Drive calls with the tenant’s key
Now switch planes. To place or manage a call for a tenant, instantiate the SDK with that tenant’s scoped key and org id. The org id is the boundary that the control plane enforces on every request. One tenant’s key can never address another tenant’s calls, agents, or audio.- TypeScript
- Python
<orgId>.sip.clutchcall.dev by its
leftmost DNS label to the tenant. It resolves the call to the agent. It answers
the call. Your backend gets involved only for outbound calls, transfers, or
supervision.
4. Wire it to an HTTP surface
Wrap the two functions above in two routes. That gives you a complete onboarding-and-dial backend. Guard the provisioning route with your own staff auth, because it holds the platform credential. Scope the dial route to the authenticated tenant.- TypeScript
- Python
Least-privilege scopes
Mint the narrowest scope set that each consumer needs. Scopes areproduct:action strings that the control plane checks per endpoint. The
control plane refuses (403) a request that does not have the required scope.
scope
Read call state and history: status polls, listing, reports. Give this scope
to a dashboard or a read-only integration.
scope
Originate, transfer, and hang up calls. Attach agents. This is the scope
that a tenant’s call-driving backend needs.
scope
All voice actions. Use it rarely. Prefer the two explicit scopes above.
Metering is automatic
You do not write metering code. The engine attributes usage per tenant as calls run. On each teardown, it emits a CDR (Q.850 cause + duration, keyed bycall_sid) rated against the tenant’s usage account. It also accounts media
bytes per tenant per modality into a per-minute rollup. Both are keyed on the
same org id. You can therefore read a tenant’s spend and bandwidth the moment
their first call clears. See
dashboards and
call traces.
Related
Building voice agent platforms
The concepts behind this code: tenancy, isolation, and metering.
Runtime configuration
The per-agent pipeline config each tenant authors.
SIP trunking
Register a tenant’s trunk against their realm.
Contact-center platform
Add ACD, skills, and supervisor tooling on top of tenancy.

