> ## Documentation Index
> Fetch the complete documentation index at: https://docs.rtvi.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Callbacks and events

A voice client exposes callback hooks that can be defined on the [constructor](./client-constructor).

Callbacks can be configured as part of your voice client constructor:

```typescript
const voiceClient = new VoiceClient({
  // ...
  callbacks: {
    onBotReady: bot_ready_handler_func,
  },
});
```

## State and connectivity

<ParamField path="onTransportStateChanged" type="state:TransportState">
  Provides a `TransportState` string representing the connectivity state of the local client.

  One of: `idle` | `initializing` | `initialized` | `authenticating` | `connecting` | `connected` | `ready` |  `disconnected` | `error`

  See [transports](./transports) for state explanation.
</ParamField>

<ParamField path="onConnected">
  Local user successfully established a connection to the transport.
</ParamField>

<ParamField path="onDisconnected">
  Local user disconnected from the transport, either intentionally by calling
  `voiceClient.disconnect()` or due to an error.
</ParamField>

<ParamField path="onBotConnected">
  Bot connected to the transport and is configuring.

  Note: bot connectivity does not infer that its pipeline is yet ready to run. Please use `onBotReady` instead.
</ParamField>

<ParamField path="onBotReady" type="botReadyData:BotReadyData">
  The bot has been instantiated, its pipeline is configured, and it is receiving user media and interactions.

  This method is passed a `BotReadyData` object, which contains a `config VoiceClientConfigOption[]` array and the RTVI `version` number.

  It is recommended to hydrate your client with the passed config in case the bot alters any configuration based on its implementation.

  Since the bot is remote and may be using a different version of RTVI than the client, you can use the passed `version` string to check for compatibility.
</ParamField>

<ParamField path="onBotDisconnected">
  Bot disconnected from the transport.

  This may occur due to session expiry, a pipeline error or because the local participant left the session.
</ParamField>

## Messages and errors

<ParamField path="onGenericMessage" type="data:unknown">
  If the client receives an unknown message type from the transport (see
  [messages and events](./messages)), it can be handled here.
</ParamField>

<ParamField path="onMessageError" type="message:VoiceMessage">
  Response error when an action fails or an unknown message type is sent from
  the client.
</ParamField>

<ParamField path="onError" type="message:VoiceMessage">
  Error signalled by the bot. This could be due to a malformed config update or
  an unknown action dispatch or the ability to complete the requested action.
</ParamField>

## Configuration

<ParamField path="onConfigUpdated" type="config:VoiceClientConfigOption[]">
  Sent when the bots configuration changes. This is most likely in response to a user `updateConfig` action, but can occur within a bots pipeline.

  It's recommended to hydate the client config with the passed config.
</ParamField>

<ParamField path="onConfigDescribe" type="configDescription:unknown">
  A list of available configuration options for each service. Sent in response to a user `describeConfig()` call.

  ```js
  "config": [
    {
        "service": "llm",
        "options": [
  	      { "name": "model", "type": "string" },
  	      { "name": "messages", "type": "array" },
  	      ...
        ]
    },
    {
        "service": "tts",
        "options": [
  	      { "name": "voice", "type": "string" },
  	      ...
        ]
    },
    ...
  ]
  ```
</ParamField>

## Media and devices

<ParamField path="onAvailableMicsUpdated" type="mics:MediaDeviceInfo[]">
  Lists available local media microphone devices. Triggered when a new device
  becomes available or in response to `voiceClient.initDevices()`.
</ParamField>

<ParamField path="onAvailableCamsUpdated" type="cams:MediaDeviceInfo[]">
  Lists available local media camera devices. Triggered when a new device
  becomes available or in response to `voiceClient.initDevices()`.
</ParamField>

<ParamField path="onMicUpdated" type="mic:MediaDeviceInfo">
  User selected a new microphone as their selected/active device.
</ParamField>

<ParamField path="onCamUpdated" type="cam:MediaDeviceInfo">
  User selected a new camera as their selected/active device.
</ParamField>

## Audio and Voice Activity

<ParamField path="onTrackStarted" type="track: MediaStreamTrack, participant:Participant">
  Media track from a local or remote participant was started and playable. Can
  be either an audio or video track.
</ParamField>

<ParamField path="onTrackStopped" type="track: MediaStreamTrack, participant:Participant">
  Media track from a local or remote participant was stopped and no longer
  playable.
</ParamField>

<ParamField path="onLocalAudioLevel" type="level:number">
  Local audio gain level (0 to 1).
</ParamField>

<ParamField path="onRemoteAudioLevel" type="level: number, participant: Participant">
  Remote audio gain level (0 to 1).

  Note: if more than one participant is connected to the transport, the `participant` property details the associated peer.
</ParamField>

<ParamField path="onBotStartedSpeaking">
  The bot started speaking/sending speech audio.
</ParamField>

<ParamField path="onBotStoppedSpeaking">
  The bot stopped speaking/sending speech audio.
</ParamField>

<ParamField path="onUserStartedSpeaking">
  The local user started speaking.

  This method is more reliable than using audio gain and is the result of the bot's VAD (voice activity detection) model. This provides a more accurate result in noisy environments.
</ParamField>

<ParamField path="onUserStoppedSpeaking">
  The local user stopped speaking, indicated by the VAD model.
</ParamField>

## Transcription

<ParamField path="onUserStoppedSpeaking" type="transcript:Transcription">
  Transcribed local user input (both partial and final)
</ParamField>

<ParamField path="onBotTranscript" type="transcript:string">
  Transcribed bot input. Sentence aggregated.
</ParamField>

## Other

<ParamField path="onMetrics" default="data:PipecatMetrics">
  Pipeline data provided by Pipecat. Please see [Pipecat
  documentation](https://docs.pipecat.ai) for more information.
</ParamField>

## Events

RTVI defines the following [standard events](https://github.com/rtvi-ai/rtvi-client-web/blob/main/rtvi-client-js/src/events.ts) that map to messages/actions from the bot to the client.

```javascript
MessageError = "messageError",
Error = "error",

Connected = "connected",
Disconnected = "disconnected",
TransportStateChanged = "transportStateChanged",

ConfigUpdated = "configUpdated",
ConfigDescribe = "configDescribe",
ActionsAvailable = "actionsAvailable",

ParticipantConnected = "participantConnected",
ParticipantLeft = "participantLeft",
TrackStarted = "trackStarted",
TrackedStopped = "trackStopped",

AvailableCamsUpdated = "availableCamsUpdated",
AvailableMicsUpdated = "availableMicsUpdated",
CamUpdated = "camUpdated",
MicUpdated = "micUpdated",

BotConnected = "botConnected",
BotReady = "botReady",
BotDisconnected = "botDisconnected",
BotStartedSpeaking = "botStartedSpeaking",
BotStoppedSpeaking = "botStoppedSpeaking",
RemoteAudioLevel = "remoteAudioLevel",

UserStartedSpeaking = "userStartedSpeaking",
UserStoppedSpeaking = "userStoppedSpeaking",
LocalAudioLevel = "localAudioLevel",

Metrics = "metrics",
UserTranscript = "userTranscript",
BotTranscript = "botTranscript",

LLMFunctionCall = "llmFunctionCall",
LLMFunctionCallStart = "llmFunctionCallStart",
LLMJsonCompletion = "llmJsonCompletion",
```

Handlers for these can be bound on the client like so:

```typescript
import { VoiceEvent } from "realtime-ai";

function handleBotReady() {
  console.log("Bot is ready!");
}

// Bind an event handler
voiceClient.on(VoiceEvent.BotReady, handleBotReady);
// or
voiceClient.on("botReady", handleBotReady);

// Unbind an event handler
voiceClient.off(VoiceEvent.BotReady, handleBotReady);
```
