Widget and SDK Setup
Use the widget when you want Kravos.ai to own the customer chat surface: launcher button, iframe, session setup,
Widget and SDK Setup
Use the widget when you want Kravos.ai to own the customer chat surface: launcher button, iframe, session setup, pre-chat collection, voice handoff, end-chat feedback, and conversation history. Use the SDK and dashboard-domain SDK routes when you need to embed that same surface inside your product or build a thin custom wrapper around it.
Dashboard-domain, not public API v1
Widget routes live on your Kravos web app domain, for example https://app.kravos.ai/widget,
/sdk/v1/loader.js, /api/sdk/*, and /api/chat/stream. The server-to-server
public API lives at https://api.kravos.ai/v1. Do not move widget calls to the public API host unless the
endpoint is explicitly listed in API Reference.
Quickstart
Create an agent-scoped chat key
Open the agent's API keys page and create a key with the chat permission. The widget chooses its agent
from this key. There is no public agentId query parameter.
Configure the widget in the dashboard
Use Widget Settings to set colors, greeting text, pre-chat fields, voice, and embed surface.
Install on a staging page
Start with the script snippet from the Embed tab. Test the real page, not only the dashboard preview, because placement and domain allowlists are page-dependent.
Check the first conversations
After launch, review Conversations, Feedbacks, and Analytics for early traffic and answer quality.
Install Options
Script loader
The dashboard embed tab generates this option. It injects the iframe, adds a floating launcher button, validates messages from the iframe origin, and starts minimized.
<script src="https://app.kravos.ai/sdk/v1/loader.js" data-api-key="spk_..." data-position="bottom-right" async></script>
For the in-app suite surface, add data-mode="suite". The dashboard uses side-panel for suite installs.
<script
src="https://app.kravos.ai/sdk/v1/loader.js"
data-api-key="spk_..."
data-mode="suite"
data-position="side-panel"
async
></script>
Supported data attributes:
| Attribute | Values | Notes |
|---|---|---|
data-api-key | Agent-scoped key with chat permission | Required |
data-mode | suite | Omit for launcher mode |
data-position | bottom-right, bottom-left, side-panel | Mobile uses a bottom sheet layout |
data-base-url | Kravos web app origin | Optional; use only when instructed by Kravos.ai support |
Direct iframe
Use a direct iframe when your app already owns the launcher button or page layout. You must size and position the iframe yourself.
<iframe
src="https://app.kravos.ai/widget?key=spk_..."
title="Chat Widget"
allow="microphone; speaker-selection"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups"
></iframe>
Add &mode=suite for the suite surface. The widget route only reads key and mode; placement is handled by
the loader or by your host page CSS.
Package factory
The repo includes @kravos.ai/sdk with createChatWidget, useWidget, useChat, and
RealtimeConnection. The package is not currently distributed for customer use; use the script or iframe
integration instead.
import { createChatWidget } from '@kravos.ai/sdk'
const widget = createChatWidget({
apiKey: 'spk_...',
baseUrl: 'https://app.kravos.ai',
mode: 'launcher',
position: 'bottom-right',
user: { name: 'Jane Doe', email: 'jane@example.com' },
context: { pageUrl: window.location.href, pageTitle: document.title },
})
widget.open()
widget.setUser({ email: 'new@example.com' })
widget.setContext({ pageUrl: window.location.href })
widget.destroy()
Realtime hooks are low level
useChat and RealtimeConnection manage socket messages and typing state. The current
useChat().sendMessage() only adds an optimistic local message and stops typing; it does not call the
hosted chat streaming endpoint for you.
Configuration
Most widget behavior is dashboard-managed and stored on the selected agent. The runtime reads that config during
POST /api/sdk/init.
| Area | Runtime behavior |
|---|---|
| Agent | Selected by the agent-scoped API key |
| Surface | launcher by default, suite when mode=suite |
| Placement | Loader supports bottom-right, bottom-left, and side-panel; mobile is bottom |
| Theme | Primary color, header text, bubbles, input colors, font, border radius |
| Branding | Title, subtitle, logo URL, and powered-by badge |
| Behavior | Greeting and input placeholder |
| Pre-chat | Optional required name, email, and phone fields before chat starts |
| Voice | Launcher voice option when widget or agent voice config is enabled |
Some saved schema fields are not currently applied by the hosted runtime, including persistSession,
showTimestamps, avatarUrl, and iconColor. The dashboard also exposes auto-open
settings, but the current script loader starts minimized. Use package or loader programmatic control if you need to open
the widget from your own event.
Identity and External IDs
By default, the widget creates or resumes an anonymous embedded user using a browser session id stored under
single_chat_session_id. Passing unsigned user data can fill name, email, and
phone, but it is not proof of identity.
For logged-in products, use signed embedded identity. The iframe accepts identityToken through
identify() or a single-chat:identify postMessage. The server verifies a short-lived HMAC token
with these claims:
{
"tenantId": "tenant_...",
"agentId": "agent_...",
"externalUserId": "user_123",
"name": "Jane Doe",
"email": "jane@example.com",
"avatarUrl": "https://example.com/jane.png",
"claims": { "plan": "pro" }
}
Issue the token on your server, never in browser code. This app verifies signed identity, but it does not expose a public endpoint that creates identity tokens for you. If Kravos.ai has not configured an issuer for your account, use anonymous sessions or unsigned profile fields instead.
Conversation Lifecycle
Launcher mode creates or resumes the latest open web text conversation for the session. The user can end the chat, which closes the conversation and shows a 1–5 star feedback form with an optional comment.
Suite mode adds conversation history. It can list, create, open, rename, archive, and search the embedded user's web text conversations. The user's last opened suite conversation is stored in embedded preferences.
Important routes used by the widget and suite:
| Route | Purpose |
|---|---|
POST /api/sdk/init | Creates/resumes session, user, config, preferences, history |
POST /api/chat/stream | Sends a text message and streams the AI response |
GET /api/sdk/conversation | Refreshes the active launcher conversation |
PATCH /api/sdk/conversation | Closes a launcher conversation |
POST /api/sdk/new-chat | Starts a fresh text conversation |
GET/POST /api/sdk/conversations | Lists or creates suite conversations |
GET/PATCH /api/sdk/conversations/:id | Reads, renames, or archives a suite conversation |
GET /api/sdk/conversations/search | Searches suite conversation titles and messages |
GET/PATCH /api/sdk/preferences | Reads or updates locale, sidebar state, and last conversation |
PATCH /api/sdk/user | Updates unsigned user fields for the current session |
POST /api/sdk/feedback | Stores conversation-level rating and optional comment |
POST /api/sdk/voice/start | Starts an ElevenLabs-backed web voice conversation |
POST /api/sdk/voice/end | Ends the voice session and stores client transcript fallback |
Voice in the Widget
Voice appears in launcher mode when widget voice or the agent voice config is enabled. Starting voice requires:
- an agent voice configuration with an ElevenLabs agent
ELEVENLABS_API_KEYconfigured server-side- enough hosted credits and voice entitlement
- microphone permission in the browser
- an iframe or loader with microphone permission
If voice fails to start, the launcher falls back to text chat. Suite init currently reports voice support as disabled.
Auth, CORS, and Domain Troubleshooting
| Symptom | Check |
|---|---|
API key is required | The iframe URL needs ?key=spk_..., or the script needs data-api-key. |
401 Invalid API key | The key is missing, revoked, expired, wrong prefix, or lacks chat permission. |
403 agent-scoped API key | SDK routes require an agent-scoped key. Organization-scoped keys are for other API surfaces. |
403 Origin is not allowed | Allowed origins are exact strings. Use origins like https://app.example.com, not paths or trailing slashes. |
| Widget works in sandbox only | Dashboard session fallback can hide key/domain issues. Test with the production script on a real staging URL. |
| Cross-origin API calls fail | The hosted widget calls /api/sdk/* from inside the iframe. Contact Kravos.ai support before making direct browser calls from your app. |
| Voice button missing | Confirm launcher mode, widget/agent voice enabled, and voice config is complete. |
If you configure an origin allowlist, include the Kravos web app origin that serves /widget. Include your
product origin too only if your page directly calls SDK routes or hosts the loader from that origin.
Before You Go Live
- create a dedicated agent-scoped chat key for the widget
- verify allowed origins with the exact staging and production origins
- test launcher and suite modes separately if you use both
- check desktop, mobile, and side-panel placement on real pages
- confirm pre-chat fields are only the fields support teams actually need
- test signed identity with one returning user and one anonymous user
- start and end a voice session if voice is enabled
- submit feedback and confirm it appears in Feedbacks
Related Docs
API Keys
Create agent-scoped keys, set permissions, and manage allowed origins.
Conversations
Review text, suite, and voice conversations after users chat through the widget.
Voice Lab
Test voice sessions, debug tool calls, and manage ElevenLabs sync before enabling widget voice.
API Reference
Compare dashboard-domain widget routes with the public server-to-server API.


