Events
Listen to conversation, avatar, and world events from an Experience.
Overview
Register handlers on an Experience instance to observe conversation, avatar, and
world activity.
Startup
ready reports that the player visuals are mounted and ready. started reports that the player-owned startup button was clicked and audio and session startup completed.
const experience = await Experience.startSession({
experienceId: 'exp_…'
});
experience.on('ready', ({ manifest }) => {
console.log('Player visuals ready', manifest.experience.mode);
});
experience.on('started', ({ mode }) => {
console.log('Audio and session started in', mode, 'mode');
});
await experience.attach({ container });
ready includes the resolved manifest. started includes the experience
mode. Both replay asynchronously for handlers registered after the event. The onStart option on Experience.startSession() is a convenience callback for startup completion.
Speech and transcripts
Emitted during speak() sessions, manual or automatic listening, and custom processor
conversation. Partial transcript revisions include monotonic revision and optional delta. Only updates with isFinal: true commit a user message to
conversation history.
experience.on('userTranscript', (update) => {
if (!update.isFinal) {
liveCaptionEl.textContent = update.text;
return;
}
liveCaptionEl.textContent = update.text;
commitUtterance(update.utteranceId, update.text);
});
experience.on('userSpeechStarted', () => micIndicator.classList.add('active'));
experience.on('userSpeechEnded', () => micIndicator.classList.remove('active')); experience.on('characterSpeechStarted', (event) => {
console.log('Speaking', event.characterId, event.text, event.source);
});
experience.on('characterSpeechEnded', (event) => {
console.log('Speech ended', event.reason, event.durationMs);
});
experience.on('conversationUpdate', (conversation) => {
console.log('History length', conversation.length);
});
experience.on('listeningState', (listening) => {
console.log('Mic gate', listening);
}); Custom conversation processor
When you supply conversationProcessor on startSession(), processor
failures surface as conversationProcessorError. The managed LLM is not used as a
fallback.
experience.on('conversationProcessorError', ({ utteranceId, message }) => {
console.error('Processor failed for', utteranceId, message);
// Retry, speak a fallback line, or show host UI.
}); Conversation (managed and custom mode)
experience.on('message', (message) => {
console.log(message.role, message.text, message.source);
});
experience.on('modeChange', (mode) => {
// 'listening' | 'speaking' | 'thinking'
console.log('Session mode', mode);
}); Lip-sync, expressions, and body animation run inside the hosted player. Integrators do not receive viseme or animation keyframe events — use characterSpeechStarted / characterSpeechEnded when you need to sync
your UI with speech.
World
experience.on('stateUpdate', (patch) => { /* structured state change */ });
experience.on('locationChange', ({ locationId }) => { });
experience.on('characterEnter', ({ characterId }) => { });
experience.on('characterExit', ({ characterId }) => { });
experience.on('close', ({ reason, returnUrl }) => { }); Event reference
| Event | Payload | Description |
|---|---|---|
ready | { manifest } | Player visuals are mounted and ready |
started | { mode } | Player startup click, audio unlock, and session startup completed |
userTranscript | { utteranceId, text, revision, isFinal, delta? } | Partial and final STT updates. Ephemeral until isFinal: true. |
userSpeechStarted | { utteranceId? } | VAD detected speech activity (auto mode telemetry) |
userSpeechEnded | { utteranceId? } | VAD detected end of speech; final text may arrive after this event |
characterSpeechStarted | { speechId, turnId, characterId, text, source } | Character began speaking (speak, opening, or llm) |
characterSpeechEnded | { speechId, turnId, characterId, text, source, durationMs?, reason } | Character speech finished or was interrupted |
conversationUpdate | ConversationMessage[] | Immutable snapshot of in-session conversation history |
listeningState | boolean | Manual listening gate opened (true) or closed (false) |
message | ConversationMessage | Durable user or assistant message committed to session history |
modeChange | listening | speaking | thinking | Session activity mode for UI sync |
conversationProcessorError | { utteranceId, message } | Browser conversationProcessor threw or rejected |
stateUpdate | State patch | Structured world state change from server |
close | { reason, returnUrl? } | Session ended by user or programmatically |