Skip to content

Assistants

Dictionaries and recognition terms

Teach an assistant the words your business uses, so it hears brand names correctly and says them the way you do.

Every business has words a general-purpose speech engine gets wrong. A caller says "Gree" and the transcript reads "grease". An assistant reads out a French model number and pronounces it as an English name. A dictionary fixes both ends of that: recognition terms bias what the assistant hears, and pronunciations control how it speaks.

The two kinds of entry#

A dictionary holds one kind of entry. The dictionary's own type decides which, and you fix it when you create the dictionary: a list cannot be switched from one kind to the other afterwards. Create a second dictionary instead.

Recognition terms (keywords) bias the transcriber toward words it would otherwise mishear. They affect the transcript and everything downstream of it, including what the language model reasons about and what you read in call activity. Each entry is a term, with an optional language. An entry may also carry soundsLike, a list of phonetic hints for the term. It is accepted and stored, but no transcriber receives it yet, so do not write a rule that depends on it.

Pronunciations (pronunciations) change how the assistant says a word out loud. They never change the words it chooses, only the sound. Each entry is a word plus at least one of two ways to say it. A respell is a plain-text spelling of the sound, such as Kat. A phonemes value is space-separated IPA, such as k a t. You can supply both, and doing so is worth it, for reasons the support table below makes clear. An entry can also set caseSensitive: it defaults to false, which matches the word whatever its capitalisation, and setting it to true means only the exact capitalisation you wrote in word matches.

Pronunciations match whole words only. A rule for Quatre fires on Quatre and never inside Quatres, so a plural or a compound form needs an entry of its own.

Entries store intent rather than any provider's syntax. That is deliberate. It means a rule you write today survives changing the assistant's voice or transcriber tomorrow, because OnCore re-renders it for whatever engine is running.

Where dictionaries live, and how they combine#

Dictionaries belong to your tenant, not to one assistant. You write "the words our company uses" once, then link that list to every assistant that needs it. An assistant can link several, which is how a clinic keeps brand names and medication names in separate lists and gives a given assistant both.

On top of the linked lists, each assistant can carry its own entries for words only it needs, such as the name of that assistant's persona. You do not have to clone a shared list to add one word.

When a call starts, OnCore combines them in a fixed order. The assistant's own entries come first, then each linked dictionary in the order you linked them. If the same word appears more than once in the same kind of list, the first definition wins and the rest are ignored. So an assistant's own entry always beats a shared list, and an earlier list beats a later one. Reordering the links is how you change which wins.

The two kinds never compete with each other. A word can be a recognition term and have a pronunciation at the same time, and both apply: one decides what the assistant hears, the other decides how it speaks. For a brand name you want handled at both ends, that is exactly the setup to use, and neither copy shadows the other.

The dashboard shows a warning when a word is defined more than once within one kind, naming the list it is in, which source is used, and which are ignored. It is worth reading, because a shadowed rule looks configured but never applies.

When a rule is applied, and when it is ignored#

This is the part worth reading closely. A dictionary entry is not a guarantee. Whether it takes effect depends on the assistant's voice or transcriber, and OnCore deliberately declines to send a rule to an engine that would mishandle it.

Pronunciations by voice model#

Voice modelPhonemesRespelling
sonic-3.6, sonic-3.5 and sonic-3 (Cartesia)SpokenSpoken
eleven_flash_v2_5, eleven_turbo_v2_5Not sent, respelling used insteadSpoken
eleven_multilingual_v2Not sent, respelling used insteadSpoken
eleven_v3Not sent, respelling used insteadSpoken
Every other voiceNot sent, respelling used insteadSpoken

Only the Cartesia models named above speak phonemes, and that list is exact rather than a family: a newer Cartesia model is not covered until it has been measured. Everywhere else a phoneme rule falls back to the entry's respelling, and a rule with no respelling does nothing at all. That is why supplying both is worth the extra field: the phonemes give you exact control where they work, and the respelling keeps the rule alive everywhere else.

Phonemes are never sent to a model that cannot speak them. On several models a phoneme would delete the word from the sentence entirely rather than mispronounce it, which is worse than leaving it alone. If you write only phonemes and the assistant runs on one of those voices, the word is simply said as spelled.

A related trap is worth naming. Some catalogue voices are served by a newer model than their name suggests, so a voice whose name implies phoneme support may still fall back to the respelling. Treat the respelling as the rule that always applies and phonemes as the refinement.

One more thing about phonemes, and it catches people out: they are read with the accent of the voice speaking them. Phonetic notation looks like it ought to be accent-neutral, and it is not. The same k a t comes out as the French word on a French voice and as the English name "Kate" on an English one. A rule that is only correct in one language therefore needs a voice in that language, and setting the entry's language will not fix it, because language decides when a rule applies and never how it sounds. If a French pronunciation comes back anglicised, check which voice the assistant is using before you change the rule.

Recognition terms by transcriber#

TranscriberRecognition terms
universal-3-5-pro, universal-streaming (AssemblyAI)Applied
nova-3 and nova-3-medical (Deepgram)Applied
flux-general family (Deepgram)Applied
ink-2 (Cartesia)Applied
ink-2-multilingual (Cartesia)Applied
ink-whisper (Cartesia)Not sent: measured to accept terms and do nothing with them
Every other transcriberNot sent: never verified as safe

"Not sent" is doing real work in that table. Nothing reaches the engine in either of those rows, and only the reason differs. On an unverified engine, attaching recognition terms does not merely fail: it can stop the transcriber starting at all, and the call transcribes nothing. OnCore therefore refuses to send terms to any engine it has not verified as safe, so an unlisted or brand-new transcriber silently receives none. A dictionary that quietly does nothing is a far better outcome than a call with no transcript. ink-whisper is the milder case: it accepts terms and was measured to do nothing with them, so OnCore withholds them rather than send a parameter that buys nothing.

How much difference terms make depends on the engine. A strong transcriber often gets your brand name right unaided, and the terms change nothing. A weaker one, or a noisy phone line, is where they earn their place.

How many terms reach a supported engine is capped too, counted across every list one assistant uses: see the combined recognition-term cap.

Writing a pronunciation#

A pronunciation entry gives OnCore the sound you want, in one or both of two forms.

Respelling#

A respell is the word rewritten so an English-reading voice says it correctly. There is no formal notation. Write what you would tell a colleague who had to read the word aloud, and use hyphens to break syllables when the word is long.

WordRespellingWhy
QuatreKatGets the short vowel. Kate would be read as the English name.
Rinnairin eyeStops the voice rhyming it with "Sinai".
AriaAR-ee-uhCapitals mark the stressed syllable.

This is the form that works on every voice, so write one even when you also write phonemes.

A respelling is letters handed to the voice, not a specification of sound, so the voice reads it with its own accent. Avoid spellings that collide with a real word or name, because the voice will read the word it recognises. Kate for Quatre is the trap: it is a common English name, so an English-reading voice says the long-A name rather than the short vowel you wanted. Kat avoids the collision. Where you need the sound to be exact rather than approximated, that is what phonemes are for.

Phonemes#

A phonemes value is the International Phonetic Alphabet spelling of the word. It gives exact control, and on the voices that support it the result is not an approximation.

Write one space-separated token per sound. This is the rule that catches people out. A token is a single phoneme, and multi-character IPA symbols stay together inside one token rather than being split on their characters.

WordCorrectWrongWhat goes wrong
Quatrek a tkatOne token means one sound, so the whole thing is treated as a single phoneme.
cheesetʃ iː zt ʃ iː ztʃ is one sound. Split, it becomes two.
dayd eɪd e ɪeɪ is one diphthong, not two vowels.

To find the IPA for a word, use a dictionary that publishes it. Wiktionary lists IPA for most words and proper nouns, and shows separate British and American forms where they differ. Pick the one matching the accent of the voice you are using.

A phonemes value is at most 200 characters, and may not contain <, > or |. Those are rejected on write rather than silently stored, because they are provider markup, and storing one would tie your dictionary to a single engine and read out as gibberish on any other.

Limits#

A term or word is at most 50 characters. Longer entries are rejected, because oversized terms degrade the surrounding transcript rather than just failing. A respelling is at most 100 characters and a phonemes value at most 200. Each dictionary holds at most 100 entries. Phonemes must be plain space-separated IPA symbols, so provider-specific markup is rejected at write time rather than being read aloud on a call.

The combined recognition-term cap#

Recognition terms carry a second limit that spans everything one assistant uses. The first 100 terms are sent, counted in the combining order above, so linking several full dictionaries can leave the ones lowest in the order unreached. Pronunciations have no combined limit.

Language#

Both kinds of entry take an optional language. In the dashboard this is a dropdown of the same codes. Over the API it must be one of those codes. Leave it unset (or pick All languages) and the entry applies on every call.

CodeLanguage
enEnglish
frFrench
deGerman
esSpanish
itItalian
ptPortuguese
arArabic
nlDutch
hiHindi
ruRussian
jaJapanese

Those are the languages OnCore detects as the call runs. A locale such as en-AU or fr-CA is accepted and stored as the base code (en, fr). Names (english) and codes the detector cannot settle on (ko, zh) are rejected. A stored tag that never matches a turn is a silent no-op, so the API refuses it rather than accept any 2–10 character string.

Set a code and what happens next differs between the two kinds, because the two decisions are made at different moments in the call.

Pronunciations use it. Which rules apply is worked out fresh for every reply, once OnCore has settled which language that reply is in, which it detects automatically as the call runs. Tag a rule fr and it applies on French turns and stays out of the way on English ones. This holds even when the transcriber is set to multilingual, because the rule follows the language of the speech rather than the transcriber setting. Until a language has been settled the reply is treated as English, and the assistant's greeting is what establishes it, so a French greeting means French from the first turn.

What language never does is change how a rule sounds. If a French rule comes back anglicised even though it is tagged fr and firing on French turns, the voice is the cause rather than the tag: see Pronunciations by voice model above.

Recognition terms use it only when the transcriber is set to a single language. Terms reach the transcriber as the call connects, before anyone has spoken, so there is no detected language yet to match a tag against. On a transcriber set to fr, a term tagged en is left out. On a multilingual transcriber every term is sent, whatever its tag says.

So on a multilingual assistant, scope recognition terms by keeping them in separate dictionaries and linking only the ones that assistant needs. There, linking is what scopes them, not the tag.

Next steps#