Widget SDK
Embed and control the KlicForge chat widget from JavaScript — installation, configuration, methods and events.
The widget SDK embeds the KlicForge chat widget in a web page and gives you a JavaScript API to control it.
The widget renders inside an isolated container, so its styles cannot leak into your page and your page's styles cannot break it.
Installation
Add this before the closing </body> tag:
<script src="https://unpkg.com/@bymos/agentkit-sdk/agentkit-widget.iife.js"></script>
<script>
window.AgentKit.init({
agentId: 'your-agent-id',
tenantId: 'your-tenant-id',
apiBaseUrl: 'https://api.klicforge.ai',
});
</script>This registers window.AgentKit synchronously.
Find your agent ID and tenant ID on the agent's Widget tab in the dashboard, which also generates a ready-made snippet.
The widget only loads on domains listed in the agent's allowed origins. If you see an access-restricted message, add the site's origin under the agent's Channels → Widget settings.
Mounting
init() creates a floating widget with a launcher button. To embed the chat inside an element
of your own layout instead, use mount():
window.AgentKit.mount(document.getElementById('support-chat'), {
agentId: 'your-agent-id',
tenantId: 'your-tenant-id',
apiBaseUrl: 'https://api.klicforge.ai',
});Controlling the widget
Both init() and mount() return an instance:
const widget = window.AgentKit.init({ ... });
widget.open();
widget.close();
widget.toggle();
widget.sendMessage('Hello');
widget.reset(); // start a fresh conversation
widget.getState();
widget.destroy();window.AgentKit.destroy(id) removes a widget by ID, and calling it with no argument removes
all of them.
Events
widget.on('message:received', (event) => {
console.log(event);
});
widget.off('message:received', handler);| Event | Fires when |
|---|---|
ready | The widget has initialised |
open / close | The widget is opened or closed |
conversation:started | A new conversation begins |
message:sent | The user sends a message |
message:received | The agent's reply arrives |
message:error | A message fails |
stream:start / stream:delta / stream:end | Streaming reply lifecycle |
control_mode_changed | A human takes over or hands back |
reset | The conversation is reset |
destroy | The widget is torn down |
Identifying your users
If you already know who the visitor is, pass an external identifier so their conversations link to the same contact across sessions and devices.
Do not pass personal data you would not want in a browser. The identifier should be an opaque ID from your own system, not an email address.
Appearance
Greeting, branding, colours, whether file upload and voice notes are enabled, and links to your privacy policy and terms are all configured on the agent's Widget tab rather than in code, so non-developers can change them without a deployment.
Sessions
A conversation persists across page loads in the browser, so a visitor who navigates around your
site keeps their conversation. reset() starts a fresh one. Sessions expire after a period of
inactivity set on the agent.
Troubleshooting
| Symptom | Likely cause |
|---|---|
window.AgentKit is undefined | The script tag runs after your init code, or failed to load |
| Access-restricted message | The origin is not in the agent's allowed origins |
| Widget opens but never replies | The agent's status is draft or inactive |
| Widget is clipped or invisible | A parent element has overflow: hidden or a low stacking context |
| Uploads rejected | The file type or size is not supported |