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

# Callbacks and events

export const TransportTable = rows => {
  const headers = ["", "DailyTransport", "SmallWebRTCTransport", "RNDailyTransport", "WebSocketTransport", "OpenAIRealTimeWebRTCTransport", "GeminiLiveWebsocketTransport"];
  if (!rows || !rows.rows || !Array.isArray(rows.rows)) {
    return <div>Error: Invalid rows data</div>;
  }
  return <table className="compatibility-table">
      <tr>
        {headers.map(header => <th key={header}>{header}</th>)}
      </tr>
      {rows.rows.map(entry => <tr key={entry.name}>
          <td>
            {entry.name}() {entry.deprecated ? "⚠️ DEPRECATED" : ""}
          </td>
          <td className={entry.dt ? "supported" : "unsupported"}>
            {entry.dt || "❌"}
          </td>
          <td className={entry.swrtc ? "supported" : "unsupported"}>
            {entry.swrtc || "❌"}
          </td>
          <td className={entry.rn ? "supported" : "unsupported"}>
            {entry.rn || "❌"}
          </td>
          <td className={entry.ws ? "supported" : "unsupported"}>
            {entry.ws || "❌"}
          </td>
          <td className={entry.oai ? "supported" : "unsupported"}>
            {entry.oai || "❌"}
          </td>
          <td className={entry.gem ? "supported" : "unsupported"}>
            {entry.gem || "❌"}
          </td>
        </tr>)}
    </table>;
};

export const callbacks = () => {
  return [{
    name: "onConnected",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onDisconnected",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onTransportStateChanged",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onBotReady",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onBotConnected",
    dt: "1.0.0"
  }, {
    name: "onBotDisconnected",
    dt: "1.0.0"
  }, {
    name: "onParticipantJoined",
    dt: "1.0.0"
  }, {
    name: "onParticipantLeft",
    dt: "1.0.0"
  }, {
    name: "onServerMessage",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0"
  }, {
    name: "onMessageError",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onError",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onAvailableMicsUpdated",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onAvailableCamsUpdated",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    oai: "1.0.0"
  }, {
    name: "onAvailableSpeakersUpdated",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onMicUpdated",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onCamUpdated",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    oai: "1.0.0"
  }, {
    name: "onSpeakerUpdated",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onDeviceError",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onTrackStarted",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onTrackStopped",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onScreenTrackStarted",
    dt: "1.0.0",
    swrtc: "1.3.0",
    rn: "1.0.0"
  }, {
    name: "onScreenTrackStopped",
    dt: "1.0.0",
    swrtc: "1.3.0",
    rn: "1.0.0"
  }, {
    name: "onLocalAudioLevel",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onRemoteAudioLevel",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onBotStartedSpeaking",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onBotStoppedSpeaking",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onUserStartedSpeaking",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onUserStoppedSpeaking",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onUserMuteStarted",
    dt: "1.6.0",
    swrtc: "1.9.0",
    ws: "1.6.0"
  }, {
    name: "onUserMuteStopped",
    dt: "1.6.0",
    swrtc: "1.9.0",
    ws: "1.6.0"
  }, {
    name: "onUserTranscript",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onBotOutput",
    dt: "1.5.0",
    swrtc: "1.8.0",
    ws: "1.5.0"
  }, {
    name: "onBotTranscript",
    deprecated: true,
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0"
  }, {
    name: "onBotLlmSearchResponse",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0"
  }, {
    name: "onBotLlmText",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0"
  }, {
    name: "onBotLlmStarted",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0"
  }, {
    name: "onBotLlmStopped",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0"
  }, {
    name: "onBotTtsText",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0",
    oai: "1.0.0",
    gem: "1.0.0"
  }, {
    name: "onBotTtsStarted",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0"
  }, {
    name: "onBotTtsStopped",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0"
  }, {
    name: "onLLMFunctionCallStarted",
    dt: "1.6.0",
    swrtc: "1.9.0",
    ws: "1.6.0"
  }, {
    name: "onLLMFunctionCallInProgress",
    dt: "1.6.0",
    swrtc: "1.9.0",
    ws: "1.6.0"
  }, {
    name: "onLLMFunctionCallStopped",
    dt: "1.6.0",
    swrtc: "1.9.0",
    ws: "1.6.0"
  }, {
    name: "onMetrics",
    dt: "1.0.0",
    swrtc: "1.0.0",
    rn: "1.0.0",
    ws: "1.0.0"
  }];
};

The Pipecat JavaScript client listens for messages and events from the bot via the transport layer. This allows you to respond to changes in state, errors, and other events. The client implements the RTVI standard for these communications.

## Event Handling Options

You can handle events in two ways:

### 1. Callbacks

Define handlers in the client constructor:

```typescript theme={null}
const pcClient = new PipecatClient({
  callbacks: {
    onBotReady: () => console.log("Bot ready via callback"),
    // ... other callbacks
  },
});
```

### 2. Event Listeners

Add handlers using the event emitter pattern:

```typescript theme={null}
pcClient.on(RTVIEvent.BotReady, () => console.log("Bot ready via event"));
```

<Note>
  Events and callbacks provide the same functionality. Choose the pattern that
  best fits your application's architecture.
</Note>

## Callbacks

### State and connectivity

<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
  `pcClient.disconnect()` or due to an error.
</ParamField>

<ParamField path="onTransportStateChanged" type="state:TransportState">
  Provides a `TransportState` string representing the connectivity state of the
  local client. See [transports](./transports/transport) for state explanation.
</ParamField>

<ParamField path="onBotStarted" type="botResponse: unknown">
  A call to [`startBot()`](./client-methods#startbot) (i.e. a pre-connection
  REST endpoint) was successful and the bot should now be started or in the
  process of starting. The callback receives any data returned from your
  endpoint.
</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 the RTVI `version` number. 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="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="onBotDisconnected" type="participant: Participant">
  Bot disconnected from the transport. This may occur due to session expiry, a
  pipeline error or for any reason the server deems the session over. By
  default, the client will also disconnect when this fires. Set
  `disconnectOnBotDisconnect: false` in the constructor to keep the client
  connected.
</ParamField>

<ParamField path="onParticipantJoined" type="participant: Participant">
  A participant joined the session. Fires for all participants, including the
  bot and the local user.
</ParamField>

<ParamField path="onParticipantLeft" type="participant: Participant">
  A participant left the session. Fires for all participants, including the bot
  and the local user.
</ParamField>

### Messages and errors

<ParamField path="onServerMessage" type="data:any">
  Receives custom messages sent from the server to the client. This provides a
  generic channel for server-to-client communication. The data structure is
  flexible and defined by the server implementation.
</ParamField>

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

<ParamField path="onError" type="message:RTVIMessage">
  Error signalled by the bot. This could be due to a malformed config update or
  an unknown action dispatch or the inability to complete a client request. The
  message parameter is of type `error` and matches [the RTVI
  standard](/client/rtvi-standard#error-%F0%9F%A4%96). Its `data` field includes
  a `message` string that describes the error and a `fatal` boolean indicating
  if the error is unrecoverable and resulted in a bot disconnection. If `fatal`
  is true, the client will automatically disconnect.
</ParamField>

### Media and devices

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

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

<ParamField path="onAvailableSpeakersUpdated" type="speakers:MediaDeviceInfo[]">
  Lists available local speaker devices. Triggered when a new device becomes
  available, a device is removed, or in response to `pcClient.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>

<ParamField path="onSpeakerUpdated" type="speaker:MediaDeviceInfo">
  User selected a new speaker as their selected/active device.
</ParamField>

<ParamField path="onDeviceError" type="error:DeviceError">
  Error related to media devices, such as camera or microphone issues. This
  could be due to permissions, device unavailability, or other related problems.
  See the [DeviceError](./errors#deviceerror) section for more details about the
  return type.
</ParamField>

<ParamField path="onTrackStarted" type="track: MediaStreamTrack, participant:Participant">
  Media track from a local or remote participant/bot 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/bot was stopped and no longer
  playable.
</ParamField>

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

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

### Audio and Voice Activity

<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/bot.
</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>

<ParamField path="onUserMuteStarted">
  The server has started ignoring audio from the client (server-side muting).
  The client should continue sending audio normally but may want to show an
  indication to the user that their input is not being processed. See [User
  Input Muting](/pipecat/fundamentals/user-input-muting) for more details.
</ParamField>

<ParamField path="onUserMuteStopped">
  The server has stopped ignoring audio from the client (server-side muting
  ended). The client can update its UI to indicate that the user's input is
  being processed again.
</ParamField>

### Transcription

<ParamField path="onUserTranscript" type="TranscriptData">
  Transcribed local user input (both partial and final).

  Callback receives a `TranscriptData` object:

  <Expandable title="TranscriptData">
    <ParamField path="text" type="string">
      The transcribed text.
    </ParamField>

    <ParamField path="final" type="boolean">
      Indicates if the text is final (true) or partial (false).
    </ParamField>

    <ParamField path="timestamp" type="string">
      The timestamp of the transcription.
    </ParamField>

    <ParamField path="user_id" type="string">
      The ID of the user the transcription is for.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="onBotOutput" type="BotOutputData">
  A best-effort stream of the bot's output text, including both spoken and unspoken content. This callback is triggered as the bot aggregates the LLM's response into sentences or other logical text blocks as well as word-by-word during TTS synthesis. The callback receives a `BotOutputData` object:

  <Expandable title="BotOutputData">
    <ParamField path="text" type="string">
      The aggregated output text from the bot.
    </ParamField>

    <ParamField path="spoken" type="boolean">
      Indicates if the text has been spoken by the bot.
    </ParamField>

    <ParamField path="aggregated_by" type="'sentence' | 'word' | string">
      The aggregation type used for this output (e.g., "sentence", "code").
      "sentence" and "word" are reserved aggregation types defined by the RTVI
      standard. Other aggregation types may be defined by custom text aggregators
      used by the server. "word" aggregated outputs are sent at the time of TTS
      synthesis for real-time word-level streaming and can be used in lieu of
      `onBotTtsText` if desired.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="onBotTranscript" type="text:BotLLMTextData">
  <Warning>
    DEPRECATED in favor of `onBotOutput` in Pipecat version 0.0.95 and client-js
    version 1.5.0
  </Warning>

  Finalized bot output text generated by the LLM. Sentence aggregated.
</ParamField>

### Service-specific Events

<ParamField path="onBotLlmSearchResponse" type="BotLLMSearchResponseData">
  Bot LLM search response text generated by the LLM service. This is typically
  used for search or retrieval tasks.

  <Warning>
    Search capabilities are currently only supported by Google Gemini. To take
    advantage of this event, your pipeline must include a
    [`GoogleLLMService`](/api-reference/server/services/llm/google) and your
    pipeline task should include the
    [`GoogleRTVIObserver`](/api-reference/server/rtvi/google-rtvi-observer) in
    lieu of the typical `RTVIObserver`.
  </Warning>

  <Expandable title="BotLLMSearchResponseData">
    <ParamField path="search_result" type="string">
      The search result text.
    </ParamField>

    <ParamField path="rendered_content" type="string">
      The rendered content of the search result.
    </ParamField>

    <ParamField path="origins" type="LLMSearchOrigin[]">
      The origins of the search result.

      <Expandable title="LLMSearchOrigin">
        <ParamField path="site_uri" type="string">
          The URI of the site where the search result was found.
        </ParamField>

        <ParamField path="site_title" type="string">
          The title of the site where the search result was found.
        </ParamField>

        <ParamField path="results" type="LLMSearchResult[]">
          The individual search results.

          <Expandable title="LLMSearchResult">
            <ParamField path="text" type="string">
              The text of the search result.
            </ParamField>

            <ParamField path="confidence" type="number[]">
              The confidence scores for the search result.
            </ParamField>
          </Expandable>
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="onBotLlmText" type="BotLLMTextData">
  Streamed LLM token response text generated by the LLM service.

  <Expandable title="BotLLMTextData">
    <ParamField path="text" type="string">
      The text of the LLM response.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="onBotLlmStarted">LLM service inference started.</ParamField>

<ParamField path="onBotLlmStopped">LLM service inference concluded.</ParamField>

<ParamField path="onBotTtsText" type="BotTTSTextData">
  If your TTS service supports streamed responses over sockets, the text
  parameter contains the words from TTS service as they are spoken. If you are
  using a HTTP based TTS service, the text parameter will contain the full text
  of the TTS response.

  <Expandable title="BotTTSTextData" defaultOpen="true">
    <ParamField path="text" type="string">
      The text of the LLM response.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="onBotTtsStarted">TTS service started inference.</ParamField>

<ParamField path="onBotTtsStopped">TTS service inference concluded.</ParamField>

### Function Calling

<ParamField path="onLLMFunctionCallStarted" type="LLMFunctionCallStartedData">
  A function call has been initiated by the LLM. The metadata included depends
  on the server's [`function_call_report_level`](/api-reference/server/rtvi/rtvi-observer#configuration) configuration.

  <Expandable title="LLMFunctionCallStartedData">
    <ParamField path="function_name" type="string">
      Name of the function being called. Only included if report level is `NAME` or `FULL`.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="onLLMFunctionCallInProgress" type="LLMFunctionCallInProgressData">
  A function call is in progress. This replaces the deprecated `onLLMFunctionCall`
  callback and is the event that triggers registered
  [`FunctionCallHandler`s](/api-reference/client/js/client-methods#registerfunctioncallhandler)
  when a `function_name` is present.

  <Expandable title="LLMFunctionCallInProgressData">
    <ParamField path="function_name" type="string">
      Name of the function being called. Only included if report level is `NAME` or `FULL`.
    </ParamField>

    <ParamField path="tool_call_id" type="string">
      Unique identifier for this function call.
    </ParamField>

    <ParamField path="arguments" type="Record<string, unknown>">
      Arguments passed to the function. Only included if report level is `FULL`.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="onLLMFunctionCallStopped" type="LLMFunctionCallStoppedData">
  A function call has completed or been cancelled.

  <Expandable title="LLMFunctionCallStoppedData">
    <ParamField path="function_name" type="string">
      Name of the function that was called. Only included if report level is `NAME` or `FULL`.
    </ParamField>

    <ParamField path="tool_call_id" type="string">
      Identifier matching the original function call.
    </ParamField>

    <ParamField path="cancelled" type="boolean">
      Whether the function call was cancelled before completing.
    </ParamField>

    <ParamField path="result" type="unknown">
      The result of the function call, if available. Only included if report level is `FULL`.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="onLLMFunctionCall" type="LLMFunctionCallData">
  <Warning>
    DEPRECATED in favor of `onLLMFunctionCallInProgress` in Pipecat version
    0.0.102 and client-js version 1.6.0
  </Warning>

  A function call request from the LLM.
</ParamField>

### Other

<ParamField path="onMetrics" default="data:PipecatMetricsData">
  Pipeline mterics data provided by Pipecat. [Learn
  more](/pipecat/fundamentals/metrics).
</ParamField>

## Events

Each callback described above has a corresponding event that can be listened for using the `.on()` method. This allows you to handle the same functionality using either callbacks or event listeners, depending on your preferred architecture.

Here's the complete reference mapping events to their corresponding callbacks:

### State and connectivity Events

| Event Name              | Callback Name             | Data Type        |
| ----------------------- | ------------------------- | ---------------- |
| `Connected`             | `onConnected`             | -                |
| `Disconnected`          | `onDisconnected`          | -                |
| `TransportStateChanged` | `onTransportStateChanged` | `TransportState` |
| `BotReady`              | `onBotReady`              | `BotReadyData`   |
| `BotConnected`          | `onBotConnected`          | -                |
| `BotDisconnected`       | `onBotDisconnected`       | `Participant`    |
| `ParticipantConnected`  | `onParticipantJoined`     | `Participant`    |
| `ParticipantLeft`       | `onParticipantLeft`       | `Participant`    |

### Message and Error Events

| Event Name      | Callback Name     | Data Type     |
| --------------- | ----------------- | ------------- |
| `ServerMessage` | `onServerMessage` | `any`         |
| `MessageError`  | `onMessageError`  | `RTVIMessage` |
| `Error`         | `onError`         | `RTVIMessage` |

### Media Events

| Event Name             | Callback Name            | Data Type                       |
| ---------------------- | ------------------------ | ------------------------------- |
| `TrackStarted`         | `onTrackStarted`         | `MediaStreamTrack, Participant` |
| `TrackStopped`         | `onTrackStopped`         | `MediaStreamTrack, Participant` |
| `AvailableMicsUpdated` | `onAvailableMicsUpdated` | `MediaDeviceInfo[]`             |
| `AvailableCamsUpdated` | `onAvailableCamsUpdated` | `MediaDeviceInfo[]`             |
| `MicUpdated`           | `onMicUpdated`           | `MediaDeviceInfo`               |
| `CamUpdated`           | `onCamUpdated`           | `MediaDeviceInfo`               |
| `SpeakerUpdated`       | `onSpeakerUpdated`       | `MediaDeviceInfo`               |
| `DeviceError`          | `onDeviceError`          | `DeviceError`                   |

### Audio Activity Events

| Event Name            | Callback Name           | Data Type             |
| --------------------- | ----------------------- | --------------------- |
| `LocalAudioLevel`     | `onLocalAudioLevel`     | `number`              |
| `RemoteAudioLevel`    | `onRemoteAudioLevel`    | `number, Participant` |
| `BotStartedSpeaking`  | `onBotStartedSpeaking`  | -                     |
| `BotStoppedSpeaking`  | `onBotStoppedSpeaking`  | -                     |
| `UserStartedSpeaking` | `onUserStartedSpeaking` | -                     |
| `UserStoppedSpeaking` | `onUserStoppedSpeaking` | -                     |
| `UserMuteStarted`     | `onUserMuteStarted`     | -                     |
| `UserMuteStopped`     | `onUserMuteStopped`     | -                     |

### Text and Transcription Events

| Event Name          | Callback Name         | Data Type        |
| ------------------- | --------------------- | ---------------- |
| `UserTranscript`    | `onUserTranscript`    | `TranscriptData` |
| `BotOutput`         | `onBotOutput`         | `BotOutputData`  |
| ~~`BotTranscript`~~ | ~~`onBotTranscript`~~ | `BotLLMTextData` |
| `BotLlmText`        | `onBotLlmText`        | `BotLLMTextData` |
| `BotTtsText`        | `onBotTtsText`        | `BotTTSTextData` |

### Service State Events

| Event Name             | Callback Name            | Data Type                  |
| ---------------------- | ------------------------ | -------------------------- |
| `BotLlmSearchResponse` | `onBotLlmSearchResponse` | `BotLLMSearchResponseData` |
| `BotLlmStarted`        | `onBotLlmStarted`        | -                          |
| `BotLlmStopped`        | `onBotLlmStopped`        | -                          |
| `BotTtsStarted`        | `onBotTtsStarted`        | -                          |
| `BotTtsStopped`        | `onBotTtsStopped`        | -                          |

### Function Call Events

| Event Name                  | Callback Name                 | Data Type                       |
| --------------------------- | ----------------------------- | ------------------------------- |
| `LLMFunctionCallStarted`    | `onLLMFunctionCallStarted`    | `LLMFunctionCallStartedData`    |
| `LLMFunctionCallInProgress` | `onLLMFunctionCallInProgress` | `LLMFunctionCallInProgressData` |
| `LLMFunctionCallStopped`    | `onLLMFunctionCallStopped`    | `LLMFunctionCallStoppedData`    |
| ~~`LLMFunctionCall`~~       | ~~`onLLMFunctionCall`~~       | `LLMFunctionCallData`           |

### Other Events

| Event Name | Callback Name | Data Type            |
| ---------- | ------------- | -------------------- |
| `Metrics`  | `onMetrics`   | `PipecatMetricsData` |

## Usage Example

```typescript theme={null}
import { PipecatClient, RTVIEvent } from "@pipecat-ai/client-js";

// Using callbacks
const pcClient = new PipecatClient({
  callbacks: {
    onBotReady: () => console.log("Bot ready via callback"),
    onUserTranscript: (data) => console.log("Transcript:", data.text),
  },
});

// Alternate approach: Using event listeners
pcClient.on(RTVIEvent.BotReady, () => {
  console.log("Bot ready via event");
});
```

## Transport Compatibility

<TransportTable rows={callbacks()} />
