Skip to content

Events

Complete event reference — every event type, its payload, and when it fires.

How events work

CompositeVoice uses an event-driven architecture. Subscribe with on(), unsubscribe with off(), or listen once with once(). The on() method returns an unsubscribe function for convenience.

// Subscribe
voice.on('agent.stateChange', ({ state }) => { ... });

// Unsubscribe via returned function
const unsubscribe = voice.on('transcription.speechFinal', ({ text }) => { ... });
unsubscribe();

// Unsubscribe via off()
const handler = ({ text }) => { ... };
voice.on('transcription.speechFinal', handler);
voice.off('transcription.speechFinal', handler);

// Listen once
voice.once('agent.ready', () => { ... });

// Wildcard — receive every event
voice.on('*', (event) => {
  console.log(`[${event.type}]`, event);
});

Every event extends BaseEvent, which includes a timestamp (Unix ms) and an optional metadata record.

Agent events

EventPayloadDescription
agent.ready{}Pipeline initialized, ready to start
agent.stateChange{ state: AgentState, previousState: AgentState }State transition occurred
agent.error{ error: Error, recoverable: boolean, context?: string }Top-level pipeline error

AgentState values: 'idle''ready''listening''thinking''speaking' → back to 'listening' (or 'error')

Typical flow:

idle → ready → listening → thinking → speaking → listening → ...

Transcription events

EventPayloadDescription
transcription.start{}STT provider began listening for speech
transcription.interim{ text, confidence? }Partial recognition result (updates as user speaks)
transcription.final{ text, confidence? }Confirmed recognition segment
transcription.speechFinal{ text, confidence? }End-of-utterance detected — triggers LLM generation
transcription.preflight{ text, confidence? }Early end-of-speech signal (DeepgramFlux only) — triggers eager LLM
transcription.error{ error: Error, recoverable: boolean }STT provider error

The pipeline sends speechFinal text to the LLM. interim events update in real time as the user speaks. Multi-segment providers (Deepgram) may emit several transcription.final events for a single utterance; only the last one is followed by transcription.speechFinal.

LLM events

EventPayloadDescription
llm.start{ prompt }Generation started
llm.chunk{ chunk, accumulated }Text token received (streaming); accumulated holds the full response so far
llm.complete{ text, tokensUsed? }Full response complete
llm.error{ error: Error, recoverable: boolean }LLM provider error

LLM text streams to TTS as it arrives. Each llm.chunk forwards its text to the TTS provider for incremental synthesis (when using a live/WebSocket TTS provider).

TTS events

EventPayloadDescription
tts.start{ text }Synthesis started
tts.audio{ chunk: AudioChunk }Audio chunk received
tts.metadata{ metadata: AudioMetadata }Audio format information (sample rate, encoding, channels)
tts.complete{}Synthesis finished (playback may still be in progress)
tts.error{ error: Error, recoverable: boolean }TTS provider error

Audio events

EventPayloadDescription
audio.capture.start{}Microphone capture started
audio.capture.stop{}Microphone capture stopped
audio.capture.error{ error: Error }Microphone access or capture error
audio.playback.start{}Audio playback started
audio.playback.end{}Audio playback finished
audio.playback.error{ error: Error }Playback error

Event flow diagram

User speaks
  → transcription.start
  → transcription.interim (repeating)
  → transcription.final
  → transcription.speechFinal
      → agent.stateChange { state: 'thinking' }
      → llm.start
      → llm.chunk (repeating)
          → tts.start
          → tts.audio (repeating)
              → audio.playback.start
              → agent.stateChange { state: 'speaking' }
      → llm.complete
      → tts.complete
      → audio.playback.end
      → agent.stateChange { state: 'listening' }

Error events

All error events include an error property and a recoverable boolean. Agent-level errors (agent.error) also carry an optional context string identifying the subsystem that failed (e.g., 'initialization', 'pipeline').

The SDK defines CompositeVoiceError as the base error class. Check error.code for a machine-readable identifier ('PROVIDER_INIT_ERROR', 'TIMEOUT_ERROR', 'WEBSOCKET_ERROR', etc.) and error.recoverable to determine if the error is transient.

voice.on('agent.error', ({ error, recoverable, context }) => {
  if (error instanceof CompositeVoiceError) {
    console.error(`[${error.code}] ${error.message}`);
  }
  if (!recoverable) {
    showFatalError(error.message);
  }
});

© 2026 CompositeVoice. All rights reserved.

Font size
Contrast
Motion
Transparency