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

# Voice Agent

> A full spoken conversation

`RunAnywhere.voice` assembles speech-to-text, a language model, and text-to-speech into one
session that listens, thinks, and answers out loud. It owns the microphone while it runs.

```ts theme={null}
const session = await RunAnywhere.voice.createSession(config)
await session.start()
```

## Signature

```ts theme={null}
createSession(config: VoiceSessionConfig): Promise<VoiceSession>
```

The config names the three models and, optionally, VAD options, turn handling, generation
options, and whether to download anything missing.

## VoiceSession

```ts theme={null}
session.start(): Promise<void>
session.say(text: string): Promise<SpeechHandle>
session.interrupt(): Promise<void>
session.close(): Promise<void>
```

`say` speaks a line without waiting for the user, which is how you greet someone. `interrupt`
cuts off whatever is being spoken.

Always `close()` the session. It holds the microphone, and on macOS the menu-bar recording
indicator stays lit until you do.

## Turn handling

| Setting                      | Default | Meaning                                    |
| ---------------------------- | ------- | ------------------------------------------ |
| `endpointing.minDelayMs`     | `500`   | Shortest silence that ends a turn          |
| `endpointing.maxDelayMs`     | `3000`  | Longest wait before ending it anyway       |
| `interruption.enabled`       | `true`  | A person talking over the model stops it   |
| `interruption.minDurationMs` | `500`   | Speech this long counts as an interruption |

Raise `interruption.minDurationMs` in a noisy room, or a cough cuts the model off.

## Steering the replies

```ts theme={null}
generation: {
  systemPrompt: 'You are a voice assistant. Answer in one or two sentences.',
  maxOutputTokens: 100,
}
```

Spoken replies want to be short, even on a desktop where you could afford longer ones. A model
that writes four paragraphs is unbearable to listen to.

## Closing on window close

```ts theme={null}
win.on('closed', () => {
  void session?.close()
})

app.on('before-quit', () => {
  void session?.close()
})
```

Both matter. A window closing does not end the process, so a session tied only to `before-quit`
keeps recording after the user thinks they stopped.

## Three models at once

A voice session holds a speech model, a language model, and a synthesis model together. A
desktop has the headroom for this, but see
[residency policy](/electron/models#residency-policy) when a chat model is also loaded, or the
session will evict it on every turn.

## Microphone permission

On macOS, add `NSMicrophoneUsageDescription` to the app's Info.plist. The session cannot start
without consent, and a denial persists until the user changes it in System Settings.

## Diarization

To answer "who spoke when" over a recording rather than run a live conversation, use the
[diarization namespace](/electron/diarization).
