> ## Documentation Index
> Fetch the complete documentation index at: https://docs.spatius.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Backend Mode Integration

> Your backend owns the audio pipeline and downstream transport.

export const HostedModeOwnTransportDiagram = () => {
  return <div className="spatius-diagram not-prose" aria-label="Backend Mode architecture with your own transport">
      <svg viewBox="-83 0 1535 800" role="img">
        <defs>
          <marker id="spatius-custom-own-transport" viewBox="0 0 12 10" refX="10.5" refY="5" markerWidth="4.5" markerHeight="6" orient="auto-start-reverse">
            <path d="M0 0L12 5L0 10Z" fill="var(--spatius-diagram-red)" />
          </marker>
          <marker id="spatius-custom-own-ink" viewBox="0 0 12 10" refX="10.5" refY="5" markerWidth="4.5" markerHeight="6" orient="auto-start-reverse">
            <path d="M0 0L12 5L0 10Z" fill="var(--spatius-diagram-ink)" />
          </marker>
        </defs>

        <text x="440" y="72" textAnchor="middle" fill="var(--spatius-diagram-red)" fontSize="30" fontWeight="600">You Managed</text>
        <text x="1000" y="72" textAnchor="middle" fill="var(--spatius-diagram-brand)" fontSize="30" fontWeight="600">Spatius Managed</text>

        <rect x="245" y="118" width="390" height="275" rx="18" fill="var(--spatius-diagram-owned)" stroke="var(--spatius-diagram-stroke)" strokeWidth="3" />
        <rect x="285" y="152" width="310" height="92" rx="12" fill="var(--spatius-diagram-owned)" stroke="var(--spatius-diagram-red)" strokeWidth="3" />
        <text x="440" y="192" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="30" fontWeight="500">
          <tspan x="440">Voice Agent</tspan>
          <tspan x="440" dy="34" fill="var(--spatius-diagram-muted)" fontSize="22">ASR / LLM / TTS</tspan>
        </text>
        <rect x="285" y="276" width="310" height="82" rx="12" fill="var(--spatius-diagram-node)" stroke="var(--spatius-diagram-stroke)" strokeWidth="3" />
        <text x="440" y="311" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="30" fontWeight="500">Server SDK</text>
        <text x="440" y="342" textAnchor="middle" fill="var(--spatius-diagram-muted)" fontSize="20" fontWeight="500">Backend Mode</text>
        <polyline points="608,306 865,306" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-ink)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-own-ink)" />
        <polyline points="865,328 608,328" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-ink)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-own-ink)" />
        <text x="736" y="290" textAnchor="middle" fill="var(--spatius-diagram-muted)" fontSize="20" fontWeight="600">Agent Audio</text>
        <text x="736" y="363" textAnchor="middle" fill="var(--spatius-diagram-muted)" fontSize="20" fontWeight="600">Motion Data</text>

        <rect x="875" y="118" width="250" height="275" rx="18" fill="var(--spatius-diagram-managed)" stroke="var(--spatius-diagram-brand)" strokeWidth="3" />
        <text x="1000" y="245" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="31" fontWeight="500">
          <tspan x="1000">Motion</tspan>
          <tspan x="1000" dy="44">Server</tspan>
        </text>
        <polyline points="420,442 420,405" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-red)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-own-transport)" />
        <polyline points="460,405 460,442" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-red)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-own-transport)" />
        <text x="376" y="428" textAnchor="end" fill="var(--spatius-diagram-muted)" fontSize="20" fontWeight="600">User Audio</text>
        <text x="490" y="428" textAnchor="start" fill="var(--spatius-diagram-muted)" fontSize="20" fontWeight="600">Agent Audio + Motion Data</text>
        <rect x="310" y="452" width="750" height="82" rx="12" fill="var(--spatius-diagram-owned)" stroke="var(--spatius-diagram-red)" strokeWidth="3" />
        <text x="685" y="505" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="32" fontWeight="600">Your own transport layer</text>

        <rect x="535" y="615" width="300" height="130" rx="14" fill="var(--spatius-diagram-managed)" stroke="var(--spatius-diagram-brand)" strokeWidth="3" />
        <text x="685" y="680" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="32" fontWeight="500">AvatarKit SDK</text>
        <text x="685" y="722" textAnchor="middle" fill="var(--spatius-diagram-muted)" fontSize="23" fontWeight="500">Web/iOS/Android/Flutter</text>
        <polyline points="665,605 665,548" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-red)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-own-transport)" />
        <polyline points="705,548 705,605" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-red)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-own-transport)" />

        <g className="spatius-audio-visualizer" aria-label="user audio">
          <rect className="spatius-audio-bar" x="220" y="654" width="8" height="54" rx="4" />
          <rect className="spatius-audio-bar" x="238" y="640" width="8" height="82" rx="4" />
          <rect className="spatius-audio-bar" x="256" y="662" width="8" height="38" rx="4" />
          <rect className="spatius-audio-bar" x="274" y="634" width="8" height="94" rx="4" />
          <rect className="spatius-audio-bar" x="292" y="650" width="8" height="62" rx="4" />
        </g>
        <text x="260" y="748" textAnchor="middle" fill="var(--spatius-diagram-muted)" fontSize="28" fontWeight="500">user audio</text>
        <polyline points="335,680 525,680" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-ink)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-own-ink)" />
        <polyline points="847,680 1080,680" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-ink)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-own-ink)" />
        <text x="1102" y="690" textAnchor="start" fill="var(--spatius-diagram-ink)" fontSize="32" fontWeight="500">Avatar</text>
      </svg>
    </div>;
};

export const HostedModeRealtimeTransportDiagram = () => {
  return <div className="spatius-diagram not-prose" aria-label="Backend Mode architecture with third-party realtime transport">
      <svg viewBox="-83 0 1535 800" role="img">
        <defs>
          <marker id="spatius-custom-rtc-transport" viewBox="0 0 12 10" refX="10.5" refY="5" markerWidth="4.5" markerHeight="6" orient="auto-start-reverse">
            <path d="M0 0L12 5L0 10Z" fill="var(--spatius-diagram-livekit)" />
          </marker>
          <marker id="spatius-custom-rtc-ink" viewBox="0 0 12 10" refX="10.5" refY="5" markerWidth="4.5" markerHeight="6" orient="auto-start-reverse">
            <path d="M0 0L12 5L0 10Z" fill="var(--spatius-diagram-ink)" />
          </marker>
        </defs>

        <text x="440" y="72" textAnchor="middle" fill="var(--spatius-diagram-red)" fontSize="30" fontWeight="600">You Managed</text>
        <text x="1000" y="72" textAnchor="middle" fill="var(--spatius-diagram-brand)" fontSize="30" fontWeight="600">Spatius Managed</text>

        <rect x="245" y="118" width="390" height="275" rx="18" fill="var(--spatius-diagram-owned)" stroke="var(--spatius-diagram-stroke)" strokeWidth="3" />
        <rect x="285" y="152" width="310" height="92" rx="12" fill="var(--spatius-diagram-owned)" stroke="var(--spatius-diagram-red)" strokeWidth="3" />
        <text x="440" y="192" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="30" fontWeight="500">
          <tspan x="440">Voice Agent</tspan>
          <tspan x="440" dy="34" fill="var(--spatius-diagram-muted)" fontSize="22">ASR / LLM / TTS</tspan>
        </text>
        <rect x="285" y="276" width="310" height="82" rx="12" fill="var(--spatius-diagram-node)" stroke="var(--spatius-diagram-stroke)" strokeWidth="3" />
        <text x="440" y="311" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="30" fontWeight="500">Server SDK</text>
        <text x="440" y="342" textAnchor="middle" fill="var(--spatius-diagram-muted)" fontSize="20" fontWeight="500">Backend Mode</text>
        <polyline points="608,317 865,317" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-ink)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-rtc-ink)" />

        <rect x="875" y="118" width="250" height="275" rx="18" fill="var(--spatius-diagram-managed)" stroke="var(--spatius-diagram-brand)" strokeWidth="3" />
        <text x="1000" y="245" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="31" fontWeight="500">
          <tspan x="1000">Motion</tspan>
          <tspan x="1000" dy="44">Server</tspan>
        </text>
        <polyline points="1000,400 1000,442" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-livekit)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-rtc-transport)" />

        <polyline points="440,442 440,405" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-livekit)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-rtc-transport)" />
        <rect x="310" y="452" width="750" height="82" rx="12" fill="var(--spatius-diagram-livekit-surface)" stroke="var(--spatius-diagram-livekit)" strokeWidth="3" />
        <text x="685" y="505" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="32" fontWeight="600">Realtime transport</text>

        <rect x="535" y="615" width="300" height="130" rx="14" fill="var(--spatius-diagram-managed)" stroke="var(--spatius-diagram-brand)" strokeWidth="3" />
        <text x="685" y="680" textAnchor="middle" fill="var(--spatius-diagram-ink)" fontSize="32" fontWeight="500">AvatarKit SDK</text>
        <text x="685" y="722" textAnchor="middle" fill="var(--spatius-diagram-muted)" fontSize="25" fontWeight="500">Web</text>
        <polyline points="665,605 665,548" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-livekit)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-rtc-transport)" />
        <polyline points="705,548 705,605" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-livekit)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-rtc-transport)" />

        <g className="spatius-audio-visualizer" aria-label="user audio">
          <rect className="spatius-audio-bar" x="220" y="654" width="8" height="54" rx="4" />
          <rect className="spatius-audio-bar" x="238" y="640" width="8" height="82" rx="4" />
          <rect className="spatius-audio-bar" x="256" y="662" width="8" height="38" rx="4" />
          <rect className="spatius-audio-bar" x="274" y="634" width="8" height="94" rx="4" />
          <rect className="spatius-audio-bar" x="292" y="650" width="8" height="62" rx="4" />
        </g>
        <text x="260" y="748" textAnchor="middle" fill="var(--spatius-diagram-muted)" fontSize="28" fontWeight="500">user audio</text>
        <polyline points="335,680 525,680" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-ink)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-rtc-ink)" />
        <polyline points="847,680 1080,680" className="spatius-diagram-flow" fill="none" stroke="var(--spatius-diagram-ink)" strokeWidth="4" strokeLinecap="round" markerEnd="url(#spatius-custom-rtc-ink)" />
        <text x="1102" y="690" textAnchor="start" fill="var(--spatius-diagram-ink)" fontSize="32" fontWeight="500">Avatar</text>
      </svg>
    </div>;
};

## What is Backend Mode Integration?

Backend Mode Integration is a **Standalone Integration** centered on the **Server SDK**: your backend connects to Motion Server, sends avatar speech audio, receives encoded audio payloads and motion data payloads, then delivers those payloads to AvatarKit clients.

Use this path when your backend owns ASR, LLM, TTS, turn-taking, provider keys, and the connection to Motion Server.

## At a glance

| Dimension            | Backend Mode Integration                                                                                                |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| **Dev effort**       | 🔴 High                                                                                                                 |
| **Latency profile**  | ⚙️ Low and tunable; your backend controls chunking, buffering, and downstream delivery.                                 |
| **You build**        | 🖥️ Server SDK session, 🎙️ audio pipeline, 🔀 transport, 🧩 client message feed, recovery, and observability.          |
| **You do not build** | 🚫 Avatar rendering or motion generation. AvatarKit renders locally; Motion Server generates motion data.               |
| **Best first demo**  | 🧪 [Backend Mode demos](/resources/demo-projects#recommended-starting-points) after you understand the Server SDK role. |
| **Client support**   | 🌐 Web / 🍎 iOS / 🤖 Android / 📱 Flutter                                                                               |

## Core backend flow

```mermaid theme={null}
flowchart LR
    A["Your backend<br/>(ASR / LLM / TTS)"] -->|avatar speech audio| B["Server SDK"]
    B -->|connects to| C["Motion Server"]
    C -->|encoded audio payloads + motion data payloads| B
    B -->|your chosen transport| D["AvatarKit client"]
    D -->|yieldAudioData / yieldFramesData| E["Local avatar rendering"]
```

The Server SDK is the required piece in this path. The client does not connect to Motion Server directly, and it usually does not hold a Spatius Session Token. Instead, the client receives encoded audio payloads and motion data payloads from your backend and feeds them into AvatarKit with `yieldAudioData()` and `yieldFramesData()`.

<Note>
  Do not confuse a Backend Mode server with a Direct Mode token endpoint. A Direct Mode token endpoint only mints short-lived Session Tokens. A Backend Mode server is part of the runtime: it owns the audio pipeline, connects to Motion Server with the Server SDK, and transports encoded audio payloads + motion data payloads to clients.
</Note>

## SDK roles

| SDK surface                                | Runs in                              | What it does                                                                                                                                    |
| ------------------------------------------ | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| **[Server SDK](/backend-mode/server-sdk)** | Your backend                         | Authenticates with Spatius, connects to Motion Server, sends avatar speech audio, and receives encoded audio payloads and motion data payloads. |
| **[Client SDK](/backend-mode/client-sdk)** | Web, iOS, Android, or Flutter client | Receives encoded audio payloads and motion data payloads from your backend and renders them locally.                                            |

## Requirements

| Requirement              | Why it matters                                                                                                                                                 |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Server SDK**           | Required. Your backend uses it to authenticate, connect to Motion Server, and provide encoded audio payloads and motion data payloads for clients.             |
| **API Key**              | Stored only on your backend. Used by the Server SDK, never by client apps.                                                                                     |
| **App ID and Avatar ID** | Identify the app and avatar your clients render.                                                                                                               |
| **Downstream transport** | Your backend must deliver encoded audio payloads and motion data payloads to clients. This can be your own WebSocket, LiveKit, or another supported transport. |

## Transport options

Transport is a second decision inside Backend Mode Integration. **LiveKit is optional.**

| Transport                           | Use when                                                                                                                                                            | Guide                                                                                  |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| **Your own WebSocket**              | You want the simplest Backend Mode shape: your backend relays encoded audio payloads and motion data payloads directly to clients. This is the reference demo path. | [Your own transport](/backend-mode/own-transport)                                      |
| **LiveKit as downstream transport** | You already want LiveKit between your backend and clients, but you are not using LiveKit Agents as the agent framework.                                             | [Backend Mode with LiveKit](/backend-mode/with-livekit)                                |
| **Agora as downstream transport**   | You already want Agora between your backend and clients, but you are not using Agora Convo AI as the agent platform.                                                | [Python SDK Agora Egress Mode](/sdk-reference/python-sdk/python-sdk#agora-egress-mode) |

<Note>
  **Backend Mode does not require LiveKit or Agora.** The required integration point is the Server SDK on your backend. RTC providers are downstream transport options after your backend receives data from Motion Server.
</Note>

## Architecture variants

### Your own transport

<Frame>
  <HostedModeOwnTransportDiagram />
</Frame>

> Your backend receives encoded audio payloads and motion data payloads from the Server SDK and relays them to clients over your own WebSocket or network layer.

### Third-party realtime transport

<Frame>
  <HostedModeRealtimeTransportDiagram />
</Frame>

> Your backend still uses the Server SDK. The RTC provider only carries the downstream audio payloads and motion data payloads between your backend and your clients.

## Next steps

<CardGroup cols={2}>
  <Card title="Server SDK role" icon="server" href="/backend-mode/server-sdk">
    Backend SDK responsibility and language references.
  </Card>

  <Card title="Client SDK role" icon="monitor" href="/backend-mode/client-sdk">
    Client-side rendering responsibility.
  </Card>

  <Card title="Browse all demos" icon="github" href="/resources/demo-projects">
    Run reference implementations for Web, iOS, Android, and Flutter.
  </Card>

  <Card title="Your own transport" icon="route" href="/backend-mode/own-transport">
    Direct WebSocket relay between your backend and clients.
  </Card>
</CardGroup>
