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

# Ultravox Client SDK

export const SDKCards = ({}) => <div class="sdk-cards">
    There are currently six implementations of the SDK available:
    <br />
    <CardGroup>
      <Card icon="js" title="JavaScript" horizontal>
        <code>npm install ultravox-client</code>
        <br />
        <a href="https://github.com/fixie-ai/ultravox-client-sdk-js" class="">
          <div className="flex justify-end"><Icon icon="github" size={24} /></div>
        </a>
      </Card>
      <Card icon="flutter" title="Flutter" horizontal>
        <code>flutter add ultravox_client</code>
        <br />
        <a href="https://github.com/fixie-ai/ultravox-client-sdk-flutter" class="">
          <div className="flex justify-end"><Icon icon="github" size={24} /></div>
        </a>
      </Card>
      <Card icon="react" title="React Native" horizontal>
        <code>npm install ultravox-react-native</code>
        <br />
        <a href="https://github.com/fixie-ai/ultravox-client-sdk-react-native" class="">
          <div className="flex justify-end"><Icon icon="github" size={24} /></div>
        </a>
      </Card>
      <Card icon="python" title="Python" horizontal>
        <code>pip install ultravox-client</code>
        <br />
        <a href="https://github.com/fixie-ai/ultravox-client-sdk-python" class="">
          <div className="flex justify-end"><Icon icon="github" size={24} /></div>
        </a>
      </Card>
      <Card icon="android" title="Kotlin (Android)" horizontal>
        <div className="flex flex-col">
          <code>Find it on Maven Central</code>
          <br />
          <a href="https://github.com/fixie-ai/ultravox-client-sdk-android" class="">
            <div className="flex justify-end"><Icon icon="github" size={24} /></div>
          </a>
        </div>
      </Card>
      <Card icon="swift" title="Swift (iOS)" horizontal>
        <div className="flex flex-col">
          <code>Find it on Swift Package Index</code>
          <br />
          <a href="https://github.com/fixie-ai/ultravox-client-sdk-ios" class="">
            <div className="flex justify-end"><Icon icon="github" size={24} /></div>
          </a>
        </div>
      </Card>
    </CardGroup>
  </div>;

The Ultravox [REST API](/api-reference/) is used to create calls but a client must still join the call. For web and mobile applications, you can do this with one of our SDKs. This page primarily uses examples in JavaScript. The concepts are the same across all the [different SDK implementations](#sdk-implementations).

## Methods

The core of the SDK is the `UltravoxSession`. The session is used to join and leave calls. The `UltravoxSession` contains methods for:

* Joining/leaving a call
* Sending text messages to the agent
* Changing the output medium for how the agent replies
* Registering client tools
* Muting the microphone/speaker

### joinCall()

Joins a call.

```ts theme={null}
joinCall(joinUrl: string, clientVersion?: string): void
```

<ParamField body="joinUrl" type="string" required>
  The joinUrl that was returned from the [`Create Call`](/api-reference/calls/calls-post) request.
</ParamField>

<ParamField body="clientVersion" type="string">
  Optional string that can be used for application version tracking. Will be appended to the call and be available in the `clientVersion` field in the [`Get Call`](/api-reference/calls/calls-get) response.
</ParamField>

### leaveCall()

Leaves the current call. Returns a promise (with no return value) that resolves when the call has successfully been left.

```ts theme={null}
async leaveCall(): Promise<void>
```

### sendText()

Sends a text message to the agent. If `deferResponse` is set, the agent will not respond (i.e. no LLM generation will be done).

```ts theme={null}
sendText(text: string, deferResponse?: boolean): void
```

<ParamField body="text" type="string" required>
  The message to send to the agent.
</ParamField>

<ParamField body="deferResponse" type="boolean">
  Set to `true` to skip LLM generation (agent won't reply). Can be used to provide additional guidance to the model.
</ParamField>

### setOutputMedium()

Sets the agent's output medium for future utterances. If the agent is currently speaking, this will take effect at the end of the agent's utterance.

```ts theme={null}
setOutputMedium(medium: Medium): void
```

<ParamField body="medium" type="Medium" required>
  How replies are communicated. Must be either `'text'` or `'voice'`.
</ParamField>

Also see [muteSpeaker](#mutespeaker) and [unmuteSpeaker](#unmutespeaker) below.

### registerToolImplementation()

Registers a client tool implementation with the given name. If the call is started with a client-implemented tool, this implementation will be invoked when the model calls the tool.

```ts theme={null}
registerToolImplementation(name: string, implementation: ClientToolImplementation): void
```

<ParamField body="name" type="string" required>
  The name of the tool. Must match what is defined in `selectedTools` during [`Create Call`](/api-reference/calls/calls-post).<br /><br />If `nameOverride` is set then must match that name. Otherwise must match `modelToolName`.
</ParamField>

<ParamField body="implementation" type="ClientToolImplementation" required>
  The function that implements the tool's logic. This is a function that:

  **Accepts `parameters`** → An object containing key-value pairs for the tool's parameters. The keys will be strings.

  **Returns** → Either a string result, or an object with a result string and a responseType, or a Promise that resolves to one of these.

  For example:

  ```js theme={null}
    const stock_price = (parameters) => {
      ...  // to be implemented
      return `Stock price is ${value}`;
    };
  ```
</ParamField>

### registerToolImplementations()

Convenience batch wrapper for [`registerToolImplementation`](#registertoolimplementation).

```ts theme={null}
registerToolImplementations(implementationMap: { [name: string]: ClientToolImplementation }): void
```

<ParamField body="implementationMap" type="Object" required>
  An object where each key (a string) represents the name of the tool and each value is a `ClientToolImplementation` function.
</ParamField>

### isMicMuted()

Returns a boolen indicating if the end user's microphone is muted. This is scoped to the Ultravox SDK and does not detect muting done by the user outside of your application.

```ts theme={null}
isMicMuted(): boolean
```

### isSpeakerMuted()

Returns a boolen indicating if the speaker (the agent's voice output) is muted. This is scoped to the Ultravox SDK and does not detect muting done by the user outside of your application.

```ts theme={null}
isSpeakerMuted(): boolean
```

### muteMic()

Mutes the end user's microphone. This is scoped to the Ultravox SDK.

```ts theme={null}
muteMic(): void
```

### unmuteMic()

Unmutes the end user's microphone. This is scoped to the Ultravox SDK.

```ts theme={null}
unmuteMic(): void
```

### muteSpeaker()

Mutes the end user's speaker (the agent's voice output). This is scoped to the Ultravox SDK.

```ts theme={null}
muteSpeaker(): void
```

### unmuteSpeaker()

Unmutes the end user's speaker (the agent's voice output). This is scoped to the Ultravox SDK.

```ts theme={null}
unmuteSpeaker(): void
```

## Client Tools

Ultravox has robust support for [tools](/tools/overview). The SDK has support for client tools. Client tools will be invoked in your client code and enable you to add interactivity in your app that is driven by user interactions with your agent. For example, your agent could choose to invoke a tool that would trigger some UI change.

<Note>
  <b>Message Size Limit</b>

  Messages larger than 15-16KB may cause timeouts. Keep payload sizes within this limit.
</Note>

<br />

<b>Creating Client Tools</b>

Client tools are defined just like "server" tools with three exceptions:

<Steps>
  <Step title="'client' not 'http'">
    You don't add the URL and HTTP method for client tools.

    Instead, you add `"client": {}` to the tool definition.

    <CodeGroup>
      ```js Using a Client Tool {18} theme={null}
      {
        "systemPrompt": ...
        "selectedTools": [
          "temporaryTool": {
            "modelToolName": "stock_price",
            "description": "Get the current stock price for a given symbol",
            "dynamicParameters": [
              {
                "name": "symbol",
                "location": "PARAMETER_LOCATION_BODY",
                "schema": {
                  "type": "string",
                  "description": "Stock symbol (e.g., AAPL for Apple Inc.)"
                },
                "required": true
              }
            ],
            "client": {}
          }
        ]
      }
      ```

      ```js Using a Server Tool {18-21} theme={null}
      {
        "systemPrompt": ...
        "selectedTools": [
          "temporaryTool": {
            "modelToolName": "stock_price",
            "description": "Get the current stock price for a given symbol",
            "dynamicParameters": [
              {
                "name": "symbol",
                "location": "PARAMETER_LOCATION_QUERY",
                "schema": {
                  "type": "string",
                  "description": "Stock symbol (e.g., AAPL for Apple Inc.)"
                },
                "required": true
              }
            ],
            "http": {
              "baseUrlPattern": "https://api.stockmarket.com/v1/price",
              "httpMethod": "GET"
            }
          }
        ]
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Register Tool with Client">
    Your client tool must be registered in your client code. Here's a snippet that might be found in client code to register the client tool and implement the logic for the tool.

    See the SDK method [`registerToolImplementation()`](#registertoolimplementation) for more information.

    ```js Registering a Client Tool theme={null}
    // Start up our Ultravox Session
    uvSession = new UltravoxSession();

    // Register our client-side tool
    uvSession.registerToolImplementation(
      "stock_price",
      stock_price
    );

    uvSession.joinCall(joinUrl);

    // Function that implements tool logic
    const stock_price = (parameters) => {
      ...  // to be implemented
      return `Stock price is ${value}`;
    };
    ```
  </Step>

  <Step title="Only Body Parameters Allowed">
    Unlike server tools (which accept parameters passed by path, header, body, etc.), client tools only allow parameters to be passed in the body of the request. That means client tools will always have parameter location set like this:

    ```js theme={null}
    "location": "PARAMETER_LOCATION_BODY"
    ```
  </Step>
</Steps>

## Session Status

The `UltravoxSession` exposes status. Based on the `UltravoxSessionStatus` enum, status can be one of the following:

| status        | description                                                            |
| ------------- | ---------------------------------------------------------------------- |
| disconnected  | Session is not connected. This is the initial state prior to joinCall. |
| disconnecting | Session is in the process of disconnecting.                            |
| connecting    | Session is establishing the connection.                                |
| idle          | Session is connected but not yet active.                               |
| listening     | Listening to the end user.                                             |
| thinking      | The model is processing/thinking.                                      |
| speaking      | The model is speaking.                                                 |

<b>Status Events</b>

The status can be retrieved by adding an event listener to the session status.

```js Get Session Status Events theme={null}
// Listen for status changing events
session.addEventListener('status', (event) => {
  console.log('Session status changed: ', session.status);
});
```

## Transcripts

Sometimes you may want to augment the audio with text transcripts (e.g. if you want to show the end user the model's output in real-time). Transcripts can be retrieved by adding an event listener:

```js Get Transcripts theme={null}
// Listen for transcripts changing events
session.addEventListener('transcripts', (event) => {
  console.log('Transcripts updated: ', session.transcripts);
});
```

Transcripts are returned as an array of transcript objects.

<ResponseField name="transcript" type="Transcript Object">
  <Expandable title="properties" defaultOpen>
    <ResponseField name="text" type="string">
      Text transcript of the speech from the end user or the agent.
    </ResponseField>

    <ResponseField name="isFinal" type="boolean">
      True if the transcript represents a complete utterance. False if it is a fragment of an utterance that is still underway.
    </ResponseField>

    <ResponseField name="speaker" type="Role">
      Either "user" or "agent". Denotes who was speaking.
    </ResponseField>

    <ResponseField name="medium" type="Medium">
      Either "voice" or "text". Denotes how the message was sent.
    </ResponseField>
  </Expandable>
</ResponseField>

## Debug Messages

<Warning>
  <b>No Guarantee</b>

  Debug messages from Ultravox should be treated as debug logs. They can change regularly and don't have a contract. Relying on the specific structure or content should be avoided.
</Warning>

The `UltravoxSession` object also provides debug messages. Debug messages must be enabled when creating a new session and then are available via an event listener similar to status and transcripts:

```js Get Debug Messages theme={null}
// Start up our Ultravox Session with Debug Messages Enabled
session = new UltravoxSession({ experimentalMessages: ["debug"] });

// Listen for debug messages
session.addEventListener('experimental_message', (msg) => {
  console.log('Got a debug message: ', JSON.stringify(msg));
});
```

<b>Debug Message:  Tool Call</b>

When the agent invokes a tool, the message contains the function, all arguments, and an invocation ID:

```bash theme={null}
LLM response: Tool calls: [FunctionCall(name='createProfile', args='{"firstName":"Ron","lastName":"Burgandy","organization":"Fixie.ai","useCase":"creating a talking AI news reporter"}', invocation_id='call_D2qQVS8OQc998aMEw5PRa9cF')]
```

<b>Debug Message:  Tool Call Result</b>

When the tool call completes, the message contains an array of messages. Multiple tools can be invoked by the model. This message array will conatain all the calls followed by all the results. These messages are also available via [List Call Messages](/api-reference/calls/calls-messages-list).

Here's an example of what we might see from a single tool invocation:

```bash theme={null}
Tool call complete.

Result: [
  role: MESSAGE_ROLE_TOOL_CALL ordinal: 6 text: "{\"firstName\":\"Ron\",\"lastName\":\"Burgandy\",\"organization\":\"Fixie.ai\",\"useCase\":\"creating a talking AI news reporter\"}" tool_name: "createProfile" invocation_id: "call_D2qQVS8OQc998aMEw5PRa9cF" tool_id: "aa737e12-0989-4adb-9895-f387f40557d8" ,
  role: MESSAGE_ROLE_TOOL_RESULT ordinal: 7 text: "{\"firstName\":\"Ron\",\"lastName\":\"Burgandy\",\"emailAddress\":null,\"organization\":\"Fixie\",\"useCase\":\"creating a talking AI news reporter\"}" tool_name: "createProfile" invocation_id: "call_D2qQVS8OQc998aMEw5PRa9cF" tool_id: "aa737e12-0989-4adb-9895-f387f40557d8"
]
```

## SDK Implementations

<SDKCards />
