Skip to main content

KriyaOS Chat Widget


title: KriyaOS Chat Widget description: Add the KriyaOS Chat Widget to your website using npm, React, Next.js, or plain HTML.

Integrations

KriyaOS Chat Widget

Add the KriyaOS Chat Widget to a website so visitors can chat with a published KriyaOS agent from approved public origins.

Overview

The KriyaOS Chat Widget is a production-ready embeddable chat widget for websites and web apps.

Use it when you want to add a ready-made chat interface to a website without building your own frontend on top of the Public Chat API.

The widget supports:

* Lightweight ESM and CJS bundles * Session persistence with localStorage * Quick action chips for faster conversations * Typing animation and streaming response support * KriyaOS API support using workspaceId and agentId * Plain HTML, React, and Next.js client components * Built-in launcher GIF choices and custom launcher image URLs

Before you start

Before installing the widget, make sure you have:

* A KriyaOS workspace * A published KriyaOS agent * Public Chat enabled for the agent * Allowed origins configured for your website domain * The required workspaceId and agentId

You can get workspaceId and agentId from your KriyaOS workspace dashboard.

Install

npm install @kriyaos.com/kriyaos-chat-widget

Basic usage

Use the default package export and call ChatWidget.init(config) once in the browser.

<script type="module">
import ChatWidget from "@kriyaos.com/kriyaos-chat-widget";

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
stream: true,
textOnly: true,
source: "popup",
title: "Support Assistant",
launcherIcon: "bot3",
theme: {
primaryColor: "#0f766e",
logoUrl: "https://app.kriyaos.com/favicon.ico",
launchIconUrl: "https://app.kriyaos.com/favicon.ico",
welcomeMessage: "Hi! Ask me anything.",
fontSizeMode: "small",
},
});
</script>

React example

import { useEffect } from "react";
import ChatWidget from "@kriyaos.com/kriyaos-chat-widget";

export default function App() {
useEffect(() => {
ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
stream: true,
textOnly: true,
source: "popup",
});
}, []);

return null;
}

Next.js App Router example

Use the widget only in a client component because it uses browser APIs such as window, document, and localStorage.

"use client";

import { useEffect } from "react";
import ChatWidget from "@kriyaos.com/kriyaos-chat-widget";

export default function ChatWidgetLoader() {
useEffect(() => {
ChatWidget.init({
workspaceId: process.env.NEXT_PUBLIC_KRIYAOS_WORKSPACE_ID!,
agentId: process.env.NEXT_PUBLIC_KRIYAOS_AGENT_ID!,
apiBaseUrl: process.env.NEXT_PUBLIC_KRIYAOS_API_BASE_URL,
stream: true,
textOnly: true,
source: "popup",
});
}, []);

return null;
}

Then render the client component from your app layout or page.

import ChatWidgetLoader from "@/components/ChatWidgetLoader";

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<ChatWidgetLoader />
</body>
</html>
);
}

Configuration reference

Call:

ChatWidget.init(config);

The config object controls the agent connection, API request behavior, session persistence, launcher appearance, widget header, quick actions, and theme.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
apiBaseUrl: "https://api.kriyaos.com",
stream: true,
textOnly: true,
source: "popup",
headers: {
"X-Client-Name": "website",
},
storageKey: "kriyaos-support-widget",
launchIconUrl: "https://example.com/chat-icon.gif",
launcherIcon: "bot3",
title: "Support Assistant",
quickActions: ["Show pricing", "Book a demo", "Talk to support"],
theme: {
primaryColor: "#0f766e",
logoUrl: "https://app.kriyaos.com/favicon.ico",
launchIconUrl: "https://app.kriyaos.com/favicon.ico",
welcomeMessage: "Hi! Ask me anything.",
fontSizeMode: "small",
},
});

Configuration summary

FieldTypeRequiredDefault behaviorPurpose
workspaceIdstringYesNoneIdentifies the KriyaOS workspace.
agentIdstringYesNoneIdentifies the KriyaOS agent.
apiBaseUrlstringNoPackage default API URLSets the KriyaOS API base URL.
streambooleanNotrueSends the streaming query parameter.
textOnlybooleanNotrueSends the text-only query parameter.
sourcestringNo"popup"Sends the source query parameter.
headersRecord<string, string>NoNo extra headersAdds custom request headers.
storageKeystringNoPackage default namespaceSeeds localStorage keys for session persistence.
launchIconUrlstringNoNoneSets a custom launcher image or GIF URL.
launcherIcon"default" | "bot1" | "bot2" | "bot3" | "bot4" | "bot5" | "bot6" | "bot7"NoPackage default launcher iconSelects a built-in launcher GIF.
titlestringNoPackage default titleSets the widget header title.
quickActionsstring[]NoNo custom quick actionsAdds starter quick-action chips.
theme.primaryColorstringNoPackage default colorSets the main brand color.
theme.logoUrlstringNoNoneShows a logo in the widget header.
theme.launchIconUrlstringNoNoneSets a custom launcher image or GIF from inside theme.
theme.launcherIconUrlstringNoSame as theme.launchIconUrlLegacy alias for theme.launchIconUrl.
theme.launcherIcon"default" | "bot1" | "bot2" | "bot3" | "bot4" | "bot5" | "bot6" | "bot7"NoPackage default launcher iconSelects a built-in launcher GIF from inside theme.
theme.welcomeMessagestringNoPackage default welcome messageSets the first assistant message.
theme.fontSizeMode"small" | "medium" | "large"NoPackage default text sizeControls UI text scaling.

workspaceId

The workspaceId identifies the KriyaOS workspace that owns the agent.

The widget uses this value to route website chat requests to the correct workspace.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
});

Accepted values:

* A valid KriyaOS workspace ID. * The workspace ID must come from the same KriyaOS environment that the widget is calling.

Default behavior:

* No default value. * This field is required.

Important notes:

* The workspaceId must match the workspace that owns the agentId. * You can get the workspace ID from your KriyaOS workspace dashboard. * In Next.js, expose it with a public environment variable only when it is intended to be used in the browser.

Example:

NEXT_PUBLIC_KRIYAOS_WORKSPACE_ID=your-workspace-id

Edge cases:

* If workspaceId is missing, the widget cannot correctly identify the workspace. * If workspaceId belongs to a different environment than apiBaseUrl, requests may fail. * If the workspace does not own the agent, the public chat request may return an error.

agentId

The agentId identifies the KriyaOS agent that visitors will chat with.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
});

Accepted values:

* A valid KriyaOS agent ID. * The agent should be published and available for public chat.

Default behavior:

* No default value. * This field is required.

Important notes:

* The agent must belong to the workspace provided in workspaceId. * The agent should be published before using it in a public website widget. * Public Chat should be enabled for the agent.

Edge cases:

* If the agent is still in draft mode, the widget may not be able to return responses. * If Public Chat is disabled, requests from the widget may fail. * If the agent ID is deleted, invalid, or from another workspace, the widget will not be able to complete the chat request.

apiBaseUrl

The apiBaseUrl sets the KriyaOS API base URL used by the widget.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
apiBaseUrl: "https://api.kriyaos.com",
});

Accepted values:

* A valid KriyaOS API base URL. * Use HTTPS URLs in production.

Default behavior:

* Optional. * If omitted, the widget uses the package default API URL.

Important notes:

* Use the production API URL on live websites. * Use staging or development API URLs only for testing environments. * Keep workspaceId, agentId, and apiBaseUrl from the same environment.

Edge cases:

* If the API base URL is wrong, the widget may appear but chat requests will fail. * If a staging API URL is used with production IDs, the request may fail or reach the wrong environment. * If the website origin is not allow-listed by the API, the browser may show a CORS error.

stream

The stream option controls whether the widget sends the streaming query parameter.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
stream: true,
});

Accepted values:

* true * false

Default behavior:

* Defaults to true.

Important notes:

* When enabled, streaming responses can be returned using text/event-stream. * Streaming can improve perceived response speed because the answer can appear progressively.

Edge cases:

* If the backend, proxy, or hosting layer does not support Server-Sent Events, streaming may not work as expected. * If streaming is disabled, responses may appear only after the full answer is ready.

textOnly

The textOnly option controls whether the widget sends the textOnly query parameter.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
textOnly: true,
});

Accepted values:

* true * false

Default behavior:

* Defaults to true.

Important notes:

* Use textOnly: true when the widget should send and receive text-focused chat content. * This is the default public widget behavior.

Edge cases:

* If your agent or API flow expects non-text parts, confirm whether textOnly should remain enabled. * If the backend behavior changes based on this query parameter, test both local and production environments.

source

The source option sends a source query parameter with each widget request.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
source: "popup",
});

Accepted values:

* Any supported source string used by your KriyaOS API. * The package default is "popup".

Default behavior:

* Defaults to "popup".

Important notes:

* Use source to identify where the conversation is coming from. * The default public URL parameters sent by the widget include source=popup.

Edge cases:

* If your analytics or backend logic depends on source, changing it may affect reporting or routing. * Use consistent source names across environments.

headers

The headers option adds custom request headers to widget API calls.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
headers: {
"X-Client-Name": "website",
},
});

Accepted values:

* A plain object with string keys and string values: Record<string, string>.

Default behavior:

* Optional. * No additional headers are sent unless provided.

Important notes:

* Use this only when your backend requires additional request headers. * Do not expose private secrets, server API keys, or admin tokens in browser-side headers. * Anything passed into the widget can be visible in the browser.

Edge cases:

* Some custom headers can trigger browser CORS preflight requests. * If the API does not allow the custom header, the request can fail due to CORS. * Never pass sensitive backend-only credentials from frontend code.

storageKey

The storageKey option controls the namespace seed used for localStorage keys.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
storageKey: "kriyaos-support-widget",
});

Accepted values:

* Any string suitable for a localStorage key namespace.

Default behavior:

* Optional. * If omitted, the package uses its default localStorage namespace.

Important notes:

* The widget uses localStorage for session persistence. * Use a custom storageKey when you have multiple widgets or need a predictable namespace.

Edge cases:

* If two widgets use the same storage namespace, sessions may overlap. * If localStorage is blocked by the browser or privacy settings, session persistence may not work. * Changing the storage key can make existing visitor sessions appear new.

launchIconUrl

The launchIconUrl option sets a custom launcher image or GIF URL.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
launchIconUrl: "https://example.com/chat-icon.gif",
});

Accepted values:

* A valid image or GIF URL. * Use HTTPS URLs in production.

Default behavior:

* Optional. * If provided, it overrides the built-in launcher icon selection.

Important notes:

* Use optimized images to avoid slowing down page load. * Prefer small SVG, PNG, WebP, or GIF assets. * Use launchIconUrl when you want to pass your own custom image or GIF URL.

Edge cases:

* If the image URL is broken, the launcher may not display correctly. * If the image is too large, it can affect website performance. * If both a custom URL and built-in icon are configured, the custom URL should take priority.

launcherIcon

The launcherIcon option selects one of the package’s built-in launcher GIF choices.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
launcherIcon: "bot3",
});

Accepted values:

* "default" * "bot1" * "bot2" * "bot3" * "bot4" * "bot5" * "bot6" * "bot7"

Default behavior:

* Optional. * If omitted, the widget uses the package default launcher icon.

Important notes:

* Use launcherIcon when you want to use one of the built-in GIF choices. * Use launchIconUrl when you want to provide your own custom image or GIF.

Edge cases:

* If an unsupported launcher icon value is used, the widget may fall back to the default icon or fail to display the intended icon. * If launchIconUrl is also provided, the custom image URL should override the built-in icon selection.

title

The title option sets the header title displayed inside the widget.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
title: "Support Assistant",
});

Accepted values:

* Any string.

Default behavior:

* Optional. * If omitted, the widget uses the package default title.

Important notes:

* Use a short, clear title. * Match the title to the agent’s purpose, such as Support Assistant, Sales Assistant, or Booking Assistant.

Edge cases:

* Very long titles may not fit well on mobile screens. * Avoid using titles that imply human support unless a human escalation flow is available.

quickActions

The quickActions option adds starter quick-action chips for faster conversations.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
quickActions: ["Show pricing", "Book a demo", "Talk to support"],
});

Accepted values:

* An array of strings: string[].

Default behavior:

* Optional. * If omitted, no custom quick-action chips are configured.

Important notes:

* Keep labels short and action-oriented. * Use quick actions that match common visitor intents. * Examples: Book appointment, Show pricing, Track order, Talk to support.

Edge cases:

* Too many quick actions can clutter the widget UI. * Very long chip labels may wrap or overflow on mobile. * Do not add actions that the agent cannot actually handle.

theme.primaryColor

The theme.primaryColor option sets the widget’s primary brand color.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
theme: {
primaryColor: "#0f766e",
},
});

Accepted values:

* A valid CSS color string. * Hex colors and gradients are supported.

Default behavior:

* Optional. * If omitted, the widget uses the package default primary color.

Important notes:

* Use a brand color that has enough contrast. * Test buttons, links, and text against the selected color. * Use production-approved brand colors for live websites.

Edge cases:

* Invalid color strings may be ignored by the browser. * Low-contrast colors can make the widget difficult to read. * Gradients should be tested across browsers and screen sizes.

theme.logoUrl

The theme.logoUrl option shows a logo in the widget header.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
theme: {
logoUrl: "https://app.kriyaos.com/favicon.ico",
},
});

Accepted values:

* A valid image URL. * Use HTTPS URLs in production.

Default behavior:

* Optional. * If omitted, no custom logo is configured.

Important notes:

* Use a small, optimized image. * Use a logo that remains clear at small sizes. * Prefer HTTPS URLs on production sites.

Edge cases:

* Broken image URLs may show a missing image icon or blank header area. * Large image files can slow down the widget load. * Logos with transparent or low-contrast backgrounds may not display well on all themes.

theme.launchIconUrl

The theme.launchIconUrl option sets a custom launcher image or GIF URL from inside the theme object.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
theme: {
launchIconUrl: "https://example.com/chat-icon.gif",
},
});

Accepted values:

* A valid image or GIF URL.

Default behavior:

* Optional. * If provided, it sets the outside launcher button image.

Important notes:

* This is similar to the top-level launchIconUrl. * Use this when you prefer keeping visual settings inside the theme object.

Edge cases:

* If both top-level launchIconUrl and theme.launchIconUrl are set, confirm priority in the package implementation. * Broken URLs or large files can affect the launcher display.

theme.launcherIconUrl

The theme.launcherIconUrl option is a legacy alias for theme.launchIconUrl.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
theme: {
launcherIconUrl: "https://example.com/chat-icon.gif",
},
});

Accepted values:

* A valid image or GIF URL.

Default behavior:

* Optional. * Treated as a legacy alias for theme.launchIconUrl.

Important notes:

* Prefer theme.launchIconUrl for new implementations. * Keep this documented for older integrations that may already use the legacy alias.

Edge cases:

* Avoid setting both theme.launchIconUrl and theme.launcherIconUrl unless the package implementation clearly defines priority. * If both are set to different URLs, the displayed icon may not be the one the developer expects.

theme.launcherIcon

The theme.launcherIcon option selects a built-in launcher GIF from inside the theme object.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
theme: {
launcherIcon: "bot3",
},
});

Accepted values:

* "default" * "bot1" * "bot2" * "bot3" * "bot4" * "bot5" * "bot6" * "bot7"

Default behavior:

* Optional. * If omitted, the widget uses the package default launcher icon.

Important notes:

* Use this when you want to keep launcher visual settings inside theme. * Use custom icon URLs when you need a brand-specific icon.

Edge cases:

* If top-level launcherIcon, launchIconUrl, theme.launchIconUrl, and theme.launcherIcon are combined, confirm priority in implementation. * Unsupported values may fall back to the default icon.

theme.welcomeMessage

The theme.welcomeMessage option sets the first assistant message shown when the widget opens.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
theme: {
welcomeMessage: "Hi! Ask me anything.",
},
});

Accepted values:

* Any string.

Default behavior:

* Optional. * If omitted, the widget uses the package default welcome message.

Important notes:

* Keep the welcome message short and helpful. * Match the message to the agent’s actual capabilities. * Use friendly but accurate wording.

Edge cases:

* Long welcome messages may not display well on mobile. * Avoid promising services the agent cannot perform. * Do not include medical, legal, or financial claims unless the agent and business flow are approved for that use case.

theme.fontSizeMode

The theme.fontSizeMode option controls UI text scaling.

ChatWidget.init({
workspaceId: "your-workspace-id",
agentId: "your-agent-id",
theme: {
fontSizeMode: "small",
},
});

Accepted values:

* "small" * "medium" * "large"

Default behavior:

* Optional. * If omitted, the widget uses the package default text size.

Important notes:

* Use small for compact website layouts. * Use medium for standard readability. * Use large when accessibility or larger text is preferred.

Edge cases:

* Larger text may take more space inside the widget. * Smaller text may be harder to read for some users. * Always test the selected size on mobile and desktop.

Request and response format

The widget sends chat messages using the KriyaOS message format.

Request body:

{
"messages": [
{
"role": "user",
"parts": [{ "type": "text", "text": "Hello" }]
}
]
}

Expected response shape:

{
"message": {
"parts": [{ "type": "text", "text": "Hi, how can I help?" }]
},
"session": { "id": "session-id" }
}

When streaming is enabled, the widget can receive responses using text/event-stream.

By default, the widget sends these public URL parameters:

?workspaceId=...&agentId=...&stream=true&textOnly=true&source=popup

Next.js environment example

Add values to .env.local:

NEXT_PUBLIC_KRIYAOS_WORKSPACE_ID=your-workspace-id
NEXT_PUBLIC_KRIYAOS_AGENT_ID=your-agent-id
NEXT_PUBLIC_KRIYAOS_API_BASE_URL=https://api.kriyaos.com

Use them in a client component:

"use client";

import { useEffect } from "react";
import ChatWidget from "@kriyaos.com/kriyaos-chat-widget";

export function KriyaOSWidget() {
useEffect(() => {
ChatWidget.init({
workspaceId: process.env.NEXT_PUBLIC_KRIYAOS_WORKSPACE_ID!,
agentId: process.env.NEXT_PUBLIC_KRIYAOS_AGENT_ID!,
apiBaseUrl: process.env.NEXT_PUBLIC_KRIYAOS_API_BASE_URL,
stream: true,
textOnly: true,
source: "popup",
title: "Support Assistant",
launcherIcon: "bot3",
theme: {
primaryColor: "#0f766e",
welcomeMessage: "Hi! Ask me anything.",
fontSizeMode: "small",
},
});
}, []);

return null;
}

Common configuration mistakes

Using an unpublished agent

The widget requires a published agent. If the agent is still in draft mode, publish it before using the widget.

Public Chat is not enabled

The widget depends on the Public Chat integration. Enable Public Chat before testing the widget.

Website origin is not allowed

If allowed origins are configured, your website domain must be added before the widget can call the public chat endpoint.

Examples:

http://localhost:3000
https://staging.example.com
https://www.example.com

Initializing the widget on the server

In React or Next.js, initialize the widget only on the client side. For Next.js App Router, use a client component with "use client" and useEffect.

Initializing the widget more than once

Initialize the widget once per page load. Calling ChatWidget.init() multiple times can create duplicate widgets or duplicate event listeners.

Passing secrets in browser headers

Do not pass private API keys, admin tokens, or backend-only secrets in headers. Widget configuration runs in the browser, so users can inspect these values.

Mixing staging and production values

Keep local, staging, and production values separate. Do not use staging workspace IDs, agent IDs, or API URLs on a production website.

Using unsupported launcher icon values

Use only the supported built-in launcher values: "default", "bot1", "bot2", "bot3", "bot4", "bot5", "bot6", and "bot7".

Production checklist

Before going live:

* Publish the agent * Enable Public Chat * Add your website domain to allowed origins * Initialize the widget once per page load * Test the widget on staging * Check mobile responsiveness * Configure HTTPS endpoints in production * Confirm fallback or human escalation flow * Verify that the agent does not expose private workspace data * Avoid passing sensitive credentials in browser-side headers

Troubleshooting

Widget does not appear

Check that the widget package is installed correctly and that ChatWidget.init() is called in the browser.

For React and Next.js apps, make sure initialization runs inside useEffect.

Chat request fails

Make sure the agent is published, Public Chat is enabled, and your website domain is added to allowed origins.

Also confirm that workspaceId, agentId, and apiBaseUrl belong to the same environment.

CORS error in widget

Allow your website origin on the API side. If you are using custom headers, confirm that the API also allows those headers.

Works locally but not on production

Add your production domain to the allowed origins list in KriyaOS.

Also confirm that production uses the correct production workspaceId, agentId, and apiBaseUrl.

Nothing appears after install in Next.js

Confirm that the component has "use client" at the top and that the widget is initialized inside useEffect.

Duplicate widgets appear

Ensure ChatWidget.init() is called only once per page load.