Zum Inhalt

Chat einbetten und eigene Widgets

Es gibt im CLYE AI mehrere Wege, einen Chat außerhalb der normalen Oberfläche zu nutzen. Welcher Weg sinnvoll ist, hängt davon ab, wie viel Kontrolle du über Design, Zugriff und Verhalten brauchst.

Überblick

Variante Geeignet für Zugriff Eigener UI-Aufwand
Öffentliches Script-Widget Website, Landingpage, einfache Einbindung öffentlich freigegebener Assistent sehr gering
Widget per iFrame Portale, Login-geschützte Bereiche, kontrollierte Freigabe JWT oder Assistant Access Link gering
Eigenes Widget mit AI SDK volle UI-Kontrolle, eigenes Frontend, Produktintegration meist Assistant Access Link hoch

Als Grundregel gilt:

  • Nutze die integrierten Widgets, wenn du schnell einbettbar bleiben willst.
  • Nutze Assistant Access Links, wenn Zugriff, Filter und Features serverseitig kontrolliert werden sollen.
  • Nutze das AI SDK, wenn du das komplette Frontend selbst bauen willst.

Integrierte Widgets

Im Bot-Frontend wird ein eigenständiges Bundle widget.js gebaut. Dieses Bundle kann direkt in fremde Websites geladen werden und registriert mehrere Custom Elements.

1. Öffentliches Chat-Widget

Für die meisten Websites ist das die einfachste Variante:

<script type="module" src="https://bot.clye.app/widget.js"></script>
<clye-bot-chat bot-id="123"></clye-bot-chat>

Dieses Element rendert die bekannte Chat-Bubble und hängt sie an den body der Seite. Im Code ist das die empfohlene öffentliche Standard-Einbindung.

Wichtige Attribute:

  • bot-id: numerische ID des Assistenten
  • side: "left" oder "right"
  • blend-mode: z. B. "normal" oder "difference"
  • dark: optional für dunkle Darstellung
  • domain: falls das Widget gegen eine andere Bot-Domain sprechen soll
  • style-url: alternative CSS-Datei für die Bubble

Praktisch heißt das: Wenn eure Seite eigenes HTML erlaubt, reicht oft schon das Script plus das Element.

2. Direkte Bubble-Komponenten

Zusätzlich registriert widget.js niedrigere Bausteine:

  • clye-bot-bubble
  • clye-bot-bubble-open-shadow

Die beiden Varianten sind nützlich, wenn du die Bubble gezielter kontrollieren willst – zum Beispiel wenn du sie direkt in eine bestimmte Stelle im DOM einbetten willst, anstatt sie über das Portal-Verhalten von clye-bot-chat an den body anzuhängen.

Der Unterschied liegt im Shadow DOM:

  • clye-bot-bubble nutzt ein geschlossenes Shadow DOM (empfohlen, Styles sind isoliert)
  • clye-bot-bubble-open-shadow nutzt ein offenes Shadow DOM (nützlich, wenn du per JavaScript von außen in das Shadow DOM zugreifen musst)
<script type="module" src="https://bot.clye.app/widget.js"></script>
<clye-bot-bubble bot-id="123" side="right"></clye-bot-bubble>

Wichtige Attribute:

Attribut Typ Beschreibung
bot-id Zahl Numerische ID des Assistenten (Pflichtfeld)
side "left" | "right" Auf welcher Seite die Bubble erscheint
dark Boolean Aktiviert die dunkle Darstellung
style-url String Pfad zu einer alternativen CSS-Datei
domain String Alternative Bot-Domain

Der Unterschied zu clye-bot-chat: clye-bot-chat ist ein Portal-Element, das die Bubble selbst erzeugt und direkt an den document.body anhängt. clye-bot-bubble hingegen rendert an der Stelle im DOM, wo du das Element platzierst.

blend-mode wird bei clye-bot-bubble nicht als HTML-Attribut unterstützt. Für blend-mode nutze clye-bot-chat.

3. Frage-Widget

Für vordefinierte Einstiegsfragen gibt es zusätzlich:

<script type="module" src="https://bot.clye.app/widget.js"></script>
<clye-bot-question
  bot-id="123"
  label="Schnellstart"
  question="Wie kann ich helfen?"
  bot-question="Erkläre kurz, was du kannst."
></clye-bot-question>

Wichtige Attribute:

  • bot-id
  • label
  • question
  • bot-question
  • answers als JSON
  • domain

Das ist sinnvoll, wenn nicht sofort ein vollständiger Chat erscheinen soll, sondern erst ein klarer Einstiegspunkt.

4. Web-Component-Konstruktoren aus dem Widget-Bundle

Das Bundle legt zusätzlich window.clyeBot an. Dort liegen die Web-Component-Konstruktoren für alle registrierten Elemente:

Eigenschaft Registriert als Beschreibung
window.clyeBot.Chat (nicht vorregistriert) Vollständige Chat-Ansicht ohne Bubble-Wrapper. Muss manuell registriert werden.
window.clyeBot.Bubble clye-bot-bubble Identisch mit dem gleichnamigen Custom Element
window.clyeBot.Question clye-bot-question Identisch mit dem gleichnamigen Custom Element

window.clyeBot.Chat ist der einzige Konstruktor, der nicht automatisch als Custom Element registriert wird. Das gibt dir die Möglichkeit, ihn unter einem eigenen Tag-Namen einzubinden:

<script type="module">
  import "https://bot.clye.app/widget.js";
  // eigener Tag-Name, weil clye-bot-chat bereits ein Portal-Element ist
  customElements.define("mein-chat", window.clyeBot.Chat);
</script>

<mein-chat bot-id="123"></mein-chat>

window.clyeBot.Chat rendert die Chat-Oberfläche direkt (ohne Bubble und Floating-Button). Unterstützte Attribute: bot-id (Zahl), domain (String).

Widget per iFrame

Wenn du den Chat als komplette, kontrollierte Oberfläche einbetten willst, bleibt das iFrame-Widget der stabilste Weg:

<iframe
  src="https://dein-hub.example/widget/<TOKEN>"
  style="width: 100%; height: 600px; border: none;"
  allow="clipboard-write"
></iframe>

Dafür gibt es zwei Token-Varianten:

  • JWT-Widget: gut für einfache, kurze Claims wie botId und exp
  • Assistant Access Link: besser für serverseitig erzwungene Filter, Features und längere Payloads

Mehr dazu:

Eigene Chat-Widgets mit AI SDK

Wenn du das Frontend komplett selbst bauen willst, ist der relevante Pfad im Bot-Repo die Kombination aus:

  • @ai-sdk/react für useChat
  • ai für DefaultChatTransport
  • POST /api/chat als Backend-Endpunkt

Genau dieses Muster wird im Bot selbst verwendet, sowohl für eingebettete Chats als auch für normale Chat-Oberflächen.

Wann das sinnvoll ist

Ein eigenes Widget mit AI SDK ist sinnvoll, wenn du:

  • Design und UX vollständig selbst bestimmen willst
  • den Chat in eine bestehende Produktoberfläche integrieren willst
  • zusätzliche UI-Elemente wie Tabs, Formulare, Produktdaten oder Prozessschritte kombinieren willst
  • nicht an Bubble- oder iFrame-Layout gebunden sein willst

Wichtiger Unterschied zu JWT-Widgets

Für eigene AI-SDK-Frontends ist in der Regel der Assistant Access Link der richtige Zugriffspfad.

Der Grund: Das Chat-Backend leitet externe Sitzungen aus assistantAccessToken ab. Dieser Token wird im Request-Body mitgegeben. Das JWT-Widget ist dagegen primär für die Route /widget/{token} gedacht.

Kurz gesagt:

  • iFrame auf /widget/{token}: JWT oder Assistant Access Link möglich
  • Eigenes Frontend auf /api/chat: bevorzugt Assistant Access Link verwenden

Minimales React-Beispiel

Benötigte Version: Das Beispiel basiert auf AI SDK v5 (ai und @ai-sdk/react in derselben Major-Version, idealerweise beide auf ^5).

import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";

type Props = {
  botId: number;
  assistantAccessToken?: string;
};

export function EmbeddedChat({ botId, assistantAccessToken }: Props) {
  const chat = useChat({
    transport: new DefaultChatTransport({
      api: "https://<deine-whitelabel-domain>/api/chat",
      body: {
        botId,
        ...(assistantAccessToken ? { assistantAccessToken } : {}),
      },
    }),
  });

  return (
    <div>
      <div>
        {chat.messages.map((message) => (
          <div key={message.id}>
            <strong>{message.role}:</strong> {message.parts?.map((p: any) => p.text).join("")}
          </div>
        ))}
      </div>

      <form
        onSubmit={(event) => {
          event.preventDefault();
          const formData = new FormData(event.currentTarget);
          const text = String(formData.get("message") || "");
          if (!text.trim()) return;
          chat.sendMessage({ text });
          event.currentTarget.reset();
        }}
      >
        <input name="message" placeholder="Nachricht..." />
        <button type="submit">Senden</button>
      </form>
    </div>
  );
}

Praxisbeispiel mit öffentlichem Assistenten (für alle freigegeben):

Das Beispiel ist bewusst minimal. In der Praxis wirst du meist noch ergänzen:

  • persistente chatId pro Session
  • eigenes Fehler-Handling
  • Wiederaufnahme laufender Streams
  • Uploads oder Tool-Interaktionen
  • eigenes Rendering für strukturierte Antworten und Tool-Calls

Was das Backend erwartet

Der Chat-Endpunkt akzeptiert unter anderem:

  • botId
  • messages oder newMessages
  • optional assistantAccessToken
  • optional id für eine persistente Chat-ID

Wenn ein assistantAccessToken gesetzt ist, wird serverseitig daraus eine minimale Widget-Session abgeleitet. Darüber können auch permissionFilter, loginUrl, features.chatHistory und Widget-Kontext aus dem Access Link wirksam werden.

Für eigene Widgets sieht der saubere Ablauf so aus:

  1. Dein Portal oder Backend prüft die Anmeldung des Nutzers.
  2. Dein Server ruft POST /api/assistant-link auf.
  3. Die Antwort liefert token, url und jwtPayload.
  4. Dein Frontend verwendet den token als assistantAccessToken für POST /api/chat.

Damit bleiben Berechtigungen, Filter und Ablaufzeit auf deiner Server-Seite kontrollierbar.

Welche Variante in der Praxis passt

Nutze das öffentliche Script-Widget, wenn eine Website schnell einen Assistenten bekommen soll.

Nutze das iFrame-Widget, wenn du die vorhandene Chat-Oberfläche übernehmen und nur kontrolliert einbetten willst.

Nutze ein eigenes AI-SDK-Widget, wenn der Chat Teil eures Produkts werden soll und visuell oder funktional stark an eure Anwendung angepasst werden muss.

Kurz gesagt

Die integrierten Widgets decken den schnellen Einbau ab. Für eine kontrollierte externe Nutzung ist meist der Assistant Access Link die beste Grundlage. Wenn du dagegen die Oberfläche selbst besitzen willst, orientiere dich am im Bot bereits verwendeten Muster aus useChat, DefaultChatTransport und POST /api/chat.