Entity disambiguation
ProWhen a name matches more than one thing ("Account" the table, the report, the record type), the agent asks which one instead of guessing. Each candidate shows its kind, API name and what sets it apart. "None of these" is always offered. Once chosen, the card shows the answer.
Preview
Install
With the Candor CLI
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/entity-disambiguation
Brings in: chat, entity-chip, locale, terms, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import * as React from "react"
import { EntityDisambiguation, type EntityCandidate } from "@/components/entity-disambiguation"
import type { EntityRef } from "@/lib/chat"
const candidates: EntityCandidate[] = [
{ entity: { kind: "table", name: "public.orders", label: "orders" }, detail: "Table in the main database, 1.2M rows" },
{ entity: { kind: "report", name: "reports/orders-weekly", label: "Orders" }, detail: "Weekly report in the Finance folder" },
{ entity: { kind: "workflow", name: "flows.orders_sync", label: "Orders sync" }, detail: "Runs every hour on Staging" },
]
export default function Example() {
const [chosen, setChosen] = React.useState<EntityRef | null | undefined>(undefined)
return (
<div className="flex max-w-lg flex-col gap-3">
<EntityDisambiguation term="orders" candidates={candidates} onChoose={setChosen} onNone={() => setChosen(null)} chosen={chosen} />
{chosen !== undefined && (
<button type="button" onClick={() => setChosen(undefined)} className="self-start text-xs text-muted-foreground underline underline-offset-2">
Ask again
</button>
)}
</div>
)
}<EntityDisambiguation>
| Prop | Type | Default | Description |
|---|---|---|---|
| termrequired | string | — | What the person typed, e.g. "Account". |
| candidatesrequired | EntityCandidate[] | — | The things the term could mean, with kind, API name and what sets each apart. |
| onChooserequired | (entity: EntityRef) => void | — | Called with the chosen entity. |
| onNone | (() => void) | undefined | — | Shows "None of these"; called when it's picked. |
| chosen | EntityRef | null | undefined | — | The settled choice, if one was made. |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under entityDisambiguation in <LocaleProvider strings={{ … }}>; the table is exported as entityDisambiguationStrings.
| Key | English |
|---|---|
| means | “{term}” means |
| none | None of the matches for “{term}”; the agent will ask what you meant. |
| question | { one: "“{term}” matches {count} thing in the {environment}. Which one?", other: "“{term}” matches {count} things in the {environment}. Which one?", } |
| noneOfThese | None of these |
Types
- EntityCandidate
{ entity: EntityRef /** What tells it apart: "Standard object, 18,240 records", "Report in Sales folder". */ detail: string }