The complete config object you pass to AvatarProvider, field by field — and where mobile differs from web.
React Native and web share the same configuration type. The only required pieces are how to authenticate and which avatar to load; everything else is optional.
It splits into two halves: session wiring (how this session runs) at the top
level, and the agent definition (what the avatar is) under avatar.
Use getSessionToken for production — never ship a live key in your app.
Bundles can be inspected, so any key inside one is effectively public. The
apiKey path is allowed for local development but accepts test keys only
(af_test_*); live keys are rejected by the server.
Everything not in this table behaves identically on both platforms.
| Feature | On React Native |
|---|---|
| thinkingIndicator | Not available. React Native ships no built-in indicator — read useAvatar().isResponseSlow and render your own. |
| connectTone.src | Ignored. A custom tone file is web-only; React Native falls back to the built-in tone and logs a warning. |
| turnTaking.spacebar | Ignored — there is no spacebar. Push-to-talk itself works normally, via the button. |
| Picture-in-picture | Not available. The camera self-view and hideCameraPreview work as on web; the PiP layout swap does not. |
| deployId | Not a supported mobile path. Mint session tokens on your backend instead. |
| Styling props | Native takes style / captionStyle / statusBannerStyle as ViewStyle. There is no className. |
| Camera permission | A native permission, declared through the Expo config plugin. See Permissions. |
| Prop | Type | Default | Description |
|---|---|---|---|
getSessionTokenRequired | () => Promise<string> | No default | Callback returning a fresh, single-use session token. Invoked on every connect. Required for production; either this or apiKey (dev) must be supplied. |
apiKeyOptional | string | No default | Test key (af_test_*) for local development only. Live keys (af_live_*) are rejected — use getSessionToken for production. |
modeOptional | "call" | "tts" | "audio" | "player" | "call" | Operating mode. Changing this at runtime triggers a full session reset. |
turnTaking.modeOptional | "auto" | "push-to-talk" | "auto" | Who decides a turn is over: the server's endpointer, or the user holding a button. Call mode only. |
controls.enabledOptional | boolean | false | Show the built-in start / stop / mute bar. Hidden unless explicitly true. |
controls.stopSpeakingOptional | boolean | false | Add a "stop talking" button to the built-in bar, shown only while the avatar speaks. |
perception.cameraOptional | boolean | false | Allow the avatar to see. Opt-in, and even then the camera opens just-in-time when the server asks — never on connect. |
transcript.enabledOptional | boolean | false | Assemble a live transcript. Off means none is built at all. |
transcript.captionsOptional | boolean | true | Render the built-in caption overlay. False keeps the data without the UI. |
transcript.positionOptional | CaptionPosition | "bottom-center" | Anchor for the caption overlay — six positions. |
transcript.maxEntriesOptional | number | 50 | Transcript lines retained. |
statusBanner.enabledOptional | boolean | true | Built-in connectivity banner, driven by live stream health. It only appears when something is wrong. |
statusBanner.positionOptional | StatusBannerPosition | "bottom-left" | Anchor corner. Corners only. |
connectTone.enabledOptional | boolean | false | Play a ringback tone while the session connects. |
connectTone.loopOptional | boolean | true | Repeat the tone until the connect completes. |
connectTone.volumeOptional | number | 0.4 | 0–1. |
connectTone.fadeOutMsOptional | number | 350 | Fade-out on stop. A hard cut clicks. |
avatar.avatarIdRequired | string | No default | Which character to load. Use "default" for the public demo avatar, or publish your own and use its ID. |
avatar.systemPromptOptional | string | No default | Per-session context — who the end user is and why they are here. Call mode. Not the avatar's identity: set that on the platform. |
avatar.languagesOptional | "auto" | AvatarLanguage[] | No default | Languages the conversation may use. "auto" lets the server detect and switch. Omitted means English. |
avatar.brainOptional | AvatarBrain | No default | Which model powers the conversation: { provider, model?, useOwnBrain? }. |
avatar.voiceSettingsOptional | AvatarVoiceSettings | No default | Voice provider, voice, and tuning. See below. |
avatar.greetingOptional | GreetingConfig | No default | An opening line spoken once the session goes live: { enabled, message?, language? }. |
avatar.layoutOptional | Record<string, string> | No default | Platform-agnostic layout hints (e.g. fit, alignment) interpreted by the native renderer. |
debugOptional | boolean | false | Verbose console logging. Disable before shipping. |
For production, your app calls your backend, which exchanges your live key for a short-lived token.
The callback runs on every connect — initial and every reconnect — and tokens are single-use, so mint a fresh one each time. See Authentication for backend implementations.
provider is open-ended — the server validates it, so a newly supported vendor
works without an SDK release. useOwnBrain is a switch, not a carrier: the key
is resolved server-side and never passes through the app. See
Bring your own keys.
Check your TTS provider's own documentation for valid ranges of voiceSpeed,
voiceStability, and similarityBoost — the SDK passes them straight through.
An opening line spoken once the session goes live. You supply text, not audio.
Greeting languages: en, es, fr, de, hi, ru, pt, ja, it.
If you are migrating from an older integration that passed a pre-rendered
greeting.job at the top level, move it to avatar.greeting and pass a
message string instead.
Supported: en, es, fr, de, hi, ru, pt, ja, it, nl. Omitting
the field means English.
Platform-agnostic key/value pairs interpreted by the native renderer.
Voice fallback. If no valid voice is selected at publish time or in code, the avatar falls back to the default voice for the chosen provider — on both ElevenLabs and Inworld. An invalid voice ID does the same. The avatar always speaks.
Changing auth (getSessionToken / apiKey) or mode triggers a full session
reset. Other fields update without one.
Memoise the config object. A new object literal on every render is a new config every render, and the provider will keep restarting the session.