Table of Contents
"It sounds robotic" is a common verdict on a voice agent demo, and it usually describes delivery register rather than the model. Register is how far the pitch moves and how much the pacing varies, and every voice ships tuned to one.
Since that tuning holds for the whole session, a greeting and a payment confirmation land the same way, which is what reads as flat. Swapping models is the expensive answer, since a re-integration can land on another composed default, so the cheaper first move is a configuration check.
In this guide, you'll work through the diagnosis, the register values worth auditioning, and the flows where calm delivery is the correct setting.
Key takeaways
The five points below cover the parameter's range, its beta status, what carries across turns, and what you can't change mid-call.
expressivityspans a calm-to-animated register from-2to2; each voice's tuned delivery is the default at0.- Flux TTS is generally available, though the parameter is flagged beta inside that GA product. The default is the only value validated for production, and non-default values raise hallucination and pronunciation-error risk.
- Prosody carries across turns automatically, with no API surface to manage.
- Mid-stream speed adjustment (
0.85to1.15,0.05steps) is documented as forthcoming for Flux TTS; expressivity is fixed once the connection opens. - The parameter isn't available on Aura-2.
What actually makes AI voice sound flat
Flat delivery comes from register rather than the model's ceiling, and register holds constant for a whole session. Checking a single query parameter takes minutes rather than a sprint.
What delivery register means
Delivery register is the band a voice renders in, meaning how wide the pitch moves and how much the pacing varies. Play any single sentence from a modern TTS model and it sounds fine, since the complaint surfaces across a conversation, where every response lands in the same band. The band comes from the voice itself, since every Flux TTS voice ships at the delivery Deepgram tuned for production voice agents.
The same line at the same setting every turn
Every turn renders at the setting the connection opened with, because register is a session-level value rather than a per-line one. In a support queue, that consistency is the point. In a consumer app, it reads as flat, which is why you start shopping for emotional text to speech models when an expressivity change addresses the register mismatch.
What a model swap won't fix
A model swap won't fix a register mismatch. If the new model's default also sits at the composed end, the re-integration bought you nothing. So diagnose before you migrate, rendering the same script at two expressivity values and listening to both.
Delivery register vs. emotional TTS
One control is a single session-level value, the other is a label on every line, and the choice sets your whole configuration surface. Pick wrong and you either build a tagging pipeline you don't need or expect per-line control a session-level parameter can't give.
Delivery register in plain English
The register option is one dial you set once per call. The Flux TTS feature overview documents expressivity as a whole number from -2 for calm to 2 for animated, with 0 as each voice's tuned default. Lower values make the voice steadier and flatter in pitch, and higher values give it more movement and livelier pacing. The trade is uniformity, since one setting decides the whole call and no single line gets different treatment.
What "emotional TTS" usually means
Per-line direction is what most vendors mean by emotional TTS, where every string you send carries its own delivery instruction, often a label like "apologetic" or "excited." Register buys uniformity with one decision, and this pattern inverts both halves. Each line can sound different, but the decisions multiply, because something upstream has to label every one.
Why the distinction changes what you configure
The distinction decides whether you configure one value or build a tagging layer. A label system needs a pipeline. Your LLM or template layer has to emit the right tag per line, and someone has to decide what "apologetic" means for a refund script. Register needs one integer chosen before the connection opens. For most production agents that makes register the cheaper answer, with one decision to test and fewer ways to get a single turn weirdly wrong.
Setting expressivity from -2 to +2
Picking a value is a production decision rather than a preference, because only the default carries Deepgram's validation. The parameter documentation supplies that default when you send nothing. The rest of this section walks through what each value does, how the extremes read on the page, and where the value goes on each transport.
The values and what they do
Five whole numbers cover the range, and each one shifts pitch movement and pacing in the same direction as its sign. Send anything outside the range and the connection is rejected with EXPRESSIVITY_OUT_OF_RANGE. The table below pairs the two extremes and the default with the flows each one suits:
| Value | What Changes in Delivery | Where You'd Use It |
|---|---|---|
| -2 | Calm end: steadier, measured pacing, narrow pitch, potentially soft or breathy | Support and de-escalation, healthcare, IVR and self-service |
| 0 | Tuned default delivery | Production voice agents (the docs' recommended setting) |
| 2 | Animated end: widest pitch range, brightest overall pitch | Consumer applications, outbound engagement |
- What Changes in Delivery
- Calm end: steadier, measured pacing, narrow pitch, potentially soft or breathy
- Where You'd Use It
- Support and de-escalation, healthcare, IVR and self-service
- What Changes in Delivery
- Tuned default delivery
- Where You'd Use It
- Production voice agents (the docs' recommended setting)
- What Changes in Delivery
- Animated end: widest pitch range, brightest overall pitch
- Where You'd Use It
- Consumer applications, outbound engagement
The in-between values behave as smaller steps. The calmer one is a measured take on the default, and the more animated one adds wider pitch contours and livelier pacing without reaching the extreme.
Hearing the difference on the page
Take one line: "Your appointment is confirmed for 3pm tomorrow." Then mark where the emphasis (bold) and pauses (| short, ‖ longer) fall at each setting:
- At
-2: "Your appointment|is confirmed|for 3pm tomorrow." Narrow pitch band, even pacing, one small lift on the time. - At
0: "Your appointment is confirmed|for 3pm tomorrow." Tuned default: two natural stress points, one mid-sentence pause. - At
+2: "Your APPOINTMENT is confirmed‖for 3pm|tomorrow!" Wider pitch arc, brighter overall pitch, pacing shifts word to word.
Pitch movement and pacing are the dimensions to focus on. Published expressive-TTS evaluations score synthesized speech against human corpora on acoustic prosody measures of this kind. Reading only gets you so far, so render the same line at all three values on the voice you'll ship and hear the range.
Setting the parameter on each transport
Your connection method determines where the value goes. On streaming, it's a query parameter on the WebSocket URL:
wss://api.deepgram.com/v2/speak?model=flux-haley-en&expressivity=-1On batch, the same parameter rides the query string of each POST request to the Flux TTS /v2/speak endpoint. On the Voice Agent API, it sits at agent.speak.provider.expressivity inside the Settings message and applies for the whole session. The parameter exists on Flux TTS only; Aura-2's /v1/speak endpoint doesn't accept it.
Holding tone steady across turns
Tone consistency across a call is free on Flux TTS, since the model carries prosody state between turns with no code on your side. What you can change mid-call is the harder question, and today the answer is almost nothing.
Prosody that carries forward
Tone, pacing, and emotional register carry from one turn to the next without any work from you. The cross-turn context docs state there are no new API parameters to set or manage. The carry-over survives the end of a turn, and Deepgram's docs say it will also survive an interruption once barge-in support ships. Treat interruption survival as forthcoming rather than available today. Opening a new connection resets it.
Adjusting speed without reconnecting
Speed is the one setting Deepgram documents as adjustable mid-call, and it isn't shipping yet. A forthcoming Configure message would let you change pace between 0.85 and 1.15 in 0.05 steps, taking effect at the start of the next chunk of speech. Whatever is already playing finishes at the old pace, and nothing gets re-generated. Check the Voice Agent inputs docs before you build against it.
What you can't change mid-call
Expressivity is the setting you can't touch once a call is live. The docs' own FAQ answers "Can I change it mid-conversation?" with a flat no, since the value is set when you open the connection and holds for the session. So the register decision belongs before the call starts, and changing it means reconnecting. Because prosody state resets on a new connection, that carried state goes with it.
Before you hardcode a value
A register value is cheap to set and expensive to get wrong, since the register control is documented as beta and carries guidance to validate whatever value you choose. So the value belongs in your test plan rather than frozen in your config.
Audition the exact value you plan to ship
Two rules decide whether an audition means anything. Run your production scripts at the exact value you'll deploy, on the voice you'll ship. Discount any demo recorded at a different value, since it says nothing about your configuration.
The risk that grows with magnitude
Hallucinated or mispronounced output gets likelier the further you go from the default. Expressive delivery may also tax the speech recognition on the other end, and Deepgram's analysis of the accuracy tax covers the mechanisms. Published results disagree on the direction and size of any penalty. Test for the penalty on your own audio rather than assuming one.
When flat delivery is the right call
When a caller is already frustrated, measured delivery conveys composure and avoids the impression of coldness. The calm end of the range is a deliberate production register for support and IVR work.
Support, IVR, and de-escalation
Choose steadier delivery when callers need reassurance or must work through IVR flows. The documented goal is consistency rather than a more animated register. That's why the docs map negative values to de-escalation and self-service flows.
Regulated and high-stakes content
For medication instructions and financial disclosures, the default is the right register, since it's already measured delivery and it's the only setting carrying validation. The docs create a conflict here, mapping calm values to healthcare while flagging every non-default value as beta. Ship a negative setting into a regulated flow and you're knowingly accepting unvalidated behavior, so the animated end is out and the default stands.
The setting that reads as calm, not broken
Measured delivery reads as composure, not as a broken voice, so a complaint that survives the default points somewhere else. Background noise and reverberation are the usual other cause. Deepgram's environment-aware TTS research deep dive covers it, as does IDEA-TTS, which treats environment as a factor separate from speaker and text.
Pick a register, then validate it
The register you ship is a product decision, and it holds for every call your agent takes. Start at the default, audition alternatives against real scripts, and re-check after every model update.
A starting point by use case
Regulated and high-stakes flows stay at the default. Support lines that handle escalations can audition a calmer setting, and that choice accepts the beta trade-off. Consumer and outbound products are the case for more animated settings, and only after listening tests on the voices you'll actually ship. Whatever you choose, wire error handling for connection rejection before launch, because an invalid value refuses the connection.
What to re-check after a model update
Re-run your audition scripts on the same voice and value, and listen for pronunciation drift in domain terms such as drug names, account numbers, and other alphanumerics. The parameter docs tell you to re-validate values after model updates and treat every chosen value as provisional. Build that check into your release process.
The fastest way to settle a register debate is to hear your own script at two settings. Deepgram gives new accounts $200 in free credits, so create a free account and try the value your agent will actually ship with.
FAQ
Does the same expressivity value sound the same on every voice?
No. Deepgram documents unique character and sensitivity per voice; a value that's subtle on one voice can be pronounced on another.
What happens if I send a fractional value like 1.5?
Use an integer schema client-side to avoid EXPRESSIVITY_INCREMENT_INVALID at connection time.
What can't Flux TTS do with delivery and text input?
Per-line emotion labels aren't part of the API, and no voice-cloning or custom-speaker workflow ships with the model. Inline pause and pronunciation controls are documented as coming soon. Recognized W3C SSML elements and vendor audio tags get stripped with a warning while synthesis continues, and anything else, like Markdown, is read as written.
Is expressivity available on Aura-2 or the Voice Agent API?
Support is limited to Flux TTS; Aura-2 doesn't accept expressivity. In the Voice Agent API, set agent.speak.provider.version to v2, then configure agent.speak.provider.expressivity before opening the session.
How do I compare Flux TTS against other emotional text to speech providers?
Hold the script and output configuration, including format and sample rate, constant. Choose the closest comparable voice and test each vendor at its documented default plus a comparable expressive setting.









