Zum Inhalt springen
Farbschema wählenSprache wählen

Support-Konversationskanal verbinden (Chatwoot / Intercom)

SupaCloud kann als KI-Resolution-Backend hinter Chatwoot und Intercom agieren. Eine eingehende Kundennachricht wird HMAC-verifiziert, als gegateter Backlog-Eintrag eingereiht und von einem Agenten bearbeitet, der über governte conversation.*-Tools liest und antwortet — eine ConversationProvider-Naht, zwei Transport-Adapter.

Die Verbindungen-Tafel mit jeder eingerichteten Ressource, ihrer Art und ihrem Status.Die Verbindungen-Tafel mit jeder eingerichteten Ressource, ihrer Art und ihrem Status.
  • Ein Chatwoot-Konto (selbstgehostet oder Cloud) mit einem Agent-Bot-Access-Token oder ein Intercom-Workspace mit einem Workspace-Access-Token.
  • Für Chatwoot: die Instanz-Basis-URL + die numerische account_id. Für Intercom: die Region (us / eu / au) + die Bot-admin_id.
  • Das Webhook-Signing-Secret, mit dem die jeweilige Plattform Zustellungen signiert (das Chatwoot-Inbox-HMAC-Secret / das Intercom-App-client_secret).
  • Ein Workspace, in dem du Ressourcen und einen Workflow anlegen darfst.
  1. Kanal-Ressource anlegen.

    Unter Ressourcen → Neu wähle Chatwoot oder Intercom.

    • Chatwoot — setze base_url (z. B. https://chat.example.com) und account_id; füge das Agent-Bot-Access-Token als Secret ein. Da ein selbstgehosteter Host vom Betreiber stammt, läuft jeder ausgehende Aufruf dorthin über SupaClouds SSRF-gepinnten Client.
    • Intercom — wähle die region und setze die Bot-admin_id; füge das Workspace-Access-Token als Secret ein. Intercoms regionaler API-Host ist eine feste Allowlist, daher ist kein SSRF-Pinning nötig.
  2. Eingehenden Konversations-Trigger hinzufügen.

    Füge dem Workflow, der Konversationen verarbeiten soll, einen Trigger der Art chatwoot_conversation oder intercom_conversation hinzu. Konfiguriere:

    • resource_id — die Kanal-Ressource aus Schritt 1 (wird automatisch gebunden, wenn der Workspace genau eine Ressource dieser Art hat).
    • signing_secret — das Webhook-HMAC-Secret, mit dem die Plattform signiert.
    • modeauto-reply (Agent antwortet autonom, unter deinen Autonomie-/ Budget-Gates), human-gate (Antwort wartet auf menschliche Freigabe) oder notify-only (verifizierte Zustellungen werden bestätigt, starten aber keine Agentenarbeit).

    Der Trigger lässt sich erst aktivieren, wenn sowohl resource_id als auch signing_secret gesetzt sind. Kopiere seine Empfänger-URL aus dem Panel Trigger des Workflows.

  3. Plattform-Webhook verdrahten.

    Richte die Plattform auf die Empfänger-URL des Triggers:

    • Chatwoot (Einstellungen → Integrationen → Webhooks): abonniere Conversation Created + Message Created und setze das HMAC-Secret auf dein signing_secret. SupaCloud verifiziert X-Chatwoot-Signature = HMAC-SHA256 über {X-Chatwoot-Timestamp}.{body}, mit Stale-Timestamp- Replay-Schutz.

      POST <server public_url>/api/workflows/triggers/chatwoot/<token>
    • Intercom (Developer Hub → Webhooks): abonniere conversation.user.created + conversation.user.replied und setze das signing_secret des Triggers auf das client_secret deiner App. SupaCloud verifiziert X-Hub-Signature = HMAC-SHA1 über den Rohbody.

      POST <server public_url>/api/workflows/triggers/intercom/<token>
  4. Den Agenten Konversationen lösen lassen.

    Eine verifizierte neue Konversation / eingehende Kundennachricht wird als Backlog-Eintrag eingereiht und unter denselben Autonomie-, Budget- und Ruhezeiten-Gates wie jede andere Arbeit dispatched. Der Agent liest und handelt über die conversation.*-MCP-Tools: conversation.get / conversation.list (lesend) sowie conversation.reply / assign / resolve / handoff (Ops). Eine kundensichtbare Antwort läuft über denselben SSRF-geprüften Sender; handoff ist die explizite Eskalation zurück an ein menschliches Team.

Eine Inbox, an die jeder schreiben kann, ist der eine Kostenpfad in SupaCloud, den ein Unbeteiligter auslösen kann. Jeder andere — eine Task starten, aus dem Backlog dispatchen, ein MCP-Tool rufen — setzt ein Konto, eine Mitgliedschaft oder ein Token voraus. Dieser setzt die Inbox-Adresse voraus. Die folgenden Deckel sind deshalb standardmäßig aktiv; Sie müssen sie nicht einschalten.

Zwei Achsen, die verschiedene Fragen beantworten.

Je Kontakt — die Kostenachse. Der Angriff, der wirkt, ist ein Unbeteiligter, der Konversation um Konversation eröffnet. Beachten Sie: Konversation, nicht Nachricht — eine zweite Nachricht in einem bestehenden Faden ist bereits gratis, weil der Backlog-Eintrag auf die Konversation schlüsselt und damit dedupliziert wird, bevor irgendein Modell gefragt wird.

Deckel Vorgabe Was er begrenzt
contact_conversations_per_day 20 Neue Konversationen, die ein Kontakt in einem rollenden Tag eröffnen darf
contact_messages_per_hour 60 Eingehende Nachrichten eines Kontakts in einer rollenden Stunde

Eine Überschreitung ist eine Abweisung: kein Modellaufruf, der Kontakt bekommt eine kurze statische Zeile, dass ein Mensch übernimmt, und es wird ein Audit-Eintrag geschrieben. Die wichtige Eigenschaft — die ein workspace-weites Budget nicht hat — ist, dass ein erschöpfter Kontakt jeden anderen Kontakt unberührt lässt.

Je Konversation — die Qualitätsachse. Ein Faden, der endlos wächst, ist über das hinausgewachsen, was ein Bot beantworten sollte.

Deckel Vorgabe Was er begrenzt
conversation_rounds 40 Eingehende Züge in einer Konversation
conversation_context_tokens 24000 Geschätzte Token des angesammelten Fadentexts

Eine Überschreitung ist hier eine Übergabe, keine Abweisung: der Kunde ist nicht das Problem. Der Faden geht an das menschliche Team, das die Ressource optional in handoff_team nennt, und der Kunde wird informiert. Ohne handoff_team wird der Kunde trotzdem informiert; es wird kein Team zugewiesen, denn eine erfundene Team-ID würde jemanden dorthin leiten, wo niemand hinsieht.

Ergänzen Sie die Trigger-Konfiguration um einen abuse_caps-Block. Was Sie weglassen, behält seine Vorgabe:

{
"resource_id": "",
"signing_secret": "",
"mode": "human-gate",
"abuse_caps": { "contact_conversations_per_day": 5 }
}

Ein fehlerhafter Wert — eine Zeichenkette, eine negative Zahl oder 0 — wird ignoriert, die eingebaute Vorgabe bleibt in Kraft. Besonders 0 wird abgelehnt statt als „unbegrenzt” gelesen: an einer öffentlichen Inbox wäre das der teuerste Tippfehler, den es gibt.

Wenn eine Inbox angegriffen wird, schalten Sie sie stumm — ohne Deploy und ohne den Trigger zu löschen:

PUT /api/operator/v1/switches/conversation_dispatch
{ "enabled": false, "reason": "abuse incident" }

Aus bedeutet: die autonome Hälfte stoppt, und nur die. Eine Zustellung wird weiterhin authentifiziert, weiterhin im Faden gespeichert und weiterhin quittiert, damit der Anbieter aufhört zu wiederholen. Nichts, was ein Kunde geschrieben hat, geht verloren, und die Integration bleibt verdrahtet; Sie schalten zurück, wenn der Vorfall vorbei ist.

Der Schalter komponiert global-UND-workspace: ein Workspace kann seine eigene Inbox stummschalten, aber nie an einem globalen „aus” vorbei wieder einschalten. Er ist absichtlich ein anderer Schalter als global_dispatch — jener greift erst am Dispatch, also nachdem der Klassifizierer bereits bezahlt wurde.

Jeder ausgelöste Deckel schreibt einen Audit-Eintrag — conversation.rate_limited für eine Abweisung, conversation.handed_off für eine Übergabe — mit dem Deckel, der gegriffen hat, und der betroffenen Konversation. Ohne sie sähe eine stummgeschaltete Inbox genauso aus wie eine ruhige.

Das meiste, was an einer öffentlichen Inbox ankommt, beantwortet eine Seite der Produktdokumentation bereits. Solche Fragen aus der Seite selbst zu beantworten kostet nichts: es wird kein Modell aufgerufen, die Antwort ist sofort da und gratis. Die Funktion ist standardmäßig aus und wird je Kanal eingeschaltet.

Ergänzen Sie die Trigger-Konfiguration um einen docs_first-Block:

{
"resource_id": "",
"signing_secret": "",
"mode": "human-gate",
"docs_first": { "enabled": true, "min_score": 0.6, "lang": "de" }
}
  • enabled — aus, solange Sie nichts anderes sagen. Ob Ihren Kundinnen und Kunden aus einem Dokumentenbestand geantwortet wird, entscheiden Sie — nie ein Deploy.
  • min_score — wie viel der Frage die gewinnende Seite abdecken muss, größer 0 und höchstens 1. 0.6 heißt ungefähr „zwei von drei inhaltlichen Wörtern”. Höher stellen heißt: seltener antworten, dafür sicherer.
  • lang — welche Hälfte des Bestands durchsucht wird, en oder de. Nie beide: eine deutsche Kundin aus einer englischen Seite zu beantworten ist schlechter, als gar nicht zu antworten.

Ein falscher Wert im Block fällt auf die obige Voreinstellung zurück, und ein Kanal ohne docs_first-Block verhält sich exakt wie zuvor.

  • Geantwortet wird mit einem Zitat und der Seite, aus der es stammt. Es gibt keine Umformulierung, denn Umformulieren wäre ein Modellaufruf — genau das, was dieser Pfad vermeiden soll — und eine Antwort ohne Seite dahinter ist geraten.
  • Eine Begrüßung oder eine Zwei-Wort-Nachricht ist keine Nachschlagefrage und wird nicht beantwortet.
  • Ein langer Problembericht ist ebenfalls keine Frage; er gehört dem Agenten.
  • Deckt keine Seite genug von der Frage ab, wird nichts gesendet und die Konversation nimmt den gewohnten Weg. Einschalten kostet Sie keine Konversation.
  • Auf einer Instanz ohne bereitgestellte Dokumentation ist der Pfad schlicht inaktiv.

Wo er sitzt — und warum das der ganze Entwurf ist

Abschnitt betitelt „Wo er sitzt — und warum das der ganze Entwurf ist“

Die Doku-Antwort läuft hinter dem Missbrauchsdeckel von oben, nie davor. Eine Antwort, die der Deckel nicht gesehen hat, wäre eine kostenlose Antwort, und ein Fremder könnte beliebig viele davon aus einer öffentlichen Inbox ziehen — der Deckel wäre Dekoration. Ein Kontakt über seinem Deckel wird deshalb abgewiesen; er bekommt nicht ersatzweise Doku-Antworten.

Jede Antwort schreibt eine Audit-Zeile conversation.docs_answered, die die zitierte Seite benennt. So ist sichtbar statt vermutet, was der billige Pfad gespart hat.