# The Voice Lab

The Voice Lab sits at Phone → Setup and is open to both audiences. Every control on it declares which of two kinds it is: an **engine** setting that becomes a session parameter and takes effect exactly, or a **steering** setting that becomes a line in the instructions and is interpreted. A draft can be heard on a test call before it is saved.

- **Status:** Available
- **Audience:** both
- **Channels:** phone
- **In the app:** #/phone
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/phone/voice-lab/

## The honesty the screen is built on

The realtime engine is speech-to-speech. There is no text-to-speech stage underneath it, so there is **no synthesiser with a pitch dial** to reach — and a tuning screen that pretends otherwise would be offering controls that quietly do nothing. Rather than hide that, every control names its kind.

| Kind | Where it goes | What it does |
|---|---|---|
| Engine | `voice_style.session_options`, as a session parameter | Exactly what you set |
| Steering | The instructions, via `voice_style.style_block` | A direction the model interprets |

It is a small labelling decision with a large effect on how people use the screen. Somebody adjusting a steering control knows to judge it by listening to a call; somebody adjusting an engine control knows the value is the behaviour.

## What is on each side

**Engine settings** — Model, voice, a pinned language code, temperature, reply length, affective dialog (native-audio models only), the model's end-of-speech silence (`fast` = 450 ms), pre-emptive generation, thinking off, the interruption thresholds in seconds and words, false-interruption resume, noise cancellation, and the silence-check and hang-up timers.
**Steering settings** — Speed, pitch, energy, warmth, emotion, pauses, fillers, formality, humanness, accent and pronunciation.
**Behaviour texts** — Role, goal, tone, style, knowledge, rules, what to ask and never ask, objections, escalation, opening, closing, proactiveness, language switching and memory use — rendered by `behaviour_block`.

Pitch appearing on the steering side is the clearest illustration of the labelling. You can ask for a higher, lighter delivery and often get it; you cannot set a frequency, and the screen does not suggest you can. The related parameters that genuinely cannot be expressed at all — Hz, dB, jitter, formants, exact pause lengths, a delay before answering — are shown as unsupported in [human voice profiles](/docs/phone/human-voice-profiles/).

## Drafts, test calls and the two refusals

A draft is not saved configuration. It sits at the end of the [resolution order](/docs/phone/voice-profile/) — after workspace, default, purpose, line and contact — and applies to a **test call** so a change can be heard before any real caller meets it.

Two refusals happen before a test call becomes a row, and both exist because of a specific failure:

- **`bad_model`** — the model id is a Vertex path or otherwise malformed. The fifth Lab call rang the owner's phone and then died with a 1008; refusing before dialling is better than a phone that rings into a broken session.
- **`not_ready`** — no worker has checked in for 90 seconds. Refusing here is what lets the drain retry rather than leaving a call attached to nothing.

After the call, the resolved settings are snapshotted onto `call.quality`. That snapshot is what the [call quality review](/docs/phone/voice-lab-review/) judges, so a call is never scored against settings that were changed afterwards.

## Working order

1. Change one thing. Prefer an engine setting when one exists for what you want.
   - Result: An engine change is attributable; two steering changes at once are not.
2. Place a test call with the draft.
   - Result: You hear the change, and the settings that produced it are recorded on that call.
3. Read the review before saving.
   - Result: If the finding you were chasing is marked model-limited, no amount of further tuning will move it — and the review says so instead of implying a control.

> **Note** Both audiences reach the Lab through the same API surface. Phone behaviour is one implementation with two routes into it, so a customer workspace tunes its line with the same code the operator's own workspace uses.

## Questions

### I changed a steering setting and heard no difference. Is it broken?

Probably not, and that is the point of the labelling. A steering setting is a sentence in the instructions; the model weighs it against everything else it has been told. If a behaviour matters enough to be guaranteed, look for an engine setting or deterministic text instead.

### Can I tune settings while a call is happening?

Not from the Lab — that is what the [supervisor panel](/docs/phone/supervisor/) is for, and it steers behaviour with guidance rather than settings. On the default model even that cannot be delivered, because the SDK marks its session immutable.

### Does a test call cost the same as a real one?

It is a real call on a real session, so yes — it is metered like any other, on audio tokens, and it is subject to the same budget refusal. There is no free rehearsal mode, which is a good reason to change one thing at a time.

## Related

- [Voice profiles](https://connectbyjbrh.com/docs/phone/voice-profile/)
- [Call quality review](https://connectbyjbrh.com/docs/phone/voice-lab-review/)
- [Telling the voice how to speak](https://connectbyjbrh.com/docs/phone/speaking-guide/)
- [What a setting cannot change](https://connectbyjbrh.com/docs/phone/model-limits/)
- [The realtime voice engine](https://connectbyjbrh.com/docs/phone/realtime-engine/)

## What this page is based on

- Connect phone source pack — `docs-source/sources/PHONE.md` §6, the Voice Lab
- Connect phone source pack — `docs-source/sources/PHONE.md` §9, pre-call refusals
- Connect capability registry — `docs-source/facts.py` (`voice_lab`, `MEASURED`)
