You already have a working LiveKit agent. You want it reachable over the PSTN, or you want the caller edge to run on TeleQuick’s QUIC transport instead of a LiveKit SFU — without rewriting the agent. This page shows the two ways to do that: front-proxy the media through the voice gateway (shipped), or point a browser client at the livekit-compat shim (preview).
There is no packaged LiveKit-Agents adapter. You do not install a TeleQuick plugin into your LiveKit agent process, and there is no pip install-able runtime bridge that lives inside your agent. Integration happens at the edge — TeleQuick sits in front of your agent and moves audio to it — not inside your agent’s code.

Front-proxy the media

Shipped. The voice gateway terminates the caller (SIP trunk or browser QUIC) and bridges the audio to your existing LiveKit room. Your agent code is untouched — it sees a normal room participant.

Browser compat shim

Preview. Swap one import so a livekit-client browser app publishes and subscribes over MoQT/QUIC instead of the SFU. No media server to operate.

Path A — front-proxy the media (shipped)

Put the voice gateway in front of your LiveKit deployment. The gateway owns the hard edge — a PSTN SIP trunk, or a browser leg over QUIC on the single :443 plane — decodes it to the runtime’s 8 kHz PCM audio bus, and relays that audio over a WebSocket media bridge to a small bridge process you run alongside your LiveKit deployment. That bridge joins your LiveKit room as an ordinary participant, so your agent needs no changes at all.
 PSTN / SIP trunk ─▶ ┌──────────────────┐  WebSocket   ┌──────────────┐   ┌──────────────┐
                     │  voice gateway   │   media      │ bridge       │   │  your LiveKit│
 browser (QUIC/MoQT) │  (terminates the │──── bridge ──▶ sidecar      │──▶│  room + agent│
 on :443 ──────────▶ │  caller edge)    │              │ (joins room) │   │              │
                     └──────────────────┘              └──────────────┘   └──────────────┘
What you get from the edge: the gateway’s SIP trunking, in-kernel-bypass RTP media plane, MOS/jitter/loss scoring, recording, and the QUIC transport — all in front of a LiveKit agent that keeps running exactly as it does today.
What’s shipped vs. what you deploy. The gateway-side bridge — a vendor-bridge pipeline node plus the WebSocket media handler — is in-tree and shipped. The bridge sidecar that joins your LiveKit room is a component you run next to your LiveKit deployment, using your LiveKit URL, API key, and secret. The edge is shipped; the bridge is a thin component you operate.
1

Point an agent at the vendor bridge

Instead of a cascade or a duplex model, the agent’s pipeline routes the call’s media to your external vendor. The exact field names live in the Runtime Configuration reference; the shape is:
agent-config.yml
name: livekit-front-proxy
entry_node: vendor_bridge
pipeline:
  vendor_bridge:
    node_type: vendor_bridge
    target: livekit            # livekit | vapi | twilio
    # Where the bridge sidecar is reachable (WebSocket media bridge):
    bridge_url: wss://<your-bridge-host>/bridge
With this config the runtime does not run turn detection or a model — it hands the caller’s audio to the bridge and streams the bridge’s audio back onto the call. Your LiveKit agent owns the conversation.
2

Route a trunk or number to that agent

Attach an inbound number or SIP trunk to the agent so real calls reach it. Provisioning a trunk and a DID is covered in SIP Trunking and Number Provisioning.
3

Run the bridge sidecar next to LiveKit

Deploy the bridge process where it can reach both the gateway’s WebSocket media bridge and your LiveKit server. It connects to the gateway to receive caller audio and, using your LiveKit credentials, joins the target room and republishes that audio as a participant track — then relays the agent’s audio back the other way.
The bridge is an external component (declared separately from the engine), so its exact CLI and container image ship with the bridge, not the gateway. Conceptually it needs three things: the gateway bridge URL, your LIVEKIT_URL + LIVEKIT_API_KEY + LIVEKIT_API_SECRET, and the room name to join.
4

Place a call

Dial the number (or send a browser leg at the agent). The caller lands on the gateway, the gateway bridges to your room, and your LiveKit agent answers — with TeleQuick carrying the telephony and transport in front of it.
This is the same vendor-bridge mechanism used for Vapi and Twilio agents — swap target. It is a config-level front-proxy, not a rewrite of your runtime. See Keep Your Existing Runtime for the full “transport-only” spectrum.

Path B — the browser compat shim (preview)

If your LiveKit surface is a browser app (livekit-client), you can skip the edge bridge entirely and run the client’s audio over our transport directly. The livekit-compat shim re-implements the livekit-client API — Room, RoomEvent, tracks, participants — on top of MoQT/QUIC, so the common voice path (publish the mic, subscribe to remote audio, exchange data) is a one-line import swap. There is no SFU and WebRTC’s transport is never used.
Preview / experimental. The livekit-compat shim is an early-access browser package, not a shipped product. It covers the core voice path (publish/subscribe audio, data messages) — video, screenshare, and per-participant E2EE key rotation are deferred, and a session-setup race can occasionally deliver zero frames on connect (retry the connect). Pin a version and test your flows. A server-side Python equivalent (the livekit.rtc surface) is not yet available.
- import { Room, RoomEvent, createLocalAudioTrack } from "livekit-client";
+ import { Room, RoomEvent, createLocalAudioTrack } from "@telequick/sdk/livekit-compat";
const room = new Room();
await room.connect(url, token);              // to your relay.telequick.dev endpoint
await room.localParticipant.setMicrophoneEnabled(true);
room.on(RoomEvent.TrackSubscribed, (track) => track.attach());
The mic still goes through the browser’s Opus encoder, but only the encoded frames are extracted and sent over MoQT — the shim requires encoded media transforms (RTCRtpScriptTransform) and refuses to connect on a browser that would silently fall back to plaintext WebRTC. Today that means Chromium-family browsers. The full deep-dive — install, what maps to what, the fallback ladder — is in Keep Your Existing Runtime and WebRTC Diversion.

Which path?

These are not mutually exclusive — front-proxy a phone leg and move a browser client onto the transport at the same time.
You haveUseStatus
A LiveKit agent you want on the PSTN / QUIC edgeFront-proxy the media (Path A)Shipped edge + a bridge you run
A LiveKit browser app (livekit-client)The livekit-compat shim (Path B)Preview
A LiveKit Python agent, transport onlyFront-proxy (Path A) or the transport primitivesPath A shipped; Python shim not available

Keep Your Existing Runtime

The full transport-only spectrum — the shim and the raw MoQT primitives.

From Self-Hosted LiveKit

The end-to-end migration path — trunks, tokens, and rollout.

Bridge a LiveKit Agent

A worked example of connecting a LiveKit agent to a call.

Custom Agent Runtime

The same front-proxy pattern for any non-LiveKit runtime.