Public JavaScript API¶
Everything a host page can use to control the embedded chat widget from its own scripts.
The widget mounts in Shadow DOM inside the host document β there is no iframe, so all calls are ordinary same-realm JavaScript. Two globals form the contract:
| Global | Owner | Purpose |
|---|---|---|
window.daktelaAiChatConfig |
host page | where to load the widget from |
window.daktelaAiChat |
widget | the API described below |
Installation¶
Paste both scripts into the page, in the order shown below.
<script>
// Command queue: lets the page call the API before the widget has loaded.
(function () {
if (window.daktelaAiChat && window.daktelaAiChat.__isProxy) return;
var q = [];
window.daktelaAiChat = new Proxy(
{ queue: q, __isProxy: true },
{
get: function (t, p) {
if (p in t) return t[p];
return function () {
q.push({ m: p, a: [].slice.call(arguments), t: Date.now() });
};
},
},
);
})();
</script>
<script>
window.daktelaAiChatConfig = {
url: 'https://my-instance.bot.coworkers.ai',
daktelaAiChatId: 'abc123',
};
</script>
<script
defer
crossorigin="anonymous"
src="https://my-instance.bot.coworkers.ai/chat-window-public-api/loader/dai-loader.js"
></script>
url and the host in src must point at the same instance.
How loading works¶
The widget itself is downloaded lazily β for example on open() or a launcher click. Anything you call before that just queues up, and once the widget loads, it all runs in the exact order you called it β nothing is lost.
Window control¶
open()¶
Opens the chat window. Triggers the lazy download on first use. Safe to call again β it won't do anything extra.
close()¶
Closes the window and, by default, ends the conversation: with
configuration.identity.closeResetsSession at its default true, the session is reset and
the next open starts a fresh discussion. Set that option to false to make close() only
hide the window.
restart(options?) / restartAndOpen(options?)¶
Discards the current conversation and starts a new one. restartAndOpen also opens the
window.
| Option | Type | Effect |
|---|---|---|
retainContextKeys |
string[] |
Context keys copied into the new conversation. Everything else is dropped. Unknown keys are ignored. |
Without options the whole context is cleared.
restartAndClose()¶
Closes the window. Despite the name it does not restart the conversation β whether the
session ends is decided by closeResetsSession, exactly as with close().
destroy()¶
Disconnects, unmounts the widget, clears registered tools and analytics, and removes
window.daktelaAiChat. Use when the host page tears down the chat (e.g. an SPA route
change). Calls made afterwards have no effect.
Language¶
setLanguage(languageCode)¶
Switches the interface language.
The code must be listed in configuration.languages.enabledLanguages β otherwise the call
is rejected with a console error and nothing changes. Enable languages in the admin
(chat window detail β Languages) and publish; the widget only ever reads the published
configuration.
resetLanguage()¶
Drops the override and returns to the configured detection.
Conversation context¶
Context is a set of key/value pairs the bot can read β order number, plan, cart size.
Keys must be written the way bot platform names its variables: a leading $ followed by a
single word, no spaces β $orderId, not orderId or $order id. A key that does not match
is dropped with a console error, because the bot could never resolve it.
The admin Options tab can preset context pairs. Those seed every discussion the widget
starts, including the one after a restart, so they act as defaults; an addContext() /
setContext() call from the host page overrides the same key for the current discussion.
addContext(context)¶
window.daktelaAiChat.addContext({
$orderId: 'A-1234',
$plan: 'premium',
$note: { value: 'expires soon', lifespan: 3 },
});
Accepts a plain object. Scalars are wrapped automatically; pass { value, lifespan } to
limit how many bot turns an entry survives. Keys are merged, not replaced. Sent immediately
when a conversation is live, otherwise attached to the next one. Keys that break the $name
rule are skipped; the rest of the object still applies.
setContext(key, value)¶
The single-entry form of addContext. The same $name key rule applies.
Appearance¶
setCustomCss(cssText) / resetCustomCss()¶
Injects raw CSS into the widget's Shadow DOM. Takes effect only once the bundle is loaded.
Two things to know, both common causes of "nothing happened":
- Custom CSS is inserted before the widget's own stylesheet, so rules almost always need
!important. - Selectors must match real classes. The useful ones are
.daktela-ai-window,.daktela-ai-header,.daktela-ai-launcher-button,.daktela-ai-message-buttonand.daktela-ai-home-screen.
The widget logs a warning whenever custom CSS is applied. That is deliberate β class names are not a stable contract, so re-test custom CSS after widget updates.
Page-action tools¶
The Agent module β the LLM that drives your dialogs β can use tools in addition to its prompt. One type is API Integrations, which call your backend endpoints. Page-action tools are the second type: a JavaScript function running right on your page, which you register with registerTool() β letting the Agent call back into your site (look up an order, highlight an element, open a ticket) without any data ever leaving the visitor's browser.
registerTool(tool)¶
window.daktelaAiChat.registerTool({
name: 'openTicket',
description: 'Opens a support ticket and returns its id.',
parameters: {
type: 'object',
properties: { subject: { type: 'string' } },
required: ['subject'],
},
confirm: true,
handler: (args) => ({ ticketId: createTicket(args.subject) }),
});
| Field | Type | Notes |
|---|---|---|
name |
string |
Unique; re-registering the same name replaces the tool. |
description |
string |
What the assistant reads to decide when to call it. |
parameters |
JSON Schema | Object schema. Only top-level required and primitive types are validated. |
handler |
(args) => unknown |
Sync or async. Never leaves the browser. |
confirm |
boolean |
Optional. Shows an approve/decline prompt before running. |
A handler may return any JSON-serialisable value; it is passed back to the assistant. Errors
are reported as handler_error, a handler exceeding 30 seconds as timeout, a declined
prompt as user_declined.
Timing: the registered set is attached to every outgoing visitor message, not to the initial handshake. Register tools before the visitor sends their first message β the bot's opening turn does not see them.
Info
Registering a tool makes it available to the Agent, but doesn't by itself tell it when to use it. Just like with API Integrations, mention the tool (by its name) directly in the Agent's instructions β e.g. "Use the openTicket tool when the customer wants to open a support ticket."
unregisterTool(name) / getRegisteredTools()¶
getRegisteredTools() returns the schemas currently in effect (without handlers), which is
what an outgoing message carries.
Legacy ew-* custom events¶
These exist for one reason: so a site already integrated with the previous chat window keeps working after the upgrade, without touching its code. The event names, payloads and effects match the old widget.
For anything new, use the JavaScript API above β it is the supported surface, it covers more, and it reports errors. The events are maintained for compatibility only.
Dispatch them on window:
| Event | Effect | API equivalent |
|---|---|---|
ew-open-window |
Opens the window | open() |
ew-hide-window |
Hides the window without ending the conversation | β |
ew-toggle-window |
Opens or hides | β |
ew-end-discussion |
Ends the conversation on the server so the assistant can say goodbye and ask for a rating; the window stays open. Repeating it once the conversation is over closes and starts fresh. | β |
ew-reset-chat |
Starts a new conversation, window state unchanged | restart() |
ew-close-and-reset-chat |
Closes the window and starts a new conversation | restartAndClose() |
add-context |
One context entry, detail: { key, value } |
setContext(key, value) |
chatbot-ew-context-set |
Whole context object in detail |
addContext(object) |
ew-set-dark-mode |
Forces the dark theme | β |
ew-set-light-mode |
Forces the light theme | β |
ew-set-system-theme-mode |
Follows the operating system theme | β |
ew-enable-ga / ew-disable-ga |
Toggles Google Analytics reporting. ew-disable-ga stops Google Analytics only β Google Tag Manager keeps receiving events, matching the old widget's behaviour. |
β |