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

# Client Lifecycle

> SDK initialization, avatar loading, connection management, and resource cleanup.

AvatarKit follows a four-stage lifecycle: **Initialize → Load → Connect → Cleanup**. Each stage maps to a core component.

## Overview

<div style={{ backgroundColor: '#ffffff', border: '1px solid #e5e7eb', borderRadius: 12, padding: 12 }}>
  ```mermaid actions={false} theme={null}
  ---
  config:
    "look": "handDrawn"
    "theme": "base"
    "themeVariables":
      "background": "#ffffff"
      "textColor": "#111827"
      "lineColor": "#64748b"
      "primaryColor": "#e8f4fd"
      "primaryTextColor": "#111827"
      "primaryBorderColor": "#2196F3"
      "secondaryColor": "#f3e5f5"
      "secondaryTextColor": "#111827"
      "secondaryBorderColor": "#9C27B0"
      "tertiaryColor": "#fff3e0"
      "tertiaryTextColor": "#111827"
      "tertiaryBorderColor": "#FF9800"
      "clusterBkg": "#f8fafc"
      "clusterBorder": "#cbd5e1"
      "edgeLabelBackground": "#ffffff"
      "actorBkg": "#e8f4fd"
      "actorBorder": "#2196F3"
      "actorTextColor": "#111827"
      "noteBkgColor": "#fff7ed"
      "noteTextColor": "#111827"
      "signalColor": "#64748b"
      "signalTextColor": "#111827"
  ---
  graph LR
      A["<b>INITIALIZE</b><br/>AvatarSDK.initialize()"]
      B["<b>LOAD</b><br/>AvatarManager.load()"]
      C["<b>RENDER</b><br/>AvatarView(avatar)"]
      D["<b>CONNECT</b><br/>controller.start()"]

      A -->B
      B -->C
      C -->D


  ```
</div>

| Stage      | Component          | What happens                                                                                              |
| ---------- | ------------------ | --------------------------------------------------------------------------------------------------------- |
| Initialize | `AvatarSDK`        | Configures app ID, environment, audio format, and driving mode. Must be called once before any other API. |
| Load       | `AvatarManager`    | Downloads and caches avatar assets. Returns an `Avatar` instance.                                         |
| Render     | `AvatarView`       | Creates the rendering surface and its associated `AvatarController`.                                      |
| Connect    | `AvatarController` | Opens a WebSocket to the driving service. The avatar begins responding to audio.                          |

## Stage 1: Initialize

Call `AvatarSDK.initialize()` once at app startup. This sets global configuration that all subsequent operations depend on.

<Tabs>
  <Tab title="Web">
    ```typescript theme={null}
    await AvatarSDK.initialize({
      appId: 'YOUR_APP_ID',
      audioFormat: { channelCount: 1, sampleRate: 16000 },
      drivingServiceMode: 'sdk',
    });
    ```
  </Tab>

  <Tab title="iOS">
    ```swift theme={null}
    AvatarSDK.initialize(
        appID: "YOUR_APP_ID",
        configuration: Configuration(
            environment: .intl,
            audioFormat: AudioFormat(sampleRate: 16000),
            drivingServiceMode: .sdk,
            logLevel: .warning
        )
    )
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    AvatarSDK.initialize(
        context = applicationContext,
        appId = "YOUR_APP_ID",
        configuration = Configuration(
            environment = Environment.Intl,
            audioFormat = AudioFormat(16000),
            drivingServiceMode = DrivingServiceMode.SDK,
            logLevel = LogLevel.INFO
        )
    )
    ```
  </Tab>
</Tabs>

Set `AvatarSDK.sessionToken` before connecting. The token authenticates your session with the driving service.

## Stage 2: Load Avatar

Use `AvatarManager` to download and cache avatar assets. Loading is asynchronous and supports progress tracking.

<Tabs>
  <Tab title="Web">
    ```typescript theme={null}
    const avatar = await AvatarManager.load('AVATAR_ID', (progress) => {
      console.log('Loading:', progress);
    });
    ```
  </Tab>

  <Tab title="iOS">
    ```swift theme={null}
    let avatar = try await AvatarManager.shared.load(id: "AVATAR_ID") { progress in
        print("Loading: \(progress)")
    }
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    val avatar = AvatarManager.load("AVATAR_ID") { progress ->
        Log.d("Avatar", "Loading: $progress")
    }
    ```
  </Tab>
</Tabs>

Loaded assets are cached locally. Subsequent loads for the same avatar ID skip the download. Use `AvatarManager.clear(id:)` or `clearAll()` to manage cache.

## Stage 3: Render

Create an `AvatarView` with the loaded avatar. The view automatically creates an `AvatarController` you can access to manage the connection and send audio.

<Tabs>
  <Tab title="Web">
    ```typescript theme={null}
    const avatarView = new AvatarView(avatar, containerElement);
    const controller = avatarView.controller;
    ```
  </Tab>

  <Tab title="iOS">
    ```swift theme={null}
    let avatarView = AvatarView(avatar: avatar)
    let controller = avatarView.controller
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    val avatarView = AvatarView(context)
    avatarView.init(avatar, lifecycleScope)
    val controller = avatarView.controller
    ```
  </Tab>
</Tabs>

## Stage 4: Connect and Interact

Call `controller.start()` to open the WebSocket connection. Once connected, send audio with `controller.send()` (SDK Mode) or `controller.yield()` (Host Mode).

<div style={{ backgroundColor: '#ffffff', border: '1px solid #e5e7eb', borderRadius: 12, padding: 12 }}>
  ```mermaid actions={false} theme={null}
  ---
  config:
    "look": "handDrawn"
    "theme": "base"
    "themeVariables":
      "background": "#ffffff"
      "textColor": "#111827"
      "lineColor": "#000000"
      "primaryColor": "#e8f4fd"
      "primaryTextColor": "#111827"
      "primaryBorderColor": "#2196F3"
      "secondaryColor": "#f3e5f5"
      "secondaryTextColor": "#000000"
      "secondaryBorderColor": "#9C27B0"
      "tertiaryColor": "#fff3e0"
      "tertiaryTextColor": "#111827"
      "tertiaryBorderColor": "#FF9800"
      "clusterBkg": "#f8fafc"
      "clusterBorder": "#cbd5e1"
      "edgeLabelBackground": "#ffffff"
      "actorBkg": "#e8f4fd"
      "actorBorder": "#2196F3"
      "actorTextColor": "#111827"
      "noteBkgColor": "#fff7ed"
      "noteTextColor": "#111827"
      "signalColor": "#64748b"
      "signalTextColor": "#111827"
  ---
  sequenceDiagram
      autonumber
      participant C as Controller
      participant S as Connection/Voice State

      C->>S: controller.start()
      Note right of S: onConnectionState: connecting
      S-->>C: onConnectionState: connected
      S-->>C: onConversationState: idle
      
      rect rgb(240, 240, 240)
          Note over C,S: Audio Streaming
          C->>S: send(audio, end: false)
          S-->>C: onConversationState: playing
          C->>S: ... multiple chunks ...
          C->>S: send(audio, end: false)
          S-->>C: onConversationState: playing
          C->>S: send(audio chunk, end: true)
      end

      S-->>C: onConversationState: playing
      S-->>C: onConversationState: idle
  ```
</div>

Call `controller.interrupt()` to stop the current playback immediately. Call `controller.close()` when done.

## Cleanup

Clean up resources when the avatar is no longer needed.

<Tabs>
  <Tab title="Web">
    ```typescript theme={null}
    avatarView.dispose();
    ```
  </Tab>

  <Tab title="iOS">
    ```swift theme={null}
    // AvatarView automatically releases resources when removed from the view hierarchy.
    // No explicit cleanup call needed.
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={null}
    avatarView.dispose()
    ```
  </Tab>
</Tabs>

<Warning>
  On Web and Android, always call `avatarView.dispose()` when the view is no longer needed. On iOS, resources are released automatically when the view is deallocated.
</Warning>
