Reference

Create an Avatar and an Agent

← Back to Agent Components

Create an Avatar

POST https://api.avatar.us.kaltura.ai/v1/avatar/create
{
  "voice": { "id": "KbakCphLGyrStJ2sp8mp", "speed": 1.0 },
  "visual": {
    "id": "f5a6b7c8-d9e0-4f1a-2b3c-4d5e6f7a8b9c",
    "motionControl": { "speaking": 0.7, "nonSpeaking": 0.2 }
  },
  "name": "Support rep"
}

Server-enforced ranges: voice.speed 0.5–1.5; motionControl.speaking and motionControl.nonSpeaking each 0.1–1.0 (keep nonSpeaking below speaking); name up to 255 characters. A value outside these ranges is a 400.

voice.id and visual.id come from the catalog (Catalog & Assets § Browse the Catalog). For your own portrait, upload it first and use the returned itemId as visual.id (§ Upload a Custom Visual, which also covers how to prepare the photo). Returns id (24-char hex). No adminTags on avatars: tag the parent agent instead (Management Operations § Avatars).

Leave openingPhrase unset. The intellect's opening_phrase owns the first, uninterruptible turn of every session (Configure an Intellect); provision() writes it there and creates the avatar without a phrase. An avatar-level openingPhrase is spoken only for a session whose intellect has none. Clear one with avatars.update({ id, openingPhrase: null }, ks). Where the phrase lives, how to personalize it with Jinja2, and the silent-opening + kickoff pattern: Start the Conversation.

Three ways to get a visual

avatar/create needs exactly one of these to resolve a visual — pick one:

Way Body When
An existing Visual visual: { id } Fastest — a catalog preset, or your own upload via catalog.createVisual. Wins only if face/background are both omitted, or both sent together as a complete pair. Sending just one of face/background alongside visual is still a domain error (see the row below) — visual does not exempt it.
Compose a new Visual from a Face + Background face: { id } + background: { type: 'color', value?: '#hex' } (value optional, defaults to white) or { type: 'visual', value: <Background catalog itemId> } (value required) You want a specific face (a catalog.createFace upload, or a preset Face item) over a specific backdrop. face/background must travel together at create time; you can't send face now and add background later. Sending just one of them still returns an HTTP 200 with a domain error in the body (AVATAR_MISSING_VISUAL_RESOLUTION), even if visual is also sent — unless templateId is also given: a template can carry its own face and/or background, filling in whichever half you didn't send.
A curated template + whatever it's missing templateId + whichever of face/background/visual the template doesn't already supply Fastest good-looking result — see below. templateId alone is a domain failure unless the template already resolves to a complete visual on its own.

For background.type: 'color', value must be a plain 6-digit hex string (#RRGGBB) with no alpha channel: an 8-digit hex (#RRGGBBAA), rgba(...), or CSS4 rgb(... / ...%) all fail with AVATAR_INVALID_BACKGROUND_ID ("must be a 6-digit hex value"), live-confirmed against production.

An incomplete or invalid pairing is an HTTP-200 KalturaAPIException (AVATAR_MISSING_VISUAL_RESOLUTION, AVATAR_FAILED_TO_COMPOSE_VISUAL, AVATAR_MISSING_VOICE, AVATAR_NOT_FOUND). avatars.create catches the incomplete-pairing case before any network call.

Whichever way you pick, the composed result is reflected in the created avatar's visual.composition and a fresh raw previewImageUrl/loadingVideoUrl (backend asset URLs, not the rendered live-session composite). Inspect those to see what was actually built, rather than assuming the inputs alone describe the output. Changing the composition after create follows different rules: Management Operations § Avatars.

Faster path — pick a curated preset instead of assembling voice+visual by hand: mgmt.avatars.listTemplates(ks, opts) lists curated bundles, each pairing a voice with either a ready visual or a face/background pair. Pass the template's own id as templateId; if the template's face/background isn't already a complete pair, add whichever half it's missing:

const templates = await mgmt.avatars.listTemplates(ks, { pageSize: 10 });
const t = templates[0]; // { id, name, voice: { id }, face: { id, imageUrl } }
await mgmt.avatars.create(
  { voice: t.voice, templateId: t.id, background: { type: 'color', value: '#ffffff' } },
  ks,
);

Compose from a custom Face and Background

Upload the two halves first (Catalog & Assets § Upload a custom Face or Background), then pass their ids as face.id and background.value:

const face = await mgmt.catalog.createFace(portraitBlob, { name: 'Support rep', genderPresentation: 'Feminine' }, ks);
const bg = await mgmt.catalog.createBackground(backdropBlob, { name: 'Office', genderPresentation: 'Feminine' }, ks);
await mgmt.avatars.create(
  { voice: { id: voiceItemId }, face: { id: face.itemId }, background: { type: 'visual', value: bg.itemId } },
  ks,
);

Unlike createVisual (a photo used directly, already a full custom digital twin), a Face/Background is only usable through the face+background composition. It can't be passed as visual.id on its own.


Create an Agent

POST https://api.avatar.us.kaltura.ai/v1/agent/create
{
  "displayName": "StreamBot Support Agent",
  "intellect": {
    "intellectType": "genie",
    "id": 1389
  },
  "avatarIds": ["6a07d63d8ccd85cbfafc5416"],
  "adminTags": ["support"],
  "maxConversationLength": 900
}
Field Notes
intellect.intellectType "genie" — the only value mgmt.intellects.create() can produce today. The field also accepts "external", for an intellect created and managed outside this SDK.
intellect.id The intellect's configId, from intellect create — passed straight in, no discovery step
avatarIds Optional — omit for a headless text-only agent
maxConversationLength Seconds. Omit to use the backend's own default
widgetConfig / embedConfig Optional, opaque config objects for the hosted widget/embed. Omit unless you're customizing widget or embed behavior

Returns agentId (UUID). Save this.


Doc What it adds
Agent Components · Create and Configure an Intellect The intellect an agent's intellect.id points at
Agent Components The Agent Components index
Click to talk with Nova — she knows this whole SDK.
Nova AI assistant — knows this whole site

Reloading starts a fresh chat. “New conversation” does the same without leaving the drawer.