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

# Voice chat in the widget

> Let end users talk to the agent instead of typing, by live voice conversation or recorded voice messages, and turn either off

After this guide, you know which of the widget's two voice features to keep on and what an end user's browser needs for each. Both are on by default: voice mode (`voiceModeEnabled`) opens a live two-way conversation, and the microphone (`microphoneEnabled`) records a voice message that is sent like an attachment. For phone calls, see [Voice calls](/channels/voice-calls); for how voices are defined and versioned, see [Voice](/concepts/voice).

**Before you begin**

* The widget working per the [quickstart](/channels/web-widget/quickstart), served over HTTPS. Browsers grant microphone access only on secure origins and `localhost`.
* For voice mode, a voice on the agent: the first voice defined on it answers (see [Voice](/concepts/voice)). Without one, the live WebRTC session is refused and the widget falls back to its WebSocket connection.

<Steps>
  <Step title="Decide which voice features to show">
    Both buttons sit in the message box: a waveform starts voice mode and a microphone records a voice message. Both options default to `true`, so an agent with no voice still shows both buttons; set `voiceModeEnabled: false` to hide the waveform until a voice is defined. The admin dashboard's **Chat widget** settings carry the same toggle, and an inline option overrides it.

    ```js theme={null}
    window.LuaPop.init({
      agentId: "agent_abc123",
      environment: "production",
      voiceModeEnabled: true,
      microphoneEnabled: false,
    });
    ```
  </Step>

  <Step title="Know what happens in voice mode">
    Clicking the waveform asks for microphone permission, then connects a live voice session over WebRTC; when that connection can't be made, the widget falls back to streaming audio over a WebSocket. The window shows **Connecting...**, **Listening...**, and **Speaking...**, plays the agent's replies aloud, and shows a transcript of both sides. The end user ends the voice session from the toolbar that replaces the message box.
  </Step>

  <Step title="Know what happens with a voice message">
    Clicking the microphone records with the browser's `MediaRecorder`. On send, the recording uploads as `audio/webm`, reaches the agent as an audio message together with any typed text, and the agent answers in text as usual.
  </Step>

  <Step title="Verify">
    Over HTTPS, open the widget and click the waveform. The browser asks for the microphone once, and the window shows **Connecting...**, then **Listening...**. Say something: your words appear as a transcript and the agent answers out loud.
  </Step>
</Steps>

## Options you may need

### Hide voice on insecure pages

A page served over plain HTTP can't get microphone access, so hide both buttons there.

```js theme={null}
const secure = window.isSecureContext;

window.LuaPop.init({
  agentId: "agent_abc123",
  environment: "production",
  voiceModeEnabled: secure,
  microphoneEnabled: secure,
});
```

## If it isn't working

<AccordionGroup>
  <Accordion title="The window shows Connection Error">
    Microphone permission was denied or the connection failed. The end user can allow the microphone in the browser's site settings and try again; text chat keeps working meanwhile.
  </Accordion>

  <Accordion title="No microphone prompt appears">
    The page is not a secure context, or the browser remembered an earlier denial. Serve the page over HTTPS and check the site's permission settings.
  </Accordion>
</AccordionGroup>

## Next steps

<Columns cols={2}>
  <Card title="Voice" href="/concepts/voice">Voice definitions, the default voice, and voice sessions.</Card>
  <Card title="Widget configuration" href="/channels/web-widget/configuration">`voiceModeEnabled`, `microphoneEnabled`, and the rest.</Card>
</Columns>
