Enrich the same kind of entity again and again and you keep re-discovering the same real-world things — the same company, the same drug side-effect, the same person — described with slightly different words each time. A semantic ID is a stable, organization-scoped identifier Entity Enricher assigns to an object from its key fields, so those near-duplicates collapse to one identity you can group, deduplicate, and join on.
An object’s identity is built from its key fields — and there can be one or several. Two examples:
nameIt shows up as Headache, Céphalée, and Cephalalgia across runs and languages. One key field, three spellings, one real concept.
name + countryAcme Inc. · United States and Acme Incorporated · United States are the same company — while Acme Inc. · Germany is a different one. The second key disambiguates; that’s why an object can carry more than one.
Plain string matching fails on all of these; a human knows which are the same. Semantic IDs encode that judgement automatically.
string property on an object (named id by default), holding an opaque, stable identifier.manufacturer), or each item in an array (e.g. each side_effect).After the model returns its result, Entity Enricher resolves each semantic ID in six steps — cheapest first. The four steps before the embedding are pure text comparison, so an identity settled there costs nothing at all:
null in its parent, and an item inside a list is dropped from the list. The enriched entity itself is never removed; it simply has no ID.LC-39A unifies every way the rest of the text was written. Just as importantly it works the other way round: a different code vetoes a merge the embedding step would otherwise have accepted, because two things with different identifiers are two things however alike they read.“Boeing” and “The Boeing Company”. This catches exactly the verbosity differences that embeddings measure as far apart, and it costs nothing: like the exact-text step, a hit here means no embedding call and no charge.“Acme Inc.” and“Acme Incorporated” land next to each other.0.92, tunable per property), that concept’s ID is reused. Otherwise a brand-new ID is minted and stored for next time. One exception overrides a high score: when the two texts are the same words counted differently — “second stage” and“third stage” — they are treated as different things, because counting is exactly what tells them apart. The same number written two ways (2 andII) still matches.Threshold trade-off: a higher threshold is stricter (fewer accidental merges); a lower one is looser (more aggressive deduplication). Tune it per property when the default 0.92 over- or under-merges.
Whether an ID is generated depends on whether one is already present in the input for that object. This is what lets you round-trip: enrich once to obtain IDs, then pass a known ID back on later runs to attach new facts to the same identity — cheaper and unambiguous.
If the object you send already carries a semantic ID, it’s treated as a lookup: the ID is kept verbatim, the record is linked to that existing concept, and there is no embedding — no cost, no match-or-mint. You’re telling the platform “this object is already identified in our database.”
If the object has no semantic ID, the platform generates one with the steps above. That ID becomes the object’s stable identifier in your organization’s database from then on.
A present-but-unrecognizable value (not a real concept ID) is ignored, and an ID is generated instead.
Resolution costs a small amount of embedding usage per enrichment (metered like any model call). The exact-match cache makes repeats free, and input-provided IDs cost nothing.
Resolved IDs appear in the enrichment output JSON (the id field on each object), in the record detail’s semantic concepts, and all together on the Semantic IDs page, where the vocabulary they form is browsed and curated. Use them to:
Fusion reconciles disagreements across models within a single run; semantic IDs reconcile the same entity across runs and time. The two work together.