Which voice models accept inline audio tags
Four speech providers parse bracketed delivery cues and four take mood as a parameter. The two camps, four incompatible syntaxes, and how to convert a script.
Paste a script that reads [excited] We just shipped it. into a model that does not parse markup and the brackets do not become a performance. Best case they are ignored. Worst case they are rendered as words, in a pleasant voice, with no error and no warning: a clean take of exactly what you typed rather than the one you meant.
Inline delivery tags are the most useful control in text-to-speech, and support for them is not something you can assume from the family name. A model either parses markup inside the script or it treats markup as text. Knowing which route your voice is on, before you write a line of emotional direction, is the decision everything else in this family follows from.
Two camps
Versely's speech tooling routes providers down one of two paths, and the split is worth knowing before you mark up a single word.
In-text taggers read markers written inside the script and change delivery at the point the marker appears. Four providers are on this path: ElevenLabs, Chatterbox, Grok and Inworld. These are the ones the platform treats as accepting speech tags inside the text.
Parameter-driven models take mood as a separate API field, and the guidance attached to them is explicit: do not put bracketed markup in the script. Four providers are on this path: Cartesia, Gemini, Qwen3 and MiniMax.
One caveat, because you will run into it: Gemini 3.1 Flash TTS lists inline audio tags on its own catalog entry alongside natural-language style control. Both things can be true at once. The route Versely's tooling supports for it is the style parameter, and that is the route this post treats as the Gemini answer.
The distinction is structural, not a maturity ranking. A parameter-driven model is not one that has failed to catch up. It is a different interface with a real tradeoff: one mood applied cleanly to the whole take, versus positional control you have to place correctly. See audio tags for the underlying concept, and note the mechanism it describes: where a model has no inline support, tags are just characters in the script.
The four that parse tags, and their four incompatible syntaxes
There is no shared standard. All four use different markup, and a script marked up for one is not portable to another. This is worth internalising, because "it worked on ElevenLabs" is the most common way people arrive at a broken Grok render.
ElevenLabs uses square brackets prepended immediately before the phrase they apply to.
[excited] That's amazing!
[whispers] Don't tell anyone.
The documented vocabulary includes [excited], [whispers], [laughs], [sighs], [sarcastic] and [curious]. The instruction that comes with it is to tag only moments that clearly call for a shift in delivery.
Grok uses paired tags, and this is the important difference. Every opening tag must be closed, and you wrap only the portion of text the emotion actually applies to.
<cheerful>Welcome aboard!</cheerful> The setup takes about a minute.
An unclosed tag is not a soft failure that degrades gracefully. It leaves everything after it in an undefined state. If you take one thing from this section, take that.
Inworld uses inline square-bracket markup that sits at the exact word or clause it modifies, including mid-sentence, rather than only at the start of a line.
[happy] I did it! [whispering] Don't tell anyone.
The mid-sentence placement is the point. Inworld is the natural fit for conversational, UGC-style reads where the tone turns inside a clause rather than between sentences.
Chatterbox uses angle-bracket markers for non-speech vocalisations, inserted at the exact point the sound occurs.
That's incredible! <laugh> I still can't believe it.
Its vocabulary is <laugh>, <sigh>, <gasp>, <cough> and similar, and the guidance is to insert them only where a natural non-speech vocalisation would actually happen. It is a narrower tool than the other three: it produces sounds, not a change in how the surrounding words are read.
| Provider | Delimiter | Shape | Typical vocabulary |
|---|---|---|---|
| ElevenLabs | Square brackets | Single marker, before the phrase | [excited], [whispers], [laughs], [sighs] |
| Grok | Angle brackets | Paired, must be closed | <cheerful>…</cheerful> |
| Inworld | Square brackets | Single marker, inline mid-sentence | [happy], [whispering] |
| Chatterbox | Angle brackets | Single marker at the sound | <laugh>, <sigh>, <gasp>, <cough> |
Two rules apply across all four. Place the tag immediately before the phrase it modifies, not at the top of the script, because delivery is positional and a tag parked at the start applies to a boundary you did not intend. And keep them sparse: three well-placed tags produce a more controllable read than one on every clause, which produces a delivery that lurches.
The param camp: where mood actually goes
Cartesia, Gemini, Qwen3 and MiniMax all take the same instruction: do not add tags or bracketed markup to the text. Mood goes in a separate field.
- Cartesia takes an
emotionAPI parameter. - Gemini takes
style_prompt/style_instructions. - Qwen3 takes a natural-language style prompt or emotion parameter.
- MiniMax takes a natural-language style prompt or emotion parameter.
On the agent side the same split is mirrored: the speech generation tool exposes emotion and style_instructions fields precisely so that a param-driven provider gets its direction through the right channel.
The practical shape of writing for this camp is two separate things rather than one marked-up thing:
TEXT field (the script — no tags):
Three weeks ago we had no idea this would work. Now it's live in eleven countries.
STYLE / EMOTION field (kept separate):
warm, confident, unhurried
Two of these providers carry a structural capability the tag camp does not. Gemini has a dedicated multi-speaker mode where each speaker alias gets its own distinct voice, spoken in the order their lines appear, so a two-voice exchange is one call rather than a chain of single-voice generations stitched together. Write it as labelled speaker turns:
HOST: So what actually changed this quarter?
GUEST: Honestly, the thing nobody expected.
HOST: Go on.
That is the right route for a multi-voice dialogue or podcast clip. Qwen3 has the Voice Design variant, where instead of picking a voice from a catalog you describe the voice you want, something like "a gravelly older narrator with a slow, confident cadence." That description belongs in the voice-design field. The text field carries only the words to be spoken. Keep the two apart, because a character brief pasted into the script field is a character brief you have asked the model to say.
Why Auto Tag refuses to touch half the catalog
Versely's prompt-enhancement step for speech takes a target provider and then does one of two structurally different things depending on which camp that provider is in. For ElevenLabs, Grok, Inworld and Chatterbox it weaves inline delivery tags into the script it hands back. For Cartesia, Gemini, Qwen3 and MiniMax it returns clean, tag-free text plus a separate style suggestion meant for the emotion or style parameter.
That second behaviour looks like the feature not working. It is the feature working. Markup inserted into a param-driven provider's script field is not guaranteed to be interpreted as direction, so a script that comes back untouched is a script that cannot be corrupted by characters the model was never told to parse. If you point Auto Tag at Cartesia Sonic 3.5 and get your script back verbatim with a style suggestion beside it, that is the expected result, not a bug.
Handling a voice that does not support tags
You wrote a tagged script and the voice you want is in the param camp. Four options, roughly in order of how often they are the right call.
- Move the direction to the style field. Strip the tags, collapse their intent into one short mood description, accept that it applies to the whole take. This is right most of the time, because most voiceover does not actually change register mid-line.
- Split the script at the emotional turns. Generate each segment separately with its own style value, then join them on the timeline. This gives you positional control on a model that does not offer it, at the cost of one generation per segment and a little care with room tone at the joins.
- Switch models. If the read genuinely lives or dies on a mid-sentence turn — a confession, a punchline, an aside — use a tag-capable voice. Compare candidates on the best text-to-speech model page rather than guessing.
- Raise expressiveness at the model level. Where a model exposes an expressiveness or stability control, that is a different lever from mood; see voice stability for what it actually changes.
Speech models in this catalog bill per 1,000 characters of script, in credits, with current rates on pricing. Auditioning a single line across three voices before committing a full script is a habit worth forming; the text-to-speech tool page is the entry point, and the agent can write and generate a voiceover in one pass if you would rather describe the read than configure it.
FAQ
How do I tell which camp a voice is in without testing?
Check whether the model exposes an emotion or style parameter separately from the script field. If it does, it is almost certainly param-driven and expects clean text. If the model's guidance names specific bracket vocabulary, it is a tagger. The four-and-four split above covers the providers the tooling routes today, and the catalog carries speech models outside it, so check the model page rather than assuming by family.
Can I write one tagged script and reuse it everywhere?
No, and this is the most expensive assumption in the category. There is no shared standard: ElevenLabs and Inworld use square brackets differently from each other, Grok requires paired tags, Chatterbox covers only non-speech sounds, and four more providers are documented to take their direction as a parameter instead. A tagged script is written for exactly one provider.
What happens if I forget to close a Grok tag?
Everything after the opening tag is in an undefined state rather than failing cleanly, which is worse than an error because the render succeeds and sounds subtly wrong. Grok's guidance requires every opening tag to be closed. Search your script for opening tags and count the closes before you generate.
Do tags work in languages other than English?
Tags that map to non-verbal behaviour, such as a laugh or a sigh, generalise better than tags naming an abstract emotion, because the behaviour is language-independent and the emotional register is not. Test the specific tag in the specific language rather than assuming parity with your English read.