Widget Integration Guide
Embed the KlicForge chat widget on any site — one script tag, or the npm package for React and friends.
1. Allow your domain
The API only serves widget traffic from origins on the agent's allowlist. In the dashboard open your agent → Channels → Widget and add every origin the widget loads from.
Matching is exact — there are no wildcards, and scheme and host must both agree, so https://example.com and https://www.example.com are separate entries. Skip this and the widget shows an access-restricted panel instead of a chat.
2. Add the widget
Floating launcher
A bubble anchored to the bottom-right of the viewport.
<!-- Paste before </body> -->
<script src="https://unpkg.com/@bymos/[email protected]/agentkit-widget.iife.js"></script>
<script>
window.AgentKit.init({
agentId: 'your-agent-id',
tenantId: 'your-tenant-id',
apiBaseUrl: 'https://api.klicforge.ai',
title: 'Support Assistant',
});
</script>Inline panel
Fills a container you place yourself — for a sidebar or a dedicated page.
<div id="chat"></div>
<script src="https://unpkg.com/@bymos/[email protected]/agentkit-widget.iife.js"></script>
<script>
// The element is the first argument — mount() always renders inline.
window.AgentKit.mount(document.getElementById('chat'), {
agentId: 'your-agent-id',
tenantId: 'your-tenant-id',
apiBaseUrl: 'https://api.klicforge.ai',
});
</script>React / Next.js
The npm package takes the same single config object as the script tag.
npm install @bymos/agentkit-sdkimport { useEffect } from 'react'
import { init } from '@bymos/agentkit-sdk'
export function ChatWidget() {
useEffect(() => {
const widget = init({
agentId: 'your-agent-id',
tenantId: 'your-tenant-id',
apiBaseUrl: 'https://api.klicforge.ai',
})
// Closes the operator-reply stream as well as removing the DOM.
return () => widget.destroy()
}, [])
return null
}Configuration options
One config object, identical for both integration methods. Anything you set here overrides the agent's dashboard config.
| Option | Description | Default |
|---|---|---|
| agentId | Agent ID or slug from your dashboard. Required. | — |
| apiBaseUrl | Base URL of the KlicForge API. Required, must be a full URL. | — |
| tenantId | Tenant identifier. Needed for conversation tracking and validation. | — |
| user | End-user identity: { externalId?, authId?, name?, email? }. Omit for anonymous sessions. | anonymous |
| sessionId | Resume a specific conversation instead of starting a new one. | auto |
| mode | 'floating' or 'inline'. mount() forces inline regardless. | floating |
| title | Title shown in the widget header. | AI Assistant |
| subtitle | Small line under the agent name. | — |
| description | Shown in the empty state before the first message. | dashboard config |
| avatarUrl | Agent avatar image URL. | dashboard config |
| privacyPolicyUrl | Privacy link in the composer footer. | — |
| termsOfServiceUrl | Terms link in the composer footer. | — |
| disclosureText | AI processing notice above the composer. Pass '' to hide it. | standard notice |
| streaming | Stream responses token by token. | true |
| metadata | Arbitrary object sent with every message. | {} |
| theme | { mode?, accentColor?, fontFamily?, borderRadius? } | see below |
Suggested questions, file upload and attachment limits are configured on the agent in the dashboard and cannot be set from the host page.
Theming
The widget renders in a shadow root, so your page's CSS can't leak in — and your own stylesheet can't reach the widget. Pass theme instead.
window.AgentKit.init({
agentId: 'your-agent-id',
tenantId: 'your-tenant-id',
apiBaseUrl: 'https://api.klicforge.ai',
theme: {
mode: 'dark', // 'light' | 'dark' | 'system'
accentColor: '#6366f1',
fontFamily: "'Inter', sans-serif",
borderRadius: '12px',
},
})These become the custom properties --ak-accent, --ak-accent-hover, --ak-font and --ak-radius inside the shadow root.
Controlling the widget
Both init() and mount() return an instance with open, close, toggle, sendMessage, reset, destroy, getState and event handlers.
const widget = window.AgentKit.init({ /* ... */ })
widget.on('ready', (state) => console.log('session', state.sessionId))
widget.on('message:received', (msg) => console.log(msg.content))
widget.on('control_mode_changed', ({ mode }) => console.log('handed to', mode))
widget.open()
widget.sendMessage('Hello!')
widget.destroy()Content Security Policy
If your site sends a CSP, allow https://unpkg.com in script-src (CDN install only), https://api.klicforge.ai in connect-src and img-src, and 'unsafe-inline' in style-src — shadow DOM does not exempt injected styles from CSP.