Rule types
Each rule is either an alias or a phoneme rule.- Alias — the replacement is verbatim spoken text.
"UN"→"United Nations","v2"→"version two". Works on every TTS provider because the substitution happens before the text ever reaches the model. - Phoneme — the replacement is a phonetic string in the IPA or CMU alphabet (set per rule). For digraphs like
dʒ,aɪ, orkʰ, prefer whitespace-delimited input — it converts more reliably than tightly-packed Unicode.
Provider behaviour matrix
How a phoneme rule actually reaches your listener depends on the agent’s TTS provider. This is the most operationally important table on the page.
If a phoneme rule is critical, route the agent through Cartesia, ElevenLabs Flash v2, or Polly. If you don’t control the model, lean on alias rules — they apply everywhere.
Lifecycle
Versions are immutable. Every rule edit (add, remove, set) creates a new version row; the old version is preserved. On every version-creating mutation the API fires a Cartesia sync: it uploads the new version to Cartesia and caches the returnedpronunciation_dict_id on that version row. Subsequent reads of the same version reuse the cached ID — Cartesia is never re-asked for it.
Limits
V1 single-attach to Cartesia. When more than one dictionary is attached to an agent, the runtime currently passes only the first locator’spronunciation_dict_id to the Cartesia plugin and logs cartesia.multi_dict_attach for the rest. Multi-dictionary support will follow when the LiveKit Cartesia plugin signature widens to accept a list.
Operator workflow
- Dashboard → Pronunciation dictionaries → New.
- Add rules (alias, or phoneme with IPA / CMU).
- Save. The API syncs to Cartesia in the background. Look for
cartesia.uploadVersion synced … cartesia_dict_id=…in the API logs. - Attach the dictionary to an agent: Agent → Voice → Pronunciation dictionaries.
- Start a call. The runtime logs
tts.using_cartesia_plugin cartesia_dict_id_count=1when it picks up the cached ID, and the rules apply during synthesis.
Troubleshooting
cartesia.uploadVersion doesn’t appear in the API logs after saving rules. CARTESIA_API_KEY is most likely unset on the API. The sync service skips silently and emits cartesia.uploadVersion CARTESIA_API_KEY unset, skipping. Set the key, restart the API, then re-save the dictionary to force a fresh sync.
The runtime logged tts.using_cartesia_plugin cartesia_dict_id_count=1 but the rule didn’t fire on the call. Confirm the version’s rules are what you expect: GET /v1/pronunciation-dictionaries/:id/versions/:versionId. If a phoneme rule is the suspect, retype the IPA with whitespace between codepoints — digraphs like dʒ and aɪ survive the Cartesia pipe conversion more reliably when delimited.
Invalid origin on sign-in across dev ports. This isn’t a dictionary problem but it shows up while you’re iterating. BETTER_AUTH_URL on the API and the browser’s Origin must match. Set the API’s BETTER_AUTH_URL to the API’s own URL and the web app’s NEXT_PUBLIC_APP_URL to the web URL.