Skip to main content

๐Ÿค– Agent Service

An agent is where everything comes together โ€” it's the character your users will talk to.

An agent links an avatar (the face and voice) with an intelligence engine (the AI backend that understands and responds), and defines how the conversation should behave. Once an agent is configured here, the Control API can spin up real-time sessions backed by it.

Base route: POST /service/agent/action/{actionName}

Data Modelโ€‹

Agent
โ”œโ”€โ”€ agentId string (UUID)
โ”œโ”€โ”€ displayName string
โ”œโ”€โ”€ intellect
โ”‚ โ”œโ”€โ”€ intellectType 'genie' | 'external'
โ”‚ โ”œโ”€โ”€ configId number
โ”‚ โ””โ”€โ”€ genieId string
โ”œโ”€โ”€ avatarIds string[]
โ”œโ”€โ”€ maxConversationLength number (1โ€“3600s)
โ”œโ”€โ”€ widgetConfig
โ”‚ โ”œโ”€โ”€ initialPage.title string
โ”‚ โ””โ”€โ”€ layouts.avatar / layouts.chat boolean
โ”œโ”€โ”€ embedConfig
โ”‚ โ””โ”€โ”€ theme string
โ”œโ”€โ”€ adminTags string[]
โ”œโ”€โ”€ partnerId number
โ”œโ”€โ”€ createdAt / updatedAt Date
โ””โ”€โ”€ createdBy string

Agent Fieldsโ€‹

FieldTypeDescription
agentIdstring (UUID)Unique identifier for the agent
displayNamestringHuman-readable name for the agent
intellectobjectThe AI engine configuration (see below)
avatarIdsstring[]IDs of avatars assigned to this agent
maxConversationLengthnumberMax session length in seconds (1โ€“3600)
widgetConfigobjectWidget UI configuration (optional)
embedConfigobjectEmbed theme configuration (optional)
legacyScreenShareobjectScreen share settings (optional)
adminTagsstring[]Tags for filtering and organization
partnerIdnumberYour Kaltura partner ID
createdAtDateCreation timestamp
updatedAtDateLast modification timestamp
createdBystringUser ID who created the agent

Intellect Configurationโ€‹

What's an "intellect"?

The intellect defines the AI engine that powers the agent's conversations. Currently two types are supported:

  • genie โ€” Kaltura's built-in conversational AI engine. Provide a configId that references an intellect created via the ๐Ÿง  Intellect Service. The intellect controls prompts, glossary, capabilities, and can attach a ๐Ÿ“š Knowledge base.
  • external โ€” An external AI backend. Provide a configId that references your external configuration.
FieldTypeRequiredDescription
intellectType'genie' | 'external'โœ… YesThe type of intelligence engine
configIdnumberโœ… YesIntellect partner config ID โ€” see ๐Ÿง  Intellect Service
genieIdstringโœ… YesGenie instance ID

Widget Configurationโ€‹

Controls how the embedded chat widget looks and behaves:

FieldTypeDescription
widgetConfig.initialPage.titlestring (max 30 chars)Title shown on the widget's initial screen
widgetConfig.layouts.avatarbooleanWhether to show the avatar in the widget
widgetConfig.layouts.chatbooleanWhether to show the chat panel

Embed Configurationโ€‹

FieldTypeDescription
embedConfig.themestringVisual theme for the embedded widget

Actionsโ€‹

get โ€” Retrieve an Agentโ€‹

POST /service/agent/action/get

Request body:

{
"agentId": "550e8400-e29b-41d4-a716-446655440000"
}
FieldTypeRequiredDescription
agentIdstringโœ… YesThe UUID of the agent to retrieve

Response:

{
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"displayName": "Customer Support Assistant",
"intellect": {
"intellectType": "genie",
"genieId": "genie_abc123",
"configId": 42
},
"avatarIds": ["64f1a2b3c4d5e6f7a8b9c0d1"],
"maxConversationLength": 1800,
"adminTags": ["production", "support"],
"partnerId": 12345,
"createdAt": "2024-01-15T10:30:00.000Z",
"updatedAt": "2024-01-20T14:22:00.000Z",
"createdBy": "admin@company.com"
}

Examples:

cURL
curl -X POST "https://YOUR_API_HOST/service/agent/action/get" \
-H "Authorization: KS YOUR_KS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agentId": "550e8400-e29b-41d4-a716-446655440000"
}'
JavaScript
const agent = await fetch('https://YOUR_API_HOST/service/agent/action/get', {
method: 'POST',
headers: {
Authorization: `KS ${ksToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
agentId: '550e8400-e29b-41d4-a716-446655440000',
}),
}).then((res) => res.json());

console.log(`Agent: ${agent.displayName}`);

Error responses:

StatusDescription
401Invalid or expired KS token
404Agent not found

list โ€” List Agentsโ€‹

POST /service/agent/action/list

Retrieve a paginated list of agents, with optional filtering.

Request body:

{
"filter": {
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"adminTagsIn": ["production"]
},
"pager": {
"offset": 0,
"limit": 30
},
"orderBy": "-createdAt"
}
FieldTypeRequiredDescription
filter.agentIdstringNoFilter to a specific agent ID
filter.adminTagsInstring[]NoFilter by any of these admin tags
pager.offsetnumberNoPagination offset (default: 0)
pager.limitnumberNoMax results per page (default: 30)
orderBystringNoSort order: +createdAt, -createdAt, +updatedAt, -updatedAt

Response:

{
"objects": [
{
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"displayName": "Customer Support Assistant",
...
}
],
"totalCount": 5
}

Examples:

cURL โ€” list all agents, newest first
curl -X POST "https://YOUR_API_HOST/service/agent/action/list" \
-H "Authorization: KS YOUR_KS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"pager": { "offset": 0, "limit": 30 },
"orderBy": "-createdAt"
}'
JavaScript โ€” list agents with tag filter
const { objects, totalCount } = await fetch('https://YOUR_API_HOST/service/agent/action/list', {
method: 'POST',
headers: {
Authorization: `KS ${ksToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
filter: { adminTagsIn: ['production'] },
pager: { offset: 0, limit: 30 },
orderBy: '-createdAt',
}),
}).then((res) => res.json());

console.log(`Found ${totalCount} production agents`);

create โ€” Create an Agentโ€‹

POST /service/agent/action/create

Request body:

{
"displayName": "Customer Support Assistant",
"intellect": {
"intellectType": "genie",
"genieId": "genie_abc123",
"configId": 42
},
"avatarIds": ["64f1a2b3c4d5e6f7a8b9c0d1"],
"maxConversationLength": 1800,
"adminTags": ["production"],
"widgetConfig": {
"initialPage": {
"title": "How can I help?"
},
"layouts": {
"avatar": true,
"chat": true
}
}
}
FieldTypeRequiredDescription
displayNamestringNoHuman-readable name
intellectobjectโœ… YesAI engine config (see Intellect Configuration)
avatarIdsstring[]NoAvatar IDs to assign to this agent
maxConversationLengthnumberNoMax session length in seconds (1โ€“3600)
adminTagsstring[]NoTags for filtering
widgetConfigobjectNoWidget UI settings
embedConfigobjectNoEmbed theme settings
legacyScreenShareobjectNoScreen share settings

Response: Returns the created Agent object with the generated agentId.

Examples:

cURL
curl -X POST "https://YOUR_API_HOST/service/agent/action/create" \
-H "Authorization: KS YOUR_KS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"displayName": "Customer Support Assistant",
"intellect": {
"intellectType": "genie",
"genieId": "genie_abc123",
"configId": 42
},
"avatarIds": ["64f1a2b3c4d5e6f7a8b9c0d1"],
"maxConversationLength": 1800
}'
JavaScript
const newAgent = await fetch('https://YOUR_API_HOST/service/agent/action/create', {
method: 'POST',
headers: {
Authorization: `KS ${ksToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
displayName: 'Customer Support Assistant',
intellect: {
intellectType: 'genie',
genieId: 'genie_abc123',
configId: 42,
},
avatarIds: ['64f1a2b3c4d5e6f7a8b9c0d1'],
maxConversationLength: 1800,
}),
}).then((res) => res.json());

// ๐ŸŽ‰ Your agent is alive!
console.log(`Created agent: ${newAgent.agentId}`);

Error responses:

StatusDescription
400Invalid request body (e.g., missing required intellect)
401Invalid or expired KS token

update โ€” Update an Agentโ€‹

POST /service/agent/action/update

Update a subset of an agent's fields. Only include fields you want to change โ€” omitted fields remain unchanged.

Request body:

{
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"displayName": "Updated Assistant Name",
"avatarIds": ["64f1a2b3c4d5e6f7a8b9c0d2"],
"maxConversationLength": 3600
}
FieldTypeRequiredDescription
agentIdstringโœ… YesThe agent to update
displayNamestringNoNew display name
avatarIdsstring[]NoReplace the full list of avatar IDs
maxConversationLengthnumberNoNew max length in seconds (1โ€“3600)
adminTagsstring[]NoReplace the full list of admin tags
widgetConfigobjectNoNew widget configuration
embedConfigobjectNoNew embed configuration
legacyScreenShareobjectNoNew screen share settings
Arrays are replaced, not merged

When you pass avatarIds or adminTags, the entire array is replaced. To add one avatar ID, fetch the current list first and include all existing IDs plus the new one.

Response: Returns the updated Agent object.

Examples:

cURL
curl -X POST "https://YOUR_API_HOST/service/agent/action/update" \
-H "Authorization: KS YOUR_KS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agentId": "550e8400-e29b-41d4-a716-446655440000",
"maxConversationLength": 3600
}'
JavaScript
const updatedAgent = await fetch('https://YOUR_API_HOST/service/agent/action/update', {
method: 'POST',
headers: {
Authorization: `KS ${ksToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
agentId: '550e8400-e29b-41d4-a716-446655440000',
maxConversationLength: 3600,
}),
}).then((res) => res.json());

delete โ€” Delete an Agentโ€‹

POST /service/agent/action/delete

Permanently deletes an agent. This cannot be undone.

Request body:

{
"agentId": "550e8400-e29b-41d4-a716-446655440000"
}
FieldTypeRequiredDescription
agentIdstringโœ… YesThe agent to delete

Response:

{
"agentId": "550e8400-e29b-41d4-a716-446655440000"
}

Examples:

cURL
curl -X POST "https://YOUR_API_HOST/service/agent/action/delete" \
-H "Authorization: KS YOUR_KS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"agentId": "550e8400-e29b-41d4-a716-446655440000"
}'
JavaScript
await fetch('https://YOUR_API_HOST/service/agent/action/delete', {
method: 'POST',
headers: {
Authorization: `KS ${ksToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
agentId: '550e8400-e29b-41d4-a716-446655440000',
}),
});

Error responses:

StatusDescription
401Invalid or expired KS token
404Agent not found

getEmbedScript โ€” Get an Embeddable HTML Snippetโ€‹

POST /service/agent/action/getEmbedScript

The fastest way to put your agent in front of end users. Call this with an agentId and paste the returned HTML into any webpage โ€” no further configuration needed.

The response contains a <div> container and an inline <script> that loads the Unisphere widget, resolves the agent's Kaltura widget ID (creating one automatically if it doesn't exist), and initialises the chat interface.

Request body:

{
"agentId": "550e8400-e29b-41d4-a716-446655440000"
}
FieldTypeRequiredDescription
agentIdstring (UUID)โœ… YesThe agent to generate an embed script for

Response:

{
"html": "<div id='genie-container' style='width: 100%; height: 100vh'></div><script type='module'>...</script>"
}

Examples:

cURL
curl -X POST "https://YOUR_API_HOST/service/agent/action/getEmbedScript" \
-H "Authorization: KS YOUR_KS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "agentId": "550e8400-e29b-41d4-a716-446655440000" }'
JavaScript โ€” fetch and inject embed
const { html } = await fetch(
'https://YOUR_API_HOST/service/agent/action/getEmbedScript',
{
method: 'POST',
headers: { 'Authorization': `KS ${ksToken}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ agentId: '550e8400-e29b-41d4-a716-446655440000' }),
}
).then(res => res.json());

// Inject into your page
document.getElementById('agent-embed').innerHTML = html;
Drop-in vs. programmatic

getEmbedScript is the simplest delivery path โ€” one API call, paste the HTML, done. If you need programmatic control over the session (say-text, interrupt, keep-alive), use the โšก Control API instead.


Usage Notesโ€‹

Multiple Avatars per Agentโ€‹

An agent can have multiple avatar IDs assigned via avatarIds. This allows the Control API to select which avatar personality to use when starting a session. If no specific avatar is requested at session creation time, the first avatar in the list is used.

Widget vs. Embed Configโ€‹

  • widgetConfig โ€” controls the layout and initial state of the built-in chat widget (the iframe-embeddable UI Kaltura provides)
  • embedConfig โ€” controls visual theming when the widget is embedded in your site

If you're building a fully custom UI using the Control API directly, you can safely ignore both of these fields.

๐Ÿงช Advanced: Legacy Screen Share

The legacyScreenShare field enables an older screen sharing mode for the avatar session:

{
"legacyScreenShare": {
"enabled": true,
"prompt": "You can see the user's screen. Describe what you observe."
}
}

This injects the screen share prompt into the agent's conversation context when a screen share session is active. Use this if your integration relies on the legacy screen share mechanism.

Next Stepsโ€‹

  • ๐ŸŽญ Avatar Service โ€” Create the avatars referenced by avatarIds
  • ๐Ÿง  Intellect Service โ€” Configure the AI behind your agent
  • ๐Ÿ› ๏ธ Workflows โ€” See a complete agent setup from scratch
  • Embed your agent โ€” call getEmbedScript and drop the returned HTML into any webpage
  • โšก Control API โ€” Programmatic server-side session control