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.


Voraussetzungen
Abschnitt betitelt „Voraussetzungen“- 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.
Schritte
Abschnitt betitelt „Schritte“-
Kanal-Ressource anlegen.
Unter Ressourcen → Neu wähle Chatwoot oder Intercom.
- Chatwoot — setze
base_url(z. B.https://chat.example.com) undaccount_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
regionund 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.
- Chatwoot — setze
-
Eingehenden Konversations-Trigger hinzufügen.
Füge dem Workflow, der Konversationen verarbeiten soll, einen Trigger der Art
chatwoot_conversationoderintercom_conversationhinzu. 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.mode—auto-reply(Agent antwortet autonom, unter deinen Autonomie-/ Budget-Gates),human-gate(Antwort wartet auf menschliche Freigabe) odernotify-only(verifizierte Zustellungen werden bestätigt, starten aber keine Agentenarbeit).
Der Trigger lässt sich erst aktivieren, wenn sowohl
resource_idals auchsigning_secretgesetzt sind. Kopiere seine Empfänger-URL aus dem Panel Trigger des Workflows. -
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 verifiziertX-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.repliedund setze dassigning_secretdes Triggers auf dasclient_secretdeiner App. SupaCloud verifiziertX-Hub-Signature= HMAC-SHA1 über den Rohbody.POST <server public_url>/api/workflows/triggers/intercom/<token>
-
-
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) sowieconversation.reply/assign/resolve/handoff(Ops). Eine kundensichtbare Antwort läuft über denselben SSRF-geprüften Sender;handoffist die explizite Eskalation zurück an ein menschliches Team.
Missbrauchsschutz an einer öffentlichen Inbox
Abschnitt betitelt „Missbrauchsschutz an einer öffentlichen Inbox“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.
Was gedeckelt wird, und auf welcher Achse
Abschnitt betitelt „Was gedeckelt wird, und auf welcher Achse“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.
Einen Deckel enger oder weiter stellen
Abschnitt betitelt „Einen Deckel enger oder weiter stellen“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.
Der Not-Aus
Abschnitt betitelt „Der Not-Aus“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.
Was hinterher sichtbar ist
Abschnitt betitelt „Was hinterher sichtbar ist“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.
Zuerst aus der Dokumentation antworten
Abschnitt betitelt „Zuerst aus der Dokumentation antworten“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ößer0und höchstens1.0.6heiß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,enoderde. 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.
Was beantwortet wird — und was nicht
Abschnitt betitelt „Was beantwortet wird — und was nicht“- 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.