Reference

Conversation & Analytics

← Back to the API Reference index

Converse

POST https://genie.nvp1.ovp.kaltura.com/assistant/converse

Requires a conversation KS (see Authentication § KS types):

CONV_KS=$(curl -s -X POST "https://www.kaltura.com/api_v3/service/session/action/start" \
  -d "format=1" -d "secret=$AGENTIC_ADMIN_SECRET" \
  -d "partnerId=$AGENTIC_PARTNER_ID" -d "type=2" -d "expiry=86400" \
  -d "privileges=geniegpcid:1389" | tr -d '"')
{
  "userMessage": "How do I fix video buffering?",
  "threadId": null,
  "sse": false
}
Field Notes
userMessage Required
threadId Omit for new conversation; pass previous value for memory
sse false = NDJSON (default); true = SSE
model_type "fast" for cheaper/faster model
force_experience Must be one of markdown, summarization, flashcards, avatar_only. Anything else 422s before any network call. A hint to the brain about which experience to render, not a guaranteed outcome.
request_vars {{var}} interpolation values. Needs allow_client_variables:true on the intellect (see Authentication § The Five Services for what an intellect is). Values persist on the thread: the server merges each message's map into what's stored, so send only deltas — a new thread starts clean. They interpolate into both prompt blocks and server-side api-tool templates. Reserved sys__* keys (including sys__user_id) are server-injected and rejected if you try to set them yourself — see § Bind a session to a real end-user identity above for how sys__user_id gets populated. Semantics in depth: Dynamic Data Injection.
capabilities Per-message capability override

Enabling allow_client_variables: mgmt.intellects.setClientVariablesEnabled(configId, true, adminKs) (WRITE, admin KS; also exposed as mgmt.intellectConfig.setClientVariablesEnabled).

With it off, the rejection is silent on every path. The turn streams back empty: no HTTP error on converse, no socket error. The server's 403 fires inside its streaming pipeline after the response has already opened, so it never reaches the wire.

Both session classes (KalturaAvatarSession, KalturaChatSession) detect the pattern and emit a once-per-session warning event (code: 'empty_turn_with_request_vars', variable names only, never values). The management converse helpers keep a defensive remap to a typed client_variables_disabled error for the pre-stream case, should the server ever start rejecting before the stream opens.

Stream segments (each line is a JSON object):

type Meaning
"think" Processing (show spinner)
"text" Response content — concatenate content fields. On an avatar-enabled intellect, spoken content streams as "avatar" (and "avatar-filler") instead, accumulated the same way.
"tool" / "tool_response" Server tool call + result; content carries client commands
"unisphere-tool" GenUI widget — metadata.runtimeName names the widget
"error" Brain error
"user-interruption" User barged in

Key envelope fields: threadId (save for follow-ups), messageId (save for feedback), isFinal:true (stream done).

Abort a running turn:

POST https://genie.nvp1.ovp.kaltura.com/assistant/abort
{ "threadId": "154a05c4-..." }

Reserved Template Variables (sys__*)

The server sets these on every turn. They're available to {{ ... }} interpolation in base_directive / prompts[].value / glossary (see Configure an Intellect) and in a Skill's instructions text (see § Skills), regardless of allow_client_variables.

Before any network call, the SDK's own request_vars pre-flight guard rejects a client-supplied value for any key in the table below, plus secrets (see request_vars above):

Variable Resolves to Notes
sys__thread_id Current conversation thread id
sys__message_id Current message id
sys__user_id The bound end-user id Empty by default (an anonymous KS). Bind a real identity with Sessions.createConversationToken({ userId }) (or createAdminToken({ userId })) so this resolves server-side instead of always being empty — see § Bind a session to a real end-user identity above.
sys__user_message The current turn's user text
sys__is_new_thread true on the first turn of a new thread, false otherwise
sys__avatar_enabled Whether the current thread has a live avatar attached Used in a Skill's condition to gate it to avatar-only sessions, e.g. {{ sys__avatar_enabled }} — see Configure an Intellect § skill_ids.
sys__avatar_share_screen_enabled Whether the current avatar session has screen-share analysis enabled Also usable in a Skill's condition, e.g. {{ sys__avatar_enabled and not sys__avatar_share_screen_enabled }} to gate a skill to avatar sessions that are NOT sharing a screen.
sys__context_id The category/entry id the current context (and its knowledge base, if any) is scoped to Set via KalturaAvatarSession's contextId constructor option, sent on the live socket join payload — see System Internals Reference · Connection and Handshake § The join payload. Empty when no context was set at join.
sys__context_type The type of that context (e.g. an entry vs. a category) Set via KalturaAvatarSession's contextType constructor option, alongside contextId; empty when no context was set at join.
sys__ks The raw Kaltura Session token for the current request ⚠️ Security warning: never reference sys__ks in a prompt whose output could be echoed back to a user or logged. It is a live credential. Rendering it as plain text in a model response, chat transcript, or log can leak that credential. See Security & Compliance.
sys__user_obj.first_name / .last_name / .title / .company / .gender / .email Attributes of the bound-user object Verify these resolve with intellects.previewPrompt() before shipping a prompt — the rendered preview flags unresolved references with a reserved_user_attr_unresolved warning.
secrets.<NAME> A named secret configured on the intellect Write-only — see § Secrets.

Check Status

GET https://genie.nvp1.ovp.kaltura.com/assistant/status

Returns {aiConsent, avatar, identifiedUser}. avatar is non-null when the agent has an avatar configured.


Threads

All thread endpoints require an admin KS (disableentitlement). Pager: {"pageIndex":1,"pageSize":30}.

Operation Endpoint Body
List POST .../v1/thread/list {"filter":{"objectType":"ListThreadFilter"},"pager":{"pageIndex":1,"pageSize":30}}
Get POST .../v1/thread/get {"id":"UUID"}
Rename POST .../v1/thread/update {"id":"UUID","title":"New name"}
Delete POST .../v1/thread/delete {"thread_ids":["UUID"]}
Transcript POST .../v1/thread/get_transcripts {"id":"UUID"}

... = https://genie.nvp1.ovp.kaltura.com

Thread list response fields per object: id, title, created_at, updated_at, status.

Transcript response: {"status":"success","data":"human: …\nai: …"} — plain text, one turn per line.

Delete returns {totalCount, objects[]} — a soft delete, followed by a scheduled infra-level purge of the underlying data.

SDK: mgmt.threads.{list, get, rename, delete, transcript}. Two more write operations live only on the SDK (setAnalysis, clearAnalysis, push); see Management Operations § Threads for their request shapes.

Compliance note. threads.delete() soft-deletes immediately; a scheduled infra-level purge erases the underlying data later. See Security & Compliance for what the SDK provides versus what the operator must configure.

Session-Completion Signal

Unlike the admin-KS thread endpoints above, this one is called from the browser client itself, with the same conversation KS (geniegpcid) used for every other client-facing call. It mints nothing new and needs no elevated privilege.

Operation Endpoint Body Auth
Session completed POST {genieUrl}/thread/session_completed {"id":"<threadId>"} Authorization: KS <conversation ks>

{genieUrl} defaults to https://genie.nvp1.ovp.kaltura.com (no /v1 prefix — a different route family from the thread CRUD above). It's idempotent: a repeat call for the same thread is a no-op server-side. There's no rate limit. It can block up to ~10s on a backend publish-ack, so a client must never await it on a page-unload path.

Call this the moment a conversation is genuinely over, instead of waiting for the server's idle timeout (about 10 minutes), so end-of-conversation lifecycle rules (summaries, insights, CRM pushes) fire in seconds.

KalturaAvatarSession/KalturaChatSession/KalturaAgentSession call this automatically on disconnect() (sessionCompleteOnEnd, default true) and on tab-close/backgrounding/bfcache. See README.md § Ending a conversation cleanly for the full config surface, and Wire Protocol · Events Catalog § Session-completion signal for the exact request shape.

Thread History and Context Size

There is no documented cap on how long a thread's history can grow. The full transcript is sent as model context on every turn, so the context each turn carries grows with thread length. Plan long-running threads accordingly: start a fresh thread per task, and delete threads you don't need.


Feedback and Follow-ups (SDK)

Feedback and follow-up suggestions route through internal Genie paths — use the SDK rather than calling them directly.


Usage Analytics

Partner-scoped read-only CSV — contains end-user IDs and verbatim questions (treat as PII).

SDK: mgmt.messages.report(ks) (raw CSV) / mgmt.messages.reportSummary(ks) (volume + feedback ratio + top questions, with a _meta provenance receipt).

mgmt.messages.get(id, ks) (POST {genieUrl}/message/get) fetches one message record directly, without paging through messages.list(). An unknown id throws a typed not_found; one belonging to another partner throws forbidden instead.


Knowledge Search (MCP)

POST https://genie.nvp1.ovp.kaltura.com/mcp/search
{ "query": "adaptive bitrate streaming" }

Returns {status, data}. A partner with no indexed content returns a "couldn't find relevant information" error response. SDK: mgmt.knowledge.search(query, ks, opts).

opts passes through five optional tuning params, all accepted as-is by the backend:

Param Default
top_n 5
with_line_numbers —
margins_in_seconds 15
include_sources —
entry_description —

include_sources:true changes the success shape's chapters from null to an array, and text to null.

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.