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

# Voice Configuration

> Tenants, auth transport, audio providers, turn response mode, VAD, and readiness gating.

# Voice Configuration

## Multi-tenancy

Tenant configuration is database-backed via PostgreSQL, with an in-memory fallback for
development. Cached tenant state is reused for performance and evicted when idle per
`TENANT_CACHE_IDLE_TTL_SECS` (default 3600s).

Reload cached tenants without dropping live sessions using
`POST /admin/tenants/reload-cached`.

## Auth transport

This is the setting most worth understanding before deploying.

| Variable                      | Default | Purpose                                                                                       |
| ----------------------------- | ------- | --------------------------------------------------------------------------------------------- |
| `STREAM_AUTH_SECRET`          | —       | Signs short-lived `stream_token` values for Twilio media streams                              |
| `STREAM_AUTH_SECRET_PREVIOUS` | —       | Temporarily accepts in-flight tokens while rotating the secret, with no media-stream downtime |
| `LEGACY_QUERY_AUTH_ENABLED`   | `false` | Opt-in raw `auth_token`/`tenant_token` query transport, for migration only                    |

<Warning>
  `LEGACY_QUERY_AUTH_ENABLED=true` re-enables raw tenant tokens in query strings and Twilio
  custom-parameter bootstrap. It exists for migration scenarios and defaults to **off**.

  In `NODE_ENV=production`, startup **fails fast** when legacy auth is off but
  `STREAM_AUTH_SECRET` is unset — so a deployment cannot end up with neither transport working.
</Warning>

Rotate `STREAM_AUTH_SECRET` by setting the old value in `STREAM_AUTH_SECRET_PREVIOUS`, deploying
the new secret, then removing the previous once in-flight tokens have expired.

## Audio output

Per-tenant `audio_output_provider`: **`elevenlabs`** (default) or **`openai`** (explicit
override).

ElevenLabs transport and 5xx/429 failures retry with backoff, and a **circuit breaker** prevents
a provider outage from cascading. Provider outcome metrics are emitted, and
`GET /admin/tenants/audio-providers` shows configured vs *effective* provider along with
fallback state and reason.

### Provider base URLs

`OPENAI_BASE_URL`, `ELEVENLABS_BASE_URL`, and `ELEVENLABS_WS_BASE_URL` redirect Chat
Completions, TTS, and STT traffic to an LLM gateway, regional proxy, or test harness. Defaults
are the public provider hosts.

<Note>
  These are read **once at startup**. Changing them requires a restart.
</Note>

## Turn response mode

Controls how assistant replies reach TTS on the Chat Completions path:

| Mode                          | Behaviour                                                                                                |
| ----------------------------- | -------------------------------------------------------------------------------------------------------- |
| `single_sentence` *(default)* | Waits for the full completion, then speaks one sanitised sentence                                        |
| `streaming`                   | Flushes sentences to TTS as LLM deltas arrive — first audio ≈ first sentence, the lowest-latency posture |

Resolution order: per-tenant `turn_response_mode` → process-wide `TURN_RESPONSE_MODE` →
`single_sentence`.

<Tip>
  The per-tenant field is settable live via the admin tenant-config `PATCH`, so you can roll
  `streaming` out tenant by tenant rather than flipping the whole fleet.
</Tip>

## Voice activity detection

VAD tuning — threshold, prefix padding, silence — is set **per tenant** in tenant config. Values
are clamped to safe defaults with a warning at load, so a bad value degrades rather than breaks.

## Handoff workflows

`receptionist.handoff_workflow` drives number-specific bridge targets and post-call notes from
tenant config rather than compiled code.

`twilio.human_agent_timeout_seconds` (default 25s) bounds the ring on a human handoff. See
[Voice API](/stateset-voice/api#human-handoff) for the no-answer recovery path.

## Custom tools

Agent versions accept `tools[]` — a JSON-schema function plus your HTTPS endpoint. Mid-call
invocations POST to your endpoint with `Authorization` passthrough and the webhook-style
`X-Webhook-Signature` HMAC; the JSON reply becomes the tool result.

`POST /make-call` also accepts a transient per-call `config` including tools, for prototyping
without publishing an agent version.

## Rate limiting

Per-IP and per-tenant token buckets with configurable limits and automatic cleanup. Tenant key
extraction supports bearer auth, signed `stream_token`, and — only when explicitly enabled —
legacy raw token transport.

## Readiness gating

Kafka is probed and reported in `/health/ready`, but only fails readiness when
`HEALTH_READY_REQUIRE_KAFKA=true`.

<Note>
  That default is deliberate: a broker outage cannot pull call-serving pods out of rotation.
  Enable it only if you genuinely want calls to stop when Kafka is down.
</Note>

## Admin safety

* Admin tenant responses **redact secrets**; updates preserve existing values when you send the
  `<redacted>` placeholder.
* Tenant reads expose deterministic config **ETags**, so writes can use `If-Match` to prevent
  lost updates.
* `ADMIN_API_KEY` is required on admin routes via `x-admin-key`.

## Related

* [Voice API](/stateset-voice/api)
* [Operations](/stateset-voice/operations)
