:443 plane. You do not negotiate ICE/DTLS/SRTP. You do
not operate a media server.
There are three ways to connect a runtime. They are listed from least code to
most control:
Vendor bridge
A config node with no code. Point a call at an external orchestration
vendor (LiveKit / Vapi / Twilio). ClutchCall stays the transport in front
of the vendor.
Raw MoQT bridge
Subscribe to the caller’s uplink. Publish your reply as the
downlink. You own capture, model, and playback. ClutchCall moves the
frames. This is the stable path.
LiveKit-compat shim
A surface with the shape of
livekit-client over our transport. Change one
import.
Route 1 — bridge to an external vendor
Your runtime can be another orchestration product, for example a LiveKit Agent, a Vapi assistant, or a Twilio app. In this case you do not write integration code. You add aVENDOR_BRIDGE node to the agent’s pipeline config. When
the runtime reads this node, it sends the call’s media to that vendor over an
external bridge sidecar. It does not run our own ASR→LLM→TTS pipeline.
ClutchCall stays the QUIC transport in front of the vendor’s media backend.
LiveKit Agents is the exception. A packaged plugin is available:
livekit-plugins-clutchcall / @clutchcall/livekit-transport. The plugin installs into your
livekit-agents worker and replaces only its transport. You do not need a
sidecar or a LiveKit server. Set vendor_provider to clutchcall
(not livekit) to dispatch to a worker that runs the plugin. See
LiveKit Agent Integration.string
required
The external orchestration vendor:
livekit, vapi, or twilio. This value
selects the bridge protocol that the sidecar speaks. Set the value to
clutchcall to dispatch directly to a worker that runs the
LiveKit-Agents transport plugin. That path does not use a sidecar.string
The vendor-side target: a LiveKit room, a Vapi assistant id, or a Twilio app.
For
clutchcall, the target is the name that your plugin worker
registered.string
A reference into the tenant’s stored vendor credentials (sealed at rest). The
vendor’s keys never appear in the pipeline document.
agent.clutchcall.dev or through the
control-plane API. Then point a trunk or an outbound call at the agent. See the
vendor-specific pages for the exact room and credential shape:
LiveKit Agent
Run a LiveKit agent behind our transport.
Pipecat
Run a Pipecat pipeline behind our transport.
Route 2 — the raw MoQT audio bridge
This is the direct path, and most custom runtimes use it. You attach to a live call. You receive the caller’s audio frames. You send your reply frames back. Each call is addressed by itscall_sid. The call’s audio lives on two
MoQT tracks under a room-scoped namespace:
The SDK’s
AudioBridge wraps both tracks behind one handle. attach()
subscribes to the uplink and publishes the downlink for you. The logic between
onUplink and publishDownlink is yours: your VAD, your turn-taking, your
model.
1
Attach to the call
Open the bridge with the call’s
call_sid. Select the codec that matches
the leg. Use opus for browser and app callers. Use g711_ulaw,
g711_alaw, or pcm16 for phone callers.2
Consume the uplink
Your
onUplink callback fires for each inbound audio frame. Send the frame
to your runtime’s input, for example your ASR or your speech-to-speech
session.3
Publish the downlink
When your runtime produces reply audio, call
publishDownlink(frame) for
each encoded frame (for example, one 20 ms Opus packet). The caller hears
the audio.4
Close on teardown
Release the handle when the call ends. This stops both tracks and ends the
bridge.
- TypeScript
- Python
Same shape in every SDK. Go, Rust, Java, and .NET expose the same
attach / publish_downlink primitives through a shared native core. The
native bindings speak QUIC/MoQT directly. They do not include the
browser’s WebSocket/WebRTC fallback leg. Plan for a QUIC-reachable network.
See the transport SDK reference for
per-language method and event names.Namespace rule. Track namespaces are room-scoped tuples. The prefix and
the suffix must not be empty. The media-over-QUIC engine rejects empty
tuples. The
voice/<sid>/{uplink,downlink} convention obeys this rule. The
SDK builds the namespaces for you from the call_sid. If you build
namespaces manually, keep them room-scoped. For more about the object model,
see
Sessions, Calls, Tracks & Streams.Where the call_sid comes from
You attach a bridge to a call that already exists. For an outbound call,
voice.calls.originate returns the call_sid. For inbound calls, point the
trunk’s inbound rule at your integration. This routes the leg to your bridge
instead of the built-in runtime. Then attach as each call arrives. The
telephony transport section
covers trunk routing.
Route 3 — the LiveKit-compatible shim
If your runtime is a browser LiveKit app, use thelivekit-compat shim. The
shim exposes a surface with the shape of livekit-client (Room, RoomEvent,
tracks, participants) mapped onto our MoQT/QUIC transport. The core voice path
covers these actions: publish the mic, subscribe to remote audio, and exchange
data messages. For this path, migration is a one-line import change. There is
no SFU and no ICE.
Preview. The
livekit-compat shim is experimental and audio-first. It
covers the core voice path. It is not yet a replacement for every
livekit-client API. Video and screenshare are deferred. The shim ships for
the browser / TypeScript client only. For a server-side LiveKit
agent, use the transport plugin
instead. The plugin replaces the agent session’s audio IO. It does not
emulate a room. Pin a version and test your flows. The full walkthrough is in
Keep Your Existing Agent Runtime.
It includes the RTCRtpScriptTransform requirement and the API mapping.Which route?
LiveKit Agents plugin
Use this route when your runtime is a
livekit-agents worker. It is a
packaged plugin. It needs no sidecar and no LiveKit server. It is shipped.Vendor bridge
Use this route when your runtime is Vapi or Twilio orchestration, or a
LiveKit room that must continue to run. It is config-only. You run the
external sidecar.
Raw MoQT bridge
Use this route for a custom runtime, a non-browser runtime, or a
server-side loop. It gives the most control. It is fully shipped in every
SDK.
LiveKit-compat shim
Use this route for a browser LiveKit app that you want to move with minimal
edits. It is a preview.
Related
Keep Your Existing Runtime
The full browser guide: the shim, the transport primitives, and the codec
tap that moves an existing WebRTC pipeline onto QUIC.
BYO Speech-to-Speech
Keep our runtime and point it at your own realtime endpoint with
per-tenant credentials.
Agent Runtime Overview
What the managed runtime does when you want us to drive the conversation.
From Self-Hosted LiveKit
The end-to-end migration path for a LiveKit deployment that moves onto our
transport.

