# Migration Overview

> Move an existing voice workload onto FirstByte Voice. Swap only the media transport. Keep your runtime, agent, models, and business logic.

You already have a working voice stack. It can be a LiveKit app, a WebRTC
pipeline, a Twilio Media Streams bridge, an Asterisk or FreeSWITCH deployment,
or a bespoke WebSocket audio sender. A migration to FirstByte Voice does
**not** require a rewrite. The fastest and lowest-risk path is
**transport-first**. Keep your runtime, your agent loop, your ASR/LLM/TTS
chain, and your call control. Swap only the layer that moves audio. That layer
becomes real-time media over QUIC/MoQT on the single `:443` plane.

## The transport-first thesis

Many voice migrations stall because teams treat them as a full-platform port.
This is not necessary. Your runtime already produces and consumes audio frames
across a media boundary. That boundary is WebRTC's SRTP, a WebSocket that
carries PCM or µ-law, or RTP on a SIP trunk. In the migration, you re-point
that one boundary at FirstByte. Everything above it stays unchanged.

  - **What you keep** — You keep your conversation loop, VAD and turn-taking, prompts and tools,
    models and vendor credentials, call-control logic, and dashboards.
  - **What you swap** — You swap only the media transport. The media transport is the wire that
    carries encoded audio between your runtime and the endpoint (browser, app,
    or phone).

Whether FirstByte also *runs* your agent is a separate, later choice. You can
adopt the transport alone and keep your runtime indefinitely. See
[Keep Your Existing Agent Runtime](/modalities/voice/runtime/keep-existing). The
menu below is only about the media boundary.

## Pick your path

Choose the path that matches where your audio lives today. Each path re-points
one boundary. The detail page for each path describes the cutover.

  - **[From WebRTC](/modalities/voice/migration/from-webrtc)** — Keep the browser's capture, echo cancellation, and Opus encoder. Divert the
    **encoded** frames onto QUIC/MoQT instead of ICE/DTLS/SRTP. This path is
    **Shipped** in the TypeScript SDK.
  - **[From Self-Hosted LiveKit](/modalities/voice/migration/from-livekit)** — Install the transport plugin in your `livekit-agents` worker. Then retire
    the SFU. This path is **Shipped**. Or swap one import in a browser app.
    That path is **Preview**.
  - **[From Custom WebSocket Audio](/modalities/voice/migration/from-websocket-audio)** — Point a bespoke WebSocket audio sender at the engine's WebSocket media
    fallback. Or connect your runtime to the raw publish/subscribe primitives.
  - **[From Twilio Media Streams](/modalities/voice/migration/from-twilio)** — Move a µ-law Media Streams WebSocket onto a SIP `PCMU` trunk with zero
    transcode. Or bridge it as an external media vendor.
  - **[From Asterisk / FreeSWITCH](/modalities/voice/migration/from-asterisk-freeswitch)** — Re-point your SIP trunks and agent endpoints at FirstByte's built-in
    B2BUA, registrar, and dialplan. This path is **Shipped**. You do not need a
    separate SIP proxy.
  - **[Migration Checklist](/modalities/voice/migration/checklist)** — Run this step-by-step cutover checklist after you pick a path.

## What each path swaps

> **NOTE:**
> Status shows what ships **today**. "Shipped" paths are proven end-to-end.
>   "Preview" paths work for the core voice case. But they are not yet drop-in for
>   every API of the source product. Read the callouts on each path page before
>   you plan a cutover.

| Coming from | You swap | You keep | Status |
| --- | --- | --- | --- |
| **WebRTC** (browser) | ICE/DTLS/SRTP → encoded Opus over QUIC/MoQT | Capture, AEC/AGC/NS, Opus encoder, your runtime | Shipped (TS SDK) |
| **Self-hosted LiveKit** (agent) | The SFU + `RoomIO` → QUIC session bound to your `AgentSession` | Your `entrypoint`, plugins, provider keys, tool calls | Shipped (transport plugin) |
| **Self-hosted LiveKit** (browser) | The SFU + `livekit-client` transport → MoQT session | Your `Room`/track code, participants, data | Preview (browser shim) |
| **Custom WebSocket audio** | Your WS media wire → engine WS media fallback / MoQT primitives | Your audio format handling and runtime | Available on-ramp |
| **Twilio Media Streams** | µ-law WS → SIP `PCMU` trunk (passthrough) or vendor bridge | Your app logic and prompts | Shipped (SIP) |
| **Asterisk / FreeSWITCH** | Your PBX/proxy → our B2BUA + registrar + dialplan | Trunks, DIDs, agents, routing intent | Shipped (SIP) |

> **WARNING:**
> **The two LiveKit rows are different products. Do not mix them up.** The
>   server-side **transport plugin** (`livekit-plugins-clutchcall` / `@clutchcall/livekit-transport`)
>   is shipped. It installs into your agent worker and replaces the session's
>   audio IO, so there is no room to emulate. It has three limits: `pcm16` audio,
>   a register-and-wait worker (not scale-to-zero), and a need for outbound
>   UDP/443.
> 
>   The browser **`livekit-compat` shim** is Preview. It covers the core voice
>   path (publish/subscribe audio, data messages). It was tested
>   browser-to-browser over the transport. But it is not yet a drop-in for every
>   `livekit-client` API, and video and screenshare are deferred. Pin a version.
>   Test your flows. See
>   [Keep Your Existing Agent Runtime](/modalities/voice/runtime/keep-existing).

## How a transport-first migration runs

Every path has the same shape. The per-source page has the detail. This section
shows the sequence.

  1. **Provision your workspace**
Onboarding creates your per-tenant endpoints: `<workspace-id>.sip.firstbyte.fast`
    for phone traffic and `<workspace-id>.webrtc.firstbyte.fast` for browser and
    app media. It also creates your relay at `relay.firstbyte.fast`. Nothing in
    your runtime changes yet.
  2. **Re-point one media boundary**
Swap only the transport for the path you picked:

    - Divert encoded WebRTC frames onto QUIC/MoQT.
    - Or swap the LiveKit import.
    - Or point your WebSocket sender at the engine's media fallback.
    - Or re-point a SIP trunk.

    Your agent code stays unchanged.
  3. **Verify audio both ways**
Check that uplink audio (caller/browser → runtime) flows. Check that
    downlink audio (runtime → caller) flows. Check quality. On telephony legs,
    the media plane scores MOS, jitter, and loss per call. Compare these scores
    against your old stack. See
    [MOS, Jitter & Loss](/modalities/voice/observability/mos-jitter-loss).
  4. **Cut over gradually**
Route a slice of traffic to the new transport. A slice can be a test DID, a
    canary trunk, or a subset of browser sessions. Watch the dashboards. Then
    widen the slice. Follow the
    [Migration Checklist](/modalities/voice/migration/checklist) for the full
    cutover sequence.

## Where the runtime line falls

Transport-first is one end of a spectrum. The minimal-change migration keeps
your runtime and uses only the wire. You can also give the conversation loop to
FirstByte and bring only the **models**. That choice is a runtime adoption,
not a transport swap. FirstByte can run a cascaded ASR→LLM→TTS pipeline or a
speech-to-speech provider for you.

> **NOTE:**
> **LiveKit Agents and Pipecat have packaged plugins. Other stacks have the
>   external-agent SDK or a bridge.** For a `livekit-agents` worker, install
>   `livekit-plugins-clutchcall` / `@clutchcall/livekit-transport`. For a Pipecat pipeline, install
>   `pipecat-clutchcall`. In both cases, your agent runs over our transport
>   directly. If you come from Twilio, Vapi, Plivo, or Telnyx, use the provider
>   starters. The starters port each vendor's official sample onto the
>   `clutchcall-agents` external-agent SDK (see the
>   [integration pages](/modalities/voice/integrations/twilio)). If you keep a
>   vendor-hosted runtime in operation and put FirstByte in front of it, that
>   is a **config-level bridge**. See
>   [Keep Your Existing Agent Runtime](/modalities/voice/runtime/keep-existing).

## Next steps

  - **[Keep Your Existing Agent Runtime](/modalities/voice/runtime/keep-existing)** — Adopt the transport alone and leave your runtime in place. This page covers
    the shim and the raw primitives in depth.
  - **[WebRTC Diversion](/modalities/voice/transport-web/webrtc-diversion)** — The encoded-frame tap moves a browser WebRTC pipeline onto QUIC. It does not
    touch capture or the codec.
  - **[SIP Trunking](/modalities/voice/transport-telephony/sip-trunking)** — Re-point carrier trunks at the built-in B2BUA and registrar for telephony
    migrations.
  - **[Migration Checklist](/modalities/voice/migration/checklist)** — Run the ordered cutover checklist after you choose a path.
