For the complete documentation index, see llms.txt. This page is also available as Markdown.

Event Reference

Reference for subscribing to connection, conversation, speech, action, session, media, and acknowledgment events in the Convai Web SDK.

const unsub = client.on('botReady', () => {
  console.log('Bot is ready');
});

// Later
unsub();
// or
client.off('botReady', handler);

Connection events

connect

Fires when the WebRTC/WebSocket transport connects. The bot may not be ready yet — wait for botReady before sending messages.

client.on('connect', () => {
  console.log('Transport connected');
});

botReady

Fires when the character has confirmed it is ready to receive messages. This is the correct signal to start interacting.

disconnect

Fires when the session ends. Receives a DisconnectReason code.

stateChange

Fires whenever any part of ConvaiClientState changes. Use this for UI updates.

error

Fires on connection errors or bot-ready timeout.


Conversation events

conversationStart

Fires when a new conversation turn begins — either when the user sends a text message or starts speaking.

turnEnd

Fires when the bot finishes speaking for a turn.

message

Fires for each new ChatMessage added to the conversation. The full history is also available in client.chatMessages.

messagesChange

Fires whenever the message array changes (includes message updates mid-stream).

userTranscriptionChange

Fires repeatedly as the user speaks, providing live speech-to-text.


Speaking events

speakingChange

Fires when the bot starts or stops speaking.

botOutput

Fires for each aggregated output chunk from the bot. Includes both spoken and unspoken text.

botTtsStarted

Fires when the TTS engine starts producing audio.

botTtsStopped

Fires when the TTS engine finishes.

botTtsText

Fires word-by-word as the bot speaks, synchronized with TTS audio.


Microphone events

userMuteStarted

Fires when the server-side mutes the user's microphone (e.g., when the bot starts speaking to prevent echo).

userMuteStopped

Fires when the server un-mutes the user's microphone.


Blendshape / lipsync events

These require enableLipsync: true in config.

blendshapes

Fires for each incoming blendshape chunk (10 frames by default). Use client.blendshapeQueue instead of handling raw chunks directly.

blendshapeStatsReceived

Fires when the server sends end-of-turn blendshape statistics. Signals that no more frames are coming for this turn.


Action events

actionResponse requires semantic affordances or v2 tool declarations. modelOutput requires modelOutputVersion: 2 and can carry text even when no Actions contract is active.

actionResponse

Fires on the legacy compatibility event surface. Under action protocol v1, the ordered array contains semantic actions. Under action protocol v2, it can also contain correlated tool calls. The SDK does not execute or schedule them.

When modelOutputVersion: 2 is selected, the SDK suppresses actionResponse to prevent duplicate handling. Use modelOutput instead.

modelOutput

Fires for each valid canonical v2 output envelope when modelOutputVersion: 2 was selected. The SDK preserves item order and drops a repeated output_id; it does not execute items or guarantee exactly-once tool execution.

Use validated items for rendering and execution. Treat raw as diagnostics only. Distinct envelopes can share a logical_turn_id, and final: true finalizes one envelope rather than the entire logical turn.

modelOutputProtocolError

Fires when a selected v2 model-output envelope is malformed or contains an unsupported item. The parser rejects the whole envelope.

The code is currently "invalid_model_output". See Actions for configuration, tool results, and limits.


Server response events

serverResponse

Fires as an acknowledgment for every message you send to the server.

For action-result, extras.tool_call_id correlates the acknowledgment and extras.idempotent reports whether an identical result was already accepted. A void return from sendActionResult() is not an acknowledgment.

interactionCreated

Fires early in the session lifecycle — before botReady — when the server assigns a unique interaction ID. This is the first message that carries both interactionId and characterSessionId, making it the right place to capture identifiers for analytics, logging, or session resumption.

Field
Type
Description

interactionId

string

Unique identifier for this interaction. Use for analytics or log correlation.

characterSessionId

string

Character session identifier. Same value as client.characterSessionId after connect.

interactionCreated fires once per connect() call. If you reconnect, a new interactionId is issued.


Session events

idleWarning

Fires before the server disconnects an idle session.

llmNoResponse

Fires when the LLM deliberately chose not to respond (e.g., because the input didn't warrant a reply).


metrics

Fires with performance data after each turn.


Audio track (WebSocket transport)

botAudioTrack

Fires when a new audio track is available from the bot (WebSocket transport only). Attach to an <audio> element to play.


Event quick-reference

Event
Payload
When

connect

—

Transport connected

botReady

—

Bot confirmed ready

disconnect

DisconnectReason

Session ended

stateChange

ConvaiClientState

Any state change

error

Error

Connection or timeout error

conversationStart

{ sessionId, userMessage, timestamp }

New turn begins

turnEnd

{ sessionId, duration, timestamp }

Bot finishes speaking

message

ChatMessage

New message

messagesChange

ChatMessage[]

History updated

userTranscriptionChange

string

Live STT update

speakingChange

boolean

Bot speaking state

botOutput

{ text, spoken, aggregatedBy }

Aggregated bot chunk

botTtsStarted

—

TTS begins

botTtsStopped

—

TTS ends

botTtsText

{ text }

Word-by-word TTS

userMuteStarted

—

Server muted user mic

userMuteStopped

—

Server un-muted user mic

blendshapes

raw data

Blendshape chunk

blendshapeStatsReceived

stats

Turn end stats

actionResponse

{ actions }

Compatibility action projection

modelOutput

ModelOutputMessage

Valid canonical v2 envelope

modelOutputProtocolError

ModelOutputProtocolError

Invalid v2 envelope

serverResponse

ServerResponse

Server acknowledgment

interactionCreated

{ interactionId, characterSessionId }

Session ID assigned

idleWarning

{ remainingSeconds }

Idle timeout warning

llmNoResponse

—

LLM chose not to respond

metrics

data

Turn performance data

botAudioTrack

MediaStreamTrack

New audio track (WS transport)

Last updated

Was this helpful?