Wrap your app once. It connects to the avatar, holds the session, and shares it with every component inside.
AvatarProvider is where you connect and configure. Give it a config object —
how to authenticate, which avatar to load, and how the session should run — and
it makes the avatar available to <Avatar /> and the useAvatar hook anywhere
below it.
Define config outside the component, or memoise it. A fresh object
literal on every render is a fresh config on every render, and the provider
will keep restarting the session. Use useMemo when any part of it is dynamic.
Provide exactly one of these three. Supplying more than one is a TypeScript error.
| Method | Runs where | Use it for |
|---|---|---|
getSessionToken | Your backend mints | Production. Your key never leaves your server. |
deployId | Browser, public | Framer, landing pages, demos — anywhere with no backend. |
apiKey | Browser, dev only | Local development, with a test key. Live keys are rejected. |
A session token is a short-lived credential good for a single connection. You give the SDK a function, not a token string, so it can fetch a fresh one on every connect — the first time and on every reconnect.
Contract:
Promise<string> resolving to a non-empty token.SESSION_TOKEN_FETCH_FAILED
and aborts before any WebSocket opens.Your backend exchanges your live key for a token. See Authentication for cURL, Node, Next.js, and Python implementations.
Keep your live key in a server-only environment variable — no
NEXT_PUBLIC_ prefix or equivalent. Anything prefixed for client exposure is
compiled into your bundle.
A deployment ID (dep_…) is a public credential scoped to one avatar in one
mode, locked to the domains you authorize and capped by a monthly minute budget.
Create one in Platform → open an avatar → Deploy → Framer → New deployment (paid plans only). The same ID powers the Framer component.
A deployId is safe to ship to the browser. Unlike an API key it cannot be
repointed at another avatar, cannot work on a domain you did not authorize, and
cannot spend beyond its budget.
This path accepts test keys only. Live keys (af_live_*) are rejected by
the server, and there is no flag to override that. See
API keys.
AvatarProvider takes a single config prop of type AvatarConfig. Below is
the shape; every field, type, and default is in the
Configuration Reference.
| Prop | Type | Default | Description |
|---|---|---|---|
configRequired | AvatarConfig | No default | The full configuration object. See the Configuration Reference for every field. |
childrenRequired | React.ReactNode | No default | Your app. <Avatar />, useAvatar(), and useAvatarEvent() work anywhere below. |
call for two-way voice, tts to speak text you send, audio to lip-sync
audio you supply. See
Modes.
The SDK ships a start / stop / mute bar for call mode. It is off by
default — opt in, or build your own with
useAvatar.
stopSpeaking adds an interrupt button that appears only while the avatar is
talking.
Context for this session — who your user is and what they came for. It is sent once when the session opens and applies to that conversation only.
Keep it short. Because it changes from session to session it cannot be cached the way the avatar's own configuration is, and it is re-sent on every turn of the call.
This is not where an avatar's personality or reference material goes. Set those
on the avatar itself in the platform — they persist across every session, hold
far more text, and stay in effect when you leave systemPrompt unset.
An opening line spoken once the session goes live. Give it text, or omit
message for the built-in line in the chosen language.
Greetings are text now — you do not supply audio. 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.
Voice, brain, language, and lip-sync settings can come from two places:
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.
Don't nest providers unless you deliberately want two independent sessions
running at once. Each AvatarProvider opens its own connection.
Client components only. AvatarProvider, useAvatar, and useAvatarEvent
run in the browser. Mark any file that uses them "use client".
Changing auth (getSessionToken / apiKey / deployId) or mode at
runtime triggers a full session reset. Other fields — systemPrompt, voice
settings, overlays — update without one.