Skip to main content

Entity management

Use entities to keep speaker identity stable across recordings.

Core model​

  • entity.id is the persistent voice identity key.
  • entity.label is an optional human-readable name.
  • Your own database should store pipeline state (stage, status, cohort, owner, etc.).

Resolve then reuse entity IDs​

const firstReceipt = await conduitClient.reports.create({
source: { url: "https://example.com/intro-call.mp3" },
output: { template: "general_report" },
target: { strategy: "magic_hint", hint: "the candidate" },
})
const first = await firstReceipt.handle?.wait()

const entityId = first?.entity?.id
if (!entityId) throw new Error("Entity not resolved")

await db.people.update({ id: "person_123", conduitEntityId: entityId })

const followUpReceipt = await conduitClient.reports.create({
source: { url: "https://example.com/follow-up.mp3" },
output: { template: "general_report" },
target: { strategy: "entity_id", entityId },
})
const followUp = await followUpReceipt.handle?.wait()

Label entities​

await conduitClient.primitives.entities.update("ent_abc123", { label: "candidate:john-doe" })

const entity = await conduitClient.primitives.entities.get("ent_abc123")
console.info(entity.label)

Clear label:

await conduitClient.primitives.entities.update("ent_abc123", { label: null })

Build a local speaker registry​

interface SpeakerRecord {
id: string;
conduitEntityId?: string;
stage: "new" | "screen" | "technical" | "final" | "hired";
}

async function analyzeSpeaker(speaker: SpeakerRecord, mediaId: string) {
const target = speaker.conduitEntityId
? { strategy: "entity_id" as const, entityId: speaker.conduitEntityId }
: {
strategy: "magic_hint" as const,
hint: "the candidate",
onMiss: "fallback_dominant" as const,
};

const receipt = await conduitClient.reports.create({
source: { mediaId },
output: { template: "general_report" },
target,
})

const report = await receipt.handle?.wait()
if (!report) throw new Error("Report handle missing")

if (!speaker.conduitEntityId && report.entity?.id) {
await db.speakers.update({ id: speaker.id, conduitEntityId: report.entity.id })
}

return report
}

Best practices​

  • Persist entity.id after the first successful report.
  • Prefer entity_id targeting after identity is known.
  • Keep business metadata in your DB, not in SDK entity fields.
  • Use conduitClient.primitives.entities.list() for audits and reconciliation tasks. It uses cursor pagination with a default limit of 20, max 100, and latests first ordering.