Event Reference
Reference for subscribing to connection, conversation, speech, action, session, media, and acknowledgment events in the Convai Web SDK.
modelOutput, modelOutputProtocolError, and v2 tool-call behavior describe an opt-in candidate implementation. They do not confirm production availability or publication in the current @convai/web-sdk npm release. Confirm the exports in your installed package.
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.
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
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?