Öffentliche JavaScript-API¶
Alles, was eine Host-Seite verwenden kann, um das eingebettete Chat-Widget über eigene Skripte zu steuern.
Das Widget wird im Shadow DOM innerhalb des Host-Dokuments gemountet — es gibt kein iframe, daher sind alle Aufrufe gewöhnliches JavaScript im selben Realm. Zwei globale Objekte bilden den Vertrag:
| Global | Eigentümer | Zweck |
|---|---|---|
window.daktelaAiChatConfig |
Host-Seite | woher das Widget geladen werden soll |
window.daktelaAiChat |
Widget | die unten beschriebene API |
Installation¶
Ihren Einbettungscode finden Sie im Tab CODE des Veröffentlichungs-Panels neben den Widget-Einstellungen. Fügen Sie ihn als einen einzigen Block in die Seite ein — er enthält die Konfiguration, installiert die Befehlswarteschlange und lädt das Widget selbst.
<script>
window.daktelaAiChatConfig = {
url: "https://my-instance.bot.coworkers.ai",
daktelaAiChatId: "abc123",
};
(function(){var e=window.daktelaAiChatConfig;if(!window.daktelaAiChat||!window.daktelaAiChat.__isProxy){var t=[];window.daktelaAiChat=new Proxy({queue:t,__isProxy:!0},{get:function(e,n){return n in e?e[n]:function(){var e={m:n,a:[].slice.call(arguments),t:Date.now()};return t.push(e),new Promise(function(t,n){e.resolve=t,e.reject=n})}}})}var n=document.createElement(`script`);n.defer=!0,n.crossOrigin=`anonymous`,n.src=e.url.replace(/\/+$/,``)+`/chat-window-public-api/loader/dai-loader.js`,document.head.appendChild(n)})();
</script>
Der einzige zur Bearbeitung vorgesehene Teil des Snippets ist daktelaAiChatConfig.
So funktioniert das Laden¶
Das Widget selbst wird lazy geladen — zum Beispiel bei open() oder einem Klick auf den Launcher. Alles, was Sie vorher aufrufen, landet in einer Warteschlange und wird ausgeführt, sobald das Widget geladen ist — und zwar genau in der Reihenfolge, in der Sie es aufgerufen haben. Es geht nichts verloren.
Jeder eingereihte Aufruf gibt ein Promise zurück, sodass await auch schon vor dem Laden des Widgets
funktioniert:
Eine Ausnahme bildet getRegisteredTools(): Vor dem Laden des Widgets gibt es nichts zu melden, das
Ergebnis ist also erst im laufenden Betrieb aussagekräftig.
Fensterkontrolle¶
open()¶
Öffnet das Chat-Fenster. Löst beim ersten Aufruf den lazy Download aus. Kann problemlos mehrfach aufgerufen werden — es passiert dann einfach nichts zusätzlich.
close()¶
Schließt das Fenster und beendet standardmäßig die Konversation: Bei der Standardeinstellung true für
configuration.identity.closeResetsSession wird die Session zurückgesetzt, und das nächste Öffnen startet eine neue Diskussion.
Setzen Sie diese Option auf false, damit close() das Fenster nur ausblendet.
restart(options?) / restartAndOpen(options?)¶
Verwirft die aktuelle Konversation und startet eine neue. restartAndOpen öffnet zusätzlich das Fenster.
| Option | Typ | Wirkung |
|---|---|---|
retainContextKeys |
string[] |
Kontextschlüssel, die in die neue Konversation kopiert werden. Alles andere wird verworfen. Unbekannte Schlüssel werden ignoriert. |
Ohne Optionen wird der gesamte Kontext gelöscht.
restartAndClose()¶
Schließt das Fenster. Entgegen dem Namen wird die Konversation nicht neu gestartet — ob die
Session endet, entscheidet closeResetsSession, genau wie bei close().
destroy()¶
Trennt die Verbindung, entfernt das Widget, löscht registrierte Tools und Analytics und entfernt
window.daktelaAiChat. Verwenden Sie dies, wenn die Host-Seite den Chat abbaut (z. B. bei einem SPA-Routenwechsel).
Danach erfolgte Aufrufe haben keine Wirkung.
Identität¶
Über die Identität teilen Sie dem Widget mit, wer der Besucher ist, damit sein Konversationsverlauf der Person folgt und nicht dem Browser. Das Widget glaubt es Ihnen nicht einfach — es legt ein von Ihrem Identity Provider signiertes Token vor, das die Plattform prüft.
Die Einrichtung (Signaturschlüssel, Claims, Session-Dauer) beschreibt die Seite Besucher authentifizieren. Dieser Abschnitt ist die Methodenreferenz.
authorize(jwt, refreshJwt?)¶
const result = await window.daktelaAiChat.authorize(
jwt,
async () => fetchFreshJwt(), // wird aufgerufen, wenn die Session abläuft
);
if (!result.authorized) {
console.warn('Chat authorization failed:', result.reason);
}
Prüft jwt und schaltet den Chat auf die daraus entstehende Session um.
Der Aufruf wird immer erfolgreich abgeschlossen — ein Token, das die Prüfung nicht besteht, kommt
als { authorized: false, reason } zurück statt als Ausnahme, sodass ein Aufruf ohne await keine
unbehandelte Rejection erzeugen kann. reason ist einer der Werte invalid_token, not_configured,
network_error oder superseded.
Das zweite Argument ist die Funktion, die der Chat nach Ablauf der Session für ein neues Token aufruft. Sie muss ein noch gültiges Token liefern — das darf auch dasselbe wie zuvor sein: Ab läuft die Chat-Session, nicht Ihr Token, ein zwischengespeichertes, noch nicht abgelaufenes Token ist also eine gültige Antwort. Ein abgelaufenes Token, ein leerer Wert, ein geworfener Fehler oder ein Aufruf, der nie abgeschlossen wird, meldet den Besucher ab, statt es erneut zu versuchen.
Tip
Der empfohlene Zeitpunkt ist das Laden der Seite, sobald das Token vorliegt — nicht erst das Öffnen des Chats durch den Besucher. Eine Session gehört zu einem Browser-Tab, ein wiederkehrender Besucher hat also keine, bis dieser Aufruf erfolgt. Ein späterer Aufruf funktioniert und es geht nichts verloren, kostet aber eine zusätzliche Anfragerunde und einen sichtbaren Verbindungsaufbau.
authorize() allein lädt das Chat-Bundle nicht herunter. Bis etwas anderes das Laden auslöst —
open() oder ein Klick des Besuchers auf den Launcher — bleibt der Aufruf in der Warteschlange.
startDiscussion(userToken?)¶
Wechselt den Besucher in eine andere Konversation oder beginnt ohne Argument eine neue. Der Server prüft weiterhin, ob die Konversation diesem Besucher gehört, und lehnt sie andernfalls ab.
| Zeitpunkt des Aufrufs | Was geschieht |
|---|---|
| Bevor das Chat-Fenster geöffnet ist | Das Handle wird übernommen und die Konversation darunter angelegt. Es wird nichts verworfen, weil noch nichts begonnen hat. |
| Während der Besucher chattet | Die Verbindung wechselt in die andere Konversation und das Transkript auf dem Bildschirm wird mit ihr geleert — blieben die alten Nachrichten stehen, zeigte das eine Konversation, zu der die Verbindung nicht mehr gehört. |
| Mit dem bereits verwendeten Handle | Nichts. |
Ein Handle, das dem Besucher nicht gehört, lehnt der Server ab, und das Widget fängt sich von selbst: Es verwirft das abgelehnte Handle und beginnt stattdessen eine eigene Konversation. Das ist wichtig zu wissen, wenn Ihre Seite ein Handle über eine Abmeldung hinweg behält — die Konversation von vor der Abmeldung gehört dem Besucher nicht mehr, und sie lässt sich durch Zurückgeben des Handles nicht wieder öffnen.
Ein Handle, das auf eine beendete Konversation zeigt, verhält sich anders: Sie wird schreibgeschützt geöffnet, mit dem Transkript auf dem Bildschirm und gesperrtem Eingabefeld. Es ist die Konversation, die der Besucher hatte, also wird sie ihm gezeigt, statt sie ihm zu nehmen; die Schaltfläche für eine neue Konversation trägt die Abschlussnachricht des Bots.
Die Konversation, die der Besucher verlässt, wird nicht beendet — sie bleibt auf dem Server offen,
sodass er später zu ihr zurückkehren kann. Wenn Sie sie beenden möchten, rufen Sie zuerst
finishDiscussion() auf:
finishDiscussion()¶
Beendet die aktuelle Unterhaltung auf dem Server und lässt das Fenster genau so, wie es ist — das Transkript bleibt auf dem Bildschirm und wird schreibgeschützt dargestellt, wie bei jedem beendeten Chat. Es wird nichts geschlossen und nichts zurückgesetzt, sodass Sie eine Konversation beenden und eine andere beginnen können, ohne dass das Fenster dazwischen aufflackert.
Verwenden Sie stattdessen restart(), wenn Sie das Fenster in einem Schritt in eine neue Konversation
zurückversetzen möchten.
setUserToken(userToken)¶
Veraltet. Der frühere Name von startDiscussion(userToken), an den die Methode nun weiterleitet.
Ein Aufruf schreibt eine Warnung in die Konsole.
logout()¶
Widerruft die Session auf dem Server für alle Tabs und Geräte und schaltet dieses Fenster mit gelöschtem lokalem Verlauf auf eine anonyme Identität um. Sie ist für den Moment gedacht, in dem sich der Besucher von Ihrer Website abmeldet.
Was sie bewusst nicht tut:
- Die Konversation beenden. Die Unterhaltung bleibt offen und wird im Transkript mit einem Hinweis gekennzeichnet. Der Besucher kann sie nicht anonym fortsetzen, kehrt aber bei erneuter Anmeldung zu ihr zurück.
- Den Browser vergessen. Der nächste anonyme Besuch wird als derselbe Browser erkannt, der zu diesem Zeitpunkt nichts mehr vom angemeldeten Konto besitzt.
Sprache¶
setLanguage(languageCode)¶
Wechselt die Sprache der Benutzeroberfläche. languageCode ist der zweibuchstabige ISO-Code der Sprache — en, cs, sk und so weiter.
Der Code muss zu einer der für das Widget aktivierten Sprachen gehören (configuration.languages.enabledLanguages) — andernfalls wird der Aufruf
mit einer Konsolenfehlermeldung abgelehnt und nichts ändert sich. Sprachen aktivieren Sie in der Administration
(Detail des Chat-Fensters → Languages) und veröffentlichen sie anschließend; das Widget liest immer nur die veröffentlichte
Konfiguration. Auf demselben Bildschirm finden Sie auch den Code jeder aktivierten Sprache.

Note
setLanguage() erwartet Sprachcodes in Kleinbuchstaben, z. B. setLanguage('cs').
resetLanguage()¶
Verwirft die Überschreibung und kehrt zur konfigurierten Erkennung zurück.
Konversationskontext¶
Kontext ist eine Menge von Schlüssel/Wert-Paaren, die der Bot lesen kann — Bestellnummer, Tarif, Warenkorbgröße.
Schlüssel müssen so geschrieben werden, wie die Bot-Plattform ihre Variablen benennt: ein führendes $, gefolgt von einem
einzelnen Wort ohne Leerzeichen — $orderId, nicht orderId oder $order id. Ein Schlüssel, der nicht passt,
wird mit einer Konsolenfehlermeldung verworfen, da der Bot ihn ohnehin nie auflösen könnte.
Der Options-Tab in der Administration kann Kontextpaare voreinstellen. Diese setzen jede Diskussion, die das Widget
startet, einschließlich der nach einem Neustart, und wirken so als Standardwerte; ein addContext()- /
setContext()-Aufruf von der Host-Seite überschreibt denselben Schlüssel für die aktuelle Diskussion.
addContext(context)¶
window.daktelaAiChat.addContext({
$orderId: 'A-1234',
$plan: 'premium',
$note: { value: 'expires soon', lifespan: 3 },
});
Akzeptiert ein einfaches Objekt. Skalare werden automatisch umschlossen; übergeben Sie { value, lifespan },
um zu begrenzen, wie viele Bot-Runden ein Eintrag überlebt. Schlüssel werden zusammengeführt, nicht ersetzt. Wird sofort
gesendet, wenn eine Konversation aktiv ist, andernfalls der nächsten zugeordnet. Schlüssel, die die $name-Regel
verletzen, werden übersprungen; der Rest des Objekts wird trotzdem angewendet.
setContext(key, value)¶
Die Einzeleintrag-Form von addContext. Es gilt dieselbe $name-Schlüsselregel.
Erscheinungsbild¶
setCustomCss(cssText) / resetCustomCss()¶
Fügt rohes CSS in den Shadow DOM des Widgets ein. Wirkt sich erst aus, sobald das Bundle geladen ist.
Zwei Dinge, die Sie wissen sollten — beide sind häufige Ursachen für "es passiert nichts":
- Eigenes CSS wird vor dem eigenen Stylesheet des Widgets eingefügt, sodass Regeln fast immer
!importantbenötigen. - Selektoren müssen zu echten Klassen passen. Die nützlichen sind
.daktela-ai-window,.daktela-ai-header,.daktela-ai-launcher-button,.daktela-ai-message-buttonund.daktela-ai-home-screen.
Das Widget protokolliert eine Warnung, sobald eigenes CSS angewendet wird. Das ist beabsichtigt — Klassennamen sind kein stabiler Vertrag, testen Sie eigenes CSS daher nach Widget-Updates erneut.
Seiten-Aktions-Tools¶
Das Agent-Modul — das LLM, das Ihre Dialoge steuert — kann neben dem Prompt auch Tools nutzen. Ein Typ davon sind API-Integrationen, die Ihre Backend-Endpunkte aufrufen. Seiten-Aktions-Tools sind der zweite Typ: eine JavaScript-Funktion, die direkt auf Ihrer Seite läuft und die Sie mit registerTool() registrieren — so kann der Agent in Ihre Seite zurückrufen (eine Bestellung nachschlagen, ein Element hervorheben, ein Ticket öffnen), ohne dass Daten den Browser des Besuchers verlassen.
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) }),
});
| Feld | Typ | Hinweise |
|---|---|---|
name |
string |
Eindeutig; eine erneute Registrierung desselben Namens ersetzt das Tool. |
description |
string |
Was der Assistent liest, um zu entscheiden, wann er es aufruft. |
parameters |
JSON Schema | Objektschema. Nur required auf oberster Ebene und primitive Typen werden validiert. |
handler |
(args) => unknown |
Synchron oder asynchron. Verlässt nie den Browser. |
confirm |
boolean |
Optional. Zeigt vor der Ausführung eine Bestätigungs-/Ablehnungsaufforderung. |
Ein Handler kann jeden JSON-serialisierbaren Wert zurückgeben; dieser wird an den Assistenten zurückgegeben. Fehler
werden als handler_error gemeldet, ein Handler, der 30 Sekunden überschreitet, als timeout, eine abgelehnte
Aufforderung als user_declined.
Timing: Die registrierte Menge wird jeder ausgehenden Besuchernachricht angehängt, nicht dem initialen Handshake. Registrieren Sie Tools, bevor der Besucher seine erste Nachricht sendet — der erste Zug des Bots sieht sie nicht.
Info
Ein Tool zu registrieren macht es für den Agent verfügbar, sagt ihm aber noch nicht, wann er es einsetzen soll. Genau wie bei API-Integrationen müssen Sie das Tool (anhand seines name) direkt in den Agent-Instruktionen erwähnen — z. B. „Nutze das Tool openTicket, wenn der Kunde ein Support-Ticket öffnen möchte."
unregisterTool(name) / getRegisteredTools()¶
getRegisteredTools() gibt die aktuell geltenden Schemas zurück (ohne Handler), also das,
was eine ausgehende Nachricht mitführt.
Alte ew-*-Custom-Events¶
Diese existieren aus einem einzigen Grund: damit eine bereits mit dem alten Chat-Fenster integrierte Seite nach dem Upgrade weiter funktioniert, ohne ihren Code anzufassen. Event-Namen, Payloads und Effekte entsprechen dem alten Widget.
Für alles Neue verwenden Sie die obige JavaScript-API — sie ist die unterstützte Oberfläche, deckt mehr ab und meldet Fehler. Die Events werden nur aus Kompatibilitätsgründen gepflegt.
Lösen Sie sie auf window aus:
| Event | Wirkung | API-Äquivalent |
|---|---|---|
ew-open-window |
Öffnet das Fenster | open() |
ew-hide-window |
Blendet das Fenster aus, ohne die Konversation zu beenden | — |
ew-toggle-window |
Öffnet oder blendet aus | — |
ew-end-discussion |
Beendet die Konversation auf dem Server, sodass sich der Assistent verabschieden und um eine Bewertung bitten kann; das Fenster bleibt geöffnet. Erneutes Auslösen nach Ende der Konversation schließt sie und startet neu. | — |
ew-reset-chat |
Startet eine neue Konversation, Fensterstatus unverändert | restart() |
ew-close-and-reset-chat |
Schließt das Fenster und startet eine neue Konversation | restartAndClose() |
add-context |
Ein Kontexteintrag, detail: { key, value } |
setContext(key, value) |
chatbot-ew-context-set |
Gesamtes Kontextobjekt in detail |
addContext(object) |
ew-set-dark-mode |
Erzwingt das dunkle Theme | — |
ew-set-light-mode |
Erzwingt das helle Theme | — |
ew-set-system-theme-mode |
Folgt dem Theme des Betriebssystems | — |
ew-enable-ga / ew-disable-ga |
Schaltet die Google-Analytics-Berichterstattung um. ew-disable-ga stoppt nur Google Analytics — Google Tag Manager erhält weiterhin Events, wie beim alten Widget. |
— |