40 KiB
Premium – WAHA: Automatisierte Statusmeldungen & KI-gestützte Antworten
WAHA ist im UCC weit mehr als ein Werkzeug zum Senden einzelner WhatsApp-Nachrichten.
Im Premium-Kapitel wird der Dienst zu einem intelligenten Kommunikationsmodul, das auf Ereignisse in deinem System reagieren und Informationen automatisiert weitergeben kann.
Ziel ist eine vollständige Integration von WAHA in deine bestehende Infrastruktur – vor allem in Verbindung mit n8n und Netdata.
So kannst du dich über wichtige Systemereignisse informieren lassen oder, optional, eingehende Nachrichten automatisch beantworten lassen – datensouverän, lokal und ohne externe Cloud-APIs.
Das Kapitel ist in zwei praxisnahe Szenarien unterteilt:
-
Automatische Statusbenachrichtigung über WhatsApp
– Wenn Netdata einen Alarm oder kritischen Wert erkennt, löst n8n automatisch eine WhatsApp-Nachricht über WAHA aus.
– Du erhältst sofort eine Benachrichtigung über Auslastung, Fehler oder Warnungen, ohne dich aktiv einloggen zu müssen. -
KI-gestützte, regelkonforme Antwortfunktion
– Eine eingehende WhatsApp-Nachricht wird von WAHA empfangen, in n8n verarbeitet und an eine lokale KI weitergeleitet.
– Die KI generiert eine personalisierte Antwort, die über WAHA zurückgesendet wird.
– Diese Variante bewegt sich aktuell im erlaubten Rahmen, da sie nur auf vom Nutzer initiierte Nachrichten reagiert,
liegt jedoch im Graubereich zukünftiger Richtlinienänderungen.
Caution
Die Nutzung einer automatisierten KI-Antwort über WAHA ist derzeit zulässig, solange jede Kommunikation vom Nutzer selbst initiiert wird
und keine Werbung oder massenhafte Nachrichten versendet werden.
Beachte jedoch, dass Meta die WhatsApp-Richtlinien jederzeit ändern kann.
Sollte WhatsApp künftig KI-basierte Antworten oder WAHA-ähnliche Systeme einschränken,
kann dieses Setup Anpassungen erfordern.
👉 Screenshot geeignet: Diagramm mit Datenfluss zwischen Netdata, n8n, KI-Agent und WAHA
Am Ende dieses Kapitels verfügst du über ein vollständig integriertes Benachrichtigungs- und Kommunikationssystem,
das deine Infrastruktur in Echtzeit überwacht und bei Bedarf automatisiert reagiert –
ein klarer Schritt in Richtung eines selbstlernenden, souveränen Kontrollzentrums.
Statusbenachrichtigung über WAHA
Schritt 1 – n8n-Workflow mit Deduplizierung und WAHA-Versand
Ziel: Ein n8n-Workflow soll Systemereignisse aus Netdata empfangen, diese in Textform bringen, doppelte Alarme herausfiltern und anschließend über WAHA als WhatsApp-Nachricht versenden.
Damit entsteht ein zentraler Benachrichtigungsweg für kritische Zustände im gesamten UCC.
👉 Screenshot geeignet: n8n-Canvas mit drei verbundenen Nodes: Webhook (POST) → Function (Nachricht & Filter) → HTTP Request (WAHA)
Node 1 – Webhook (Trigger)
Zweck: Erstellt eine Empfangsadresse, über die Netdata Alarmmeldungen an n8n sendet.
Node-Typ: Webhook
Name: Eingang – Statusalarm
Parameter:
- HTTP Method:
POST - Path:
/waha/statusalarm - Response Mode:
Last Node - Response Code:
200
Note
Nach dem Speichern zeigt n8n automatisch die Webhook-URL an, z. B.:
https://n8n.deinedomain.tld/webhook/waha/statusalarm
Diese URL wird später in der Netdata-Alarmregel eingetragen, damit Netdata Alarme direkt an diesen Workflow sendet.
👉 Screenshot geeignet: Webhook-Node mit sichtbarer URL .../webhook/waha/statusalarm
Node 2 – Function (Nachricht aufbereiten + Dedupe)
Zweck: Formatiert die eingehenden Daten und verhindert, dass wiederholt identische Alarme mehrfach gesendet werden.
Die Funktion merkt sich den letzten Alarm jedes Containers für 10 Minuten.
Wenn innerhalb dieses Zeitraums derselbe Host und Alarm erneut eintreffen, wird die Nachricht unterdrückt.
Node-Typ: Function
Name: Nachricht & Filter
Code:
const p = items[0].json || {};
const host = p.host || 'unbekannt';
const alarm = p.alarm || 'Alarm';
const status = p.status || 'warn';
const value = (p.value !== undefined && p.value !== null) ? String(p.value) : '-';
const when = p.when || new Date().toISOString();
const key = `${host}_${alarm}_${status}`;
const now = Date.now();
const last = $flow.get(key) || 0;
const interval = 10 * 60 * 1000; // 10 Minuten
if (now - last < interval) {
// gleicher Alarm innerhalb von 10 Minuten -> überspringen
return [];
}
$flow.set(key, now);
const text =
`⚠️ ${alarm}\n` +
`Host: ${host}\n` +
`Status: ${status}\n` +
`Wert: ${value}\n` +
`Zeit: ${when}`;
return [{ json: { text } }];
Tip
Die Filterzeit lässt sich über die Variable
intervalanpassen.
Für produktive Umgebungen mit vielen Containern sind 10 bis 15 Minuten meist ideal.
👉 Screenshot geeignet: Function-Node mit geöffnetem Code-Editor, markiertem Kommentar // gleicher Alarm innerhalb von 10 Minuten
Node 3 – HTTP Request (WAHA – Statusmeldung senden)
Zweck: Sendet die aufbereitete Nachricht über WAHA an WhatsApp.
Node-Typ: HTTP Request
Name: WAHA – Statusmeldung senden
Parameter:
- Method:
POST - URL:
https://waha.deinedomain.tld/api/sendText - Headers:
Content-Type:application/json- (optional)
Authorization:Bearer <DEIN_WAHA_API_TOKEN>
- Body → JSON:
{ "chatId": "49XXXXXXXXXXX@c.us", "text": "={{$json[\"text\"]}}" }
Note
Chat-ID ermitteln:
- Sende mit deinem WhatsApp-Gerät eine Testnachricht an den Ziel-Chat.
- Öffne
https://waha.deinedomain.tld/api/messages.- Kopiere den Wert
chatIdaus der letzten eingegangenen Nachricht.
– Einzelchat endet auf@c.us
– Gruppenchat endet auf@g.us- Trage diese ID im Node ein.
Important
WAHA muss im Webinterface den Status Connected anzeigen.
Bei Pairing oder Disconnected kann keine Nachricht gesendet werden.
👉 Screenshot geeignet: HTTP-Request-Node mit sichtbarer chatId
Test des Workflows
Der Workflow kann manuell getestet werden, bevor Netdata angebunden ist:
curl -X POST "https://n8n.deinedomain.tld/webhook/waha/statusalarm" \
-H "Content-Type: application/json" \
-d '{
"host": "ucc-core-01",
"alarm": "CPU high",
"status": "crit",
"value": "96%",
"when": "2025-10-20T18:42:00Z"
}'
Wenn alles funktioniert, erscheint die Meldung wenige Sekunden später als WhatsApp-Nachricht.
👉 Screenshot geeignet: WhatsApp-Chat mit empfangener Meldung „⚠️ CPU high …“
Tip
Wenn keine Nachricht ankommt, prüfe in n8n die Execution Logs.
Dort sollte der HTTP-Request-Node den Statuscode200zurückgeben.
Wird keine Ausführung gestartet, ist meist der Webhook-Pfad falsch oder Netdata erreicht den Server nicht.
Schritt 2 – Netdata-Alarmregel im Parent-LXC für WAHA-Benachrichtigung
Die zentrale Netdata-Instanz im UCC empfängt bereits alle Metriken der Child-Container per Streaming.
Damit entfällt die Notwendigkeit, in jedem einzelnen LXC eigene Alarme zu konfigurieren.
Stattdessen wird eine einzige Alarmregel direkt im Parent-Container hinterlegt,
die auf aggregierte Systemwerte zugreift und bei Erreichen bestimmter Schwellwerte eine Nachricht über n8n → WAHA sendet.
👉 Screenshot geeignet: Netdata-Parent-Dashboard mit aktivem Alarm für einen Child-Container
[!INFO]
Die zentrale Überwachung mit Netdata setzt voraus, dass alle Child-LXC-Container korrekt angebunden sind.
Im Kapitel 15 – Netdata wird beschrieben, wie du das Streaming-System einrichtest
und wie die einzelnen Container ihre Metriken an den Parent weitergeben.
Es wird dringend empfohlen, dieses Kapitel vollständig umzusetzen,
bevor du hier mit der WAHA-Benachrichtigung fortfährst –
sonst können Alarme fehlen oder falsche Hostnamen übermittelt werden.
Zentrale Alarmregel anlegen
-
Öffne auf deinem Netdata-Parent-LXC die Health-Konfiguration:
nano /etc/netdata/health.d/waha_notify.conf -
Füge folgende Definition ein:
alarm: ucc_cpu_high on: system.cpu lookup: average -1m unaligned of user + system units: % every: 1m warn: $this > 80 crit: $this > 95 exec: /usr/libexec/netdata/plugins.d/alarm-notify.sh to: webhook WEBHOOK_URL="https://n8n.deinedomain.tld/webhook/waha/statusalarm" WEBHOOK_HEADER="Content-Type: application/json" WEBHOOK_BODY="{\"host\":\"${hostname}\",\"alarm\":\"CPU high\",\"status\":\"${status}\",\"value\":\"${value}\",\"when\":\"$(date -Iseconds)\"}"Diese Regel löst aus, sobald die durchschnittliche CPU-Last eines überwachten Systems über 80 % steigt (Warnung)
oder 95 % erreicht (Kritisch).
Netdata ruft dann automatisch den im ersten Schritt erstellten n8n-Webhook auf,
der die Nachricht an WAHA weiterleitet. -
Datei speichern (STRG + O, Enter) und schließen (STRG + X).
-
Konfiguration neu laden:
systemctl restart netdata
👉 Screenshot geeignet: geöffnete waha_notify.conf mit markierten Zeilen WEBHOOK_URL und WEBHOOK_BODY
Test des zentralen Alarms
Um die Funktion zu prüfen, kann ein Test-Alarm ausgelöst werden:
sudo -u netdata /usr/libexec/netdata/plugins.d/alarm-notify.sh test webhook
Wenn die Konfiguration korrekt ist,
sollte im n8n-Log eine eingehende Anfrage erscheinen
und kurz darauf eine WhatsApp-Nachricht mit dem simulierten Alarmtext eintreffen.
👉 Screenshot geeignet: WhatsApp-Chat mit empfangener Testnachricht „⚠️ CPU high … (Test)“
Note
Diese Konfiguration gilt global für alle über Streaming verbundenen Systeme.
Netdata sendet bei jeder betroffenen Instanz den Hostnamen automatisch mit (${hostname}),
sodass du in WhatsApp genau siehst, welcher Container den Alarm ausgelöst hat.
Erweiterung auf weitere Ressourcen
Analog zur CPU-Überwachung können weitere Alarme hinzugefügt werden.
Dazu kopierst du den Block und passt lediglich den Metrikpfad (on:) und Namen (alarm:) an.
Beispiele:
RAM-Überwachung
alarm: ucc_ram_high
on: system.ram
lookup: average -1m unaligned of used
units: %
warn: $this > 80
crit: $this > 95
exec: /usr/libexec/netdata/plugins.d/alarm-notify.sh
to: webhook
WEBHOOK_URL="https://n8n.deinedomain.tld/webhook/waha/statusalarm"
WEBHOOK_HEADER="Content-Type: application/json"
WEBHOOK_BODY="{\"host\":\"${hostname}\",\"alarm\":\"RAM high\",\"status\":\"${status}\",\"value\":\"${value}\",\"when\":\"$(date -Iseconds)\"}"
Speicherplatz-Überwachung
alarm: ucc_disk_low
on: disk_space._
lookup: max -5m unaligned of used
units: %
warn: $this > 85
crit: $this > 95
exec: /usr/libexec/netdata/plugins.d/alarm-notify.sh
to: webhook
WEBHOOK_URL="https://n8n.deinedomain.tld/webhook/waha/statusalarm"
WEBHOOK_HEADER="Content-Type: application/json"
WEBHOOK_BODY="{\"host\":\"${hostname}\",\"alarm\":\"Disk usage high\",\"status\":\"${status}\",\"value\":\"${value}\",\"when\":\"$(date -Iseconds)\"}"
Tip
So entsteht eine skalierbare Struktur mit mehreren einfachen Health-Regeln,
die alle denselben Webhook nutzen.
Dadurch bleibt das System wartungsarm, aber du erhältst bei kritischen Zuständen sofort eine Nachricht auf dein Smartphone.
Premium – Elyra: Intelligente WhatsApp-Interaktion mit Opt-In-Trigger
In diesem Premium-Abschnitt erweiterst du dein bestehendes WAHA-Setup um Elyra –
eine KI-Instanz, die über WhatsApp gezielt auf Nachrichten reagiert, wenn sie vom Nutzer aktiviert wird.
Dadurch bleibt die Nutzung im Rahmen der WhatsApp-Richtlinien, da Elyra niemals selbstständig Kontakt aufnimmt.
👉 Screenshot geeignet: WhatsApp-Chat mit „Ich brauche deine Hilfe, Elyra“ als Startbefehl und automatischer Antwort
Note
Elyra ist ein optionales Modul, das lokale oder externe KI-Modelle (z. B. OpenAI, Ollama) ansprechen kann.
Die Integration setzt ein funktionierendes WAHA- und n8n-System aus dem Free-Kapitel voraus.Der Ansatz bewegt sich in einem zulässigen Graubereich,
da die Kommunikation ausschließlich user-initiiert erfolgt und somit kein unerlaubtes Messaging stattfindet.
Aktivierungslogik
Elyra reagiert nur, wenn sie bewusst aktiviert wird.
Die Aktivierung erfolgt über eine eindeutige Eingabe, die als Opt-In-Trigger dient:
Trigger-Phrase:
„Ich brauche deine Hilfe, Elyra“
Sobald diese Nachricht eingeht, aktiviert n8n den zugehörigen Workflow
und leitet den Inhalt an den KI-Knoten weiter.
Elyra verarbeitet die Anfrage, erstellt eine Antwort und sendet sie über WAHA an den Chat zurück.
Beendigungslogik
Die Sitzung endet automatisch, wenn:
- Der Nutzer „Danke, Elyra“ schreibt, oder
- 10 Minuten lang keine neue Nachricht eingeht.
Beide Bedingungen setzen den Workflow-Status zurück,
sodass Elyra keine weiteren Nachrichten beantwortet, bis erneut ein gültiger Trigger empfangen wird.
Tip
Dieses Verhalten entspricht dem Prinzip klassischer Sprachassistenten wie „Hey Siri“ oder „Alexa“
und sorgt für klare Grenzen zwischen aktiver und passiver Phase.
Beispielhafte Gesprächssequenz
👤 Nutzer: Ich brauche deine Hilfe, Elyra
🤖 Elyra: Natürlich. Wobei darf ich dir helfen?
👤 Nutzer: Wann ist der nächste Stream?
🤖 Elyra: Der nächste Stream findet am Freitag um 19:30 Uhr statt – Thema: Disney Dreams 🌟
👤 Nutzer: Danke, Elyra
🤖 Elyra: Gern geschehen. Ich bin wieder im Ruhemodus.
👉 Screenshot geeignet: WhatsApp-Chat mit Elyra, die freundlich auf eine Zuschauerfrage reagiert und danach automatisch inaktiv wird.
Node 1 – Webhook (Eingang: WhatsApp-Nachricht)
Zweck: Empfängt eingehende WhatsApp-Nachrichten, die über WAHA an diesen Workflow weitergeleitet werden.
Node-Typ: Webhook
Name: Elyra – Nachrichteneingang
Parameter:
- HTTP Method:
POST - Path:
/elyra/inbound - Response Mode:
On Received - Response Code:
200 - Response Data:
No Response Body
Note
Die Webhook-URL wird nach dem Speichern automatisch angezeigt, z. B.:
https://n8n.deinedomain.tld/webhook/elyra/inboundDiese Adresse muss im WAHA-Backend als Ziel für eingehende Nachrichten konfiguriert werden –
üblicherweise per Weiterleitung oder Trigger-Konfiguration in deinem WhatsApp-Bot-Modul.
👉 Screenshot geeignet: Webhook-Node mit sichtbarem Pfad /webhook/elyra/inbound
Node 2 – Function (Nachricht vorbereiten + Zeitstempel aktualisieren)
Zweck:
Extrahiert die chatId aus der eingehenden Nachricht, bereitet die Daten für den weiteren Verlauf auf
und speichert zusätzlich den Zeitpunkt der letzten Aktivität, um inaktive Sessions später automatisch beenden zu können.
Node-Typ: Function
Name: Elyra – Nachricht vorbereiten
Code:
const body = items[0].json || {};
const chatId = body.chatId || 'unbekannt';
const text = (body.text || '').trim().toLowerCase();
const timestamp = body.timestamp || new Date().toISOString();
// Zeitstempel der letzten Aktivität speichern
$global.set('elyra_lastmsg_' + chatId, Date.now());
// Standardisierte Ausgabe für den weiteren Workflow
return [{
json: {
chatId,
text,
timestamp
}
}];
Note
Der Eintrag
elyra_lastmsg_<chatId>ermöglicht dem separaten Cleanup-Workflow,
inaktive Sessions nach 10 Minuten automatisch zu beenden.
Jede eingehende Nachricht aktualisiert diesen Zeitstempel automatisch.
👉 Screenshot geeignet: Function-Node mit markierter Zeile $global.set('elyra_lastmsg_' + chatId, Date.now());
Node 3 – IF (Trigger: Elyra deaktivieren?)
Zweck: Erkennt, ob der Nutzer Elyra gezielt deaktivieren will – z. B. durch die Nachricht „Danke, Elyra“.
Node-Typ: IF
Name: Elyra – Deaktivierung erkennen
Bedingung:
- Mode:
All - Type:
String - Value 1:
{{$json["text"]}} - Operation:
Contains - Value 2:
danke, elyra
Tip
Du kannst weitere Formulierungen ergänzen – z. B.
tschüss elyra,ich bin fertig, etc.
Aktuell genügt ein einzelner präziser Begriff zur Deaktivierung.
👉 Screenshot geeignet: IF-Node mit Bedingung text contains "danke, elyra"
Anschlusslogik:
- TRUE → weiter mit Node 4 – Elyra – Session deaktivieren
- FALSE → weiter mit Node 5 – Elyra – Aktivierung erkennen
Node 4 – Set (Elyra-Session deaktivieren)
Zweck: Setzt den Aktivierungsstatus der Elyra-Session für diesen Chat auf „inaktiv“.
Node-Typ: Set
Name: Elyra – Session deaktivieren
Operation:
- Add Field:
elyra_active→false
Note
Die Variable
elyra_activewird später mit derchatIdkombiniert,
um eine sitzungsspezifische Statusvariable zu erzeugen, z. B.:
elyra_active_491751234567@c.us
👉 Screenshot geeignet: Set-Node mit Feld elyra_active = false
Node 5 – IF (Trigger: Elyra aktivieren?)
Zweck: Erkennt, ob Elyra durch den Nutzer aktiviert werden soll – z. B. mit „Ich brauche deine Hilfe, Elyra“.
Node-Typ: IF
Name: Elyra – Aktivierung erkennen
Bedingung:
- Mode:
All - Type:
String - Value 1:
{{$json["text"]}} - Operation:
Contains - Value 2:
ich brauche deine hilfe, elyra
Tip
Achte auf die Kleinschreibung, wenn du den Text vorher mit
.toLowerCase()vereinheitlichst (siehe Node 2).
Weitere Aktivierungsphrasen kannst du über zusätzliche OR-Verzweigungen ergänzen.
👉 Screenshot geeignet: IF-Node mit Bedingung text contains "ich brauche deine hilfe, elyra"
Anschlusslogik:
- TRUE → weiter mit Node 6 – Sessionzähler prüfen
- FALSE → weiter mit Node 9 – Elyra – Aktivstatus prüfen
Node 6 – Function (Sessionzähler prüfen)
Zweck: Zählt die aktuell aktiven Elyra-Sessions anhand der globalen Variablen
und entscheidet, ob eine weitere Session zulässig ist (Maximalgrenze: 10).
Node-Typ: Function
Name: Elyra – Sessionzähler prüfen
// Aktuelle Liste aller aktiven Sessions abrufen
const allKeys = Object.keys($global);
const activeSessions = allKeys.filter(k => k.startsWith('elyra_active_') && $global.get(k) === true);
// Ergebnis als Flag setzen
item.sessionCount = activeSessions.length;
item.sessionAllowed = activeSessions.length < 10;
return [item];
Note
Jede aktive Elyra-Session wird im weiteren Verlauf als globale Variable gespeichert, z. B.:
elyra_active_491751234567@c.us = trueDiese Function zählt exakt, wie viele davon derzeit auf
truestehen.
👉 Screenshot geeignet: Function-Node mit markierter Zeile item.sessionAllowed = ...
Anschlusslogik:
- → weiter mit Node 7 – Aktivierung zulässig? (IF)
Node 7 – IF (Aktivierung zulässig?)
Zweck: Prüft, ob die Elyra-Aktivierung für diesen Nutzer erlaubt ist (d. h. weniger als 10 aktive Sessions).
Node-Typ: IF
Name: Elyra – Aktivierung zulässig?
Bedingung:
- Mode:
All - Type:
Boolean - Value 1:
{{$json["sessionAllowed"]}} - Operation:
Is true
👉 Screenshot geeignet: IF-Node mit Bedingung sessionAllowed is true
Anschlusslogik:
- TRUE → weiter mit Node 8 – Elyra – Session aktivieren
- FALSE → weiter mit Node 9 – Elyra – Aktivstatus prüfen
Node 8 – Set (Elyra – Session aktivieren)
Zweck: Aktiviert Elyra für diesen Nutzer, indem eine globale Sitzungsvariable gesetzt wird.
Node-Typ: Set
Name: Elyra – Session aktivieren
Operation:
- Add Field:
elyra_active→true
Note
Die eigentliche Speicherung erfolgt erst im nächsten Schritt durch Kombination mit der
chatId.
Dieses Feld dient als Zwischenschritt für die globale Speicherung mit Namen wie:
elyra_active_491751234567@c.us
👉 Screenshot geeignet: Set-Node mit Feld elyra_active = true
Anschlusslogik:
- → weiter mit Node 9 – Elyra – Aktivstatus prüfen
Node 9 – IF (Elyra ist aktiv?)
Zweck: Prüft, ob für diesen Chat eine Elyra-Session aktiv ist.
Node-Typ: IF
Name: Elyra – Aktivstatus prüfen
Bedingung:
- Mode:
All - Type:
Expression - Value 1:
{{ const key = 'elyra_active_' + $json["chatId"]; return $global.get(key) === true; }} - Operation:
Is true
Tip
Diese Prüfung stellt sicher, dass Elyra nur antwortet, wenn eine Sitzung explizit aktiv ist.
Ohne vorherige Aktivierung wird der Nutzer ignoriert – oder optional weitergeleitet.
👉 Screenshot geeignet: IF-Node mit geöffneter Expression und return $global.get(...) === true
Anschlusslogik:
- TRUE → weiter mit Node 10 – Thema klassifizieren
- FALSE → weiter mit Node 16 – Antwort: Elyra ist nicht aktiv
Node 10 – HTTP Request (Themenklassifizierung über Ollama)
Zweck: Übergibt die empfangene WhatsApp-Nachricht an das lokale Mistral-Modell in Ollama,
um eine präzise Themenklassifizierung zu erhalten – z. B. streamzeit, eventinfo, zeiten, adminanfrage, chatbefehl oder nicht zulässig.
Node-Typ: HTTP Request
Name: Elyra – Thema klassifizieren (Ollama)
Parameter:
- HTTP Method:
POST - URL:
http://ollama.deinedomain.tld:11434/api/chat - Headers:
Content-Type:application/json
- Body Content Type:
JSON - Body Parameters:
{ "model": "mistral", "messages": [ { "role": "system", "content": "Du bist ein Klassifizierungsagent für WhatsApp-Nachrichten. Ordne die folgende Nachricht exakt einem der folgenden Themen zu:\n\n- streamzeit\n- eventinfo\n- zeiten\n- adminanfrage\n- chatbefehl\n\nWenn keine eindeutige Zuordnung möglich ist oder der Inhalt nicht erlaubt ist, antworte exakt mit: nicht zulässig." }, { "role": "user", "content": "={{$json[\"text\"]}}" } ], "stream": false }
Note
Die Antwort muss exakt einem der oben genannten Schlüsselwörter entsprechen.
Dadurch kannst du im nächsten Schritt zuverlässig prüfen, ob Elyra antworten darf – auch bei hoher Auslastung.
👉 Screenshot geeignet: HTTP-Request-Node mit geöffnetem Body, markierter Promptabschnitt "Ordne die folgende Nachricht ..."
Anschlusslogik:
- → weiter mit Node 11 – Zugriffsprüfung: Thema + Sessionauslastung
Node 11 – Function (Zugriffsprüfung: Thema + Sessionauslastung)
Zweck: Entscheidet, ob die Anfrage trotz möglicher Überlast bearbeitet werden darf.
Bevorzugte Themen wie streamzeit, eventinfo und zeiten dürfen auch bei Volllast durch –
alles andere wird bei Erreichen der Kapazitätsgrenze blockiert.
Node-Typ: Function
Name: Elyra – Zugriff prüfen
const thema = $json["message"]?.content?.toLowerCase() || "nicht zulässig";
const chatId = $json["chatId"];
// Speichern für spätere Entscheidung
item.thema = thema;
item.chatId = chatId;
// Bevorzugte Themen
const priorisiert = ["streamzeit", "eventinfo", "zeiten"];
// Aktive Sessions zählen
const allKeys = Object.keys($global);
const aktive = allKeys.filter(k => k.startsWith('elyra_active_') && $global.get(k) === true);
const sessionCount = aktive.length;
// Entscheidung
item.sessionCount = sessionCount;
item.zugriffErlaubt = sessionCount < 10 || priorisiert.includes(thema);
item.zugriffVerweigert = !item.zugriffErlaubt || thema === "nicht zulässig";
return [item];
Tip
Durch diese Logik reagiert Elyra auch bei starker Auslastung noch auf einfache Standardfragen.
Nur komplexe oder nicht erlaubte Inhalte werden in dem Fall geblockt oder verzögert.
👉 Screenshot geeignet: Function-Node mit sichtbarer Logik zugriffErlaubt = sessionCount < 10 || …
Anschlusslogik:
- TRUE → weiter mit Node 12 – Antwort generieren (Ollama)
- FALSE → weiter mit Node 22 – Antwort: Kapazitätsgrenze oder Thema abgelehnt
Node 12 – Set (Kontext für Themenverzweigung vorbereiten)
Zweck: Bereitet die vom Klassifizierungsmodell gelieferte Themenkategorie und alle relevanten Kontextdaten für die nachfolgende Verzweigung vor.
Dieser Node bündelt alle Variablen, die für die spätere Entscheidung im Switch-Node benötigt werden.
Node-Typ: Set
Name: Elyra – Kontext vorbereiten
Felder hinzufügen:
thema→={{$json["message"]["content"]}}chatId→={{$json["chatId"]}}text→={{$json["text"]}}timestamp→={{$json["timestamp"]}}
Note
Die Variable
themastammt direkt aus der Klassifizierungsantwort von Mistral (Node 10).
Diese wird im nächsten Node verwendet, um über einenSwitch-Node gezielt auf das Thema zu reagieren.
👉 Screenshot geeignet: Set-Node mit Feldern thema, chatId, text, timestamp
Anschlusslogik:
- → weiter mit Node 13 – Switch: Thema auswählen
Node 13 – Switch (Thema auswählen und Pfad verzweigen)
Zweck: Leitet die Verarbeitung abhängig von der klassifizierten Themenkategorie an den passenden Ablauf weiter – z. B. Datenabruf, Rechteprüfung oder feste Antwort.
Node-Typ: Switch
Name: Elyra – Thema verzweigen
Bedingungstyp: String
Vergleichswert: ={{$json["thema"]}}
Cases:
- streamzeit → weiter mit Node 14 – Twitch-Kalender abrufen
- eventinfo → weiter mit Node 15 – Eventtext setzen
- zeiten → weiter mit Node 16 – Sendezeit abrufen
- chatbefehl → weiter mit Node 17 – Standardantwort setzen
- adminanfrage → weiter mit Node 18 – Adminrechte prüfen
- nicht zulässig → weiter mit Node 19 – Antwort: Thema nicht erlaubt
Tip
Der Switch kann später beliebig erweitert werden, z. B. für
netdatainfo,feedback, etc.
Die Themenbezeichnungen müssen exakt zu denen aus dem Klassifizierungs-Prompt (Node 10) passen.
👉 Screenshot geeignet: Switch-Node mit geöffneten Case‑Bedingungen streamzeit, adminanfrage, etc.
Anschlusslogik:
- Je nach Thema → zu Node 14–19 (jeweils themenspezifisch)
Node 14 – Execute Sub‑workflow (Twitch-Kalender abfragen)
Zweck: Führt einen ausgelagerten Workflow aus, der den nächsten geplanten Streamtermin über die Twitch-API abruft
und die Antwort in strukturierter Form (z. B. als streaminfo) zurückliefert.
Node-Typ: Execute Sub-workflow
Name: Elyra – Nächsten Stream abrufen
Parameter:
- Workflow:
elyra_next_stream(wird als JSON-Download bereitgestellt) - Options → Wait for Completion:
true - Options → Variables:
chatId:={{$json["chatId"]}}text:={{$json["text"]}}timestamp:={{$json["timestamp"]}}
Note
Dieser Sub‑Workflow wird nicht im Tutorial dokumentiert, sondern separat als JSON-Datei bereitgestellt.
Er ruft die Twitch-API auf, extrahiert den nächsten geplanten Stream
und speichert die Information im Feldstreaminfofür die spätere Antwortgenerierung.
👉 Screenshot geeignet: Execute Sub-workflow Node mit gewähltem Workflow elyra_next_stream und aktiver Option Wait for Completion
Anschlusslogik:
- → weiter mit Node 20 – Antwort generieren (Ollama mit Kontext)
Node 15 – Execute Sub‑workflow (Event-Info abrufen)
Zweck: Führt einen externen Workflow aus, der die Beschreibung des nächsten geplanten Events liefert –
z. B. aus einer Kalenderquelle, Textdatei oder Datenbank.
Node-Typ: Execute Sub-workflow
Name: Elyra – Eventinfo abrufen
Parameter:
- Workflow:
elyra_eventinfo(bereitgestellt als JSON-Download) - Options → Wait for Completion:
true - Options → Variables:
chatId:={{$json["chatId"]}}text:={{$json["text"]}}timestamp:={{$json["timestamp"]}}
Note
Auch dieser Workflow wird nicht im Tutorial beschrieben, sondern als JSON-Datei zum Download bereitgestellt.
Er liefert z. B. das Feldeventinfozurück, das später in den Antwort-Prompt eingebaut werden kann.
👉 Screenshot geeignet: Execute Sub-workflow mit Workflow-Namen elyra_eventinfo und gesetzten Parametern
Anschlusslogik:
- → weiter mit Node 20 – Antwort generieren (Ollama mit Kontext)
Node 16 – Execute Sub‑workflow (Sendezeit abrufen)
Zweck: Führt einen ausgelagerten Workflow aus, der die aktuelle oder nächste Sendezeit ermittelt –
z. B. über eine ICS-Datei, einen festgelegten Wochenplan oder eine API-basierte Quelle.
Node-Typ: Execute Sub-workflow
Name: Elyra – Sendezeit abrufen
Parameter:
- Workflow:
elyra_zeiten(bereitgestellt als JSON-Download) - Options → Wait for Completion:
true - Options → Variables:
chatId:={{$json["chatId"]}}text:={{$json["text"]}}timestamp:={{$json["timestamp"]}}
Note
Der Workflow
elyra_zeitenwird separat als JSON bereitgestellt
und extrahiert z. B. aus einem Kalender die geplante Startzeit des Streams.
Die Ausgabe erfolgt idealerweise als String im Feldsendezeit.
👉 Screenshot geeignet: Execute Sub-workflow mit Workflow elyra_zeiten und gesetzten Übergabeparametern
Anschlusslogik:
- → weiter mit Node 20 – Antwort generieren (Ollama mit Kontext)
Node 17 – Execute Sub‑workflow (Chatbefehle aus StreamElements abrufen)
Zweck: Führt einen ausgelagerten Workflow aus, der die öffentlich zugängliche StreamElements‑Commands‑Seite abruft,
alle verfügbaren Chatbefehle extrahiert und als JSON-String bereitstellt.
Node-Typ: Execute Sub-workflow
Name: Elyra – Chatbefehle laden
Parameter:
- Workflow:
elyra_chatcommands(bereitgestellt als JSON-Download) - Options → Wait for Completion:
true - Options → Variables:
chatId:={{$json["chatId"]}}text:={{$json["text"]}}
Note
Dieser Sub‑Workflow ruft z. B.
https://streamelements.com/bratonien_tv/commandsauf,
analysiert das HTML und extrahiert die Befehle samt Beschreibung als JSON‑Objekt.
Das Ergebnis wird später an Ollama übergeben, damit Elyra kontextbezogen passende Befehle vorschlagen kann.Auch andere Anbieter wie Nightbot, Moobot oder Botisimo stellen vergleichbare Listen zur Verfügung –
im Rahmen dieses Tutorials verwenden wir jedoch ausschließlich StreamElements als zentrale Bot-Instanz.
👉 Screenshot geeignet: Execute Sub-workflow mit Workflow-Namen elyra_chatcommands
Anschlusslogik:
- → weiter mit Node 20 – Antwort generieren (Ollama mit Kontext)
Node 18 – Execute Sub‑workflow (Adminrechte prüfen)
Zweck: Führt einen externen Workflow aus, der prüft, ob der aktuelle Absender (chatId) zu den autorisierten Admins gehört.
Nur wenn das zutrifft, wird die Anfrage weiterverarbeitet – sonst erhält der Nutzer eine entsprechende Ablehnung.
Node-Typ: Execute Sub-workflow
Name: Elyra – Adminrechte prüfen
Parameter:
- Workflow:
elyra_admincheck(bereitgestellt als JSON-Download) - Options → Wait for Completion:
true - Options → Variables:
chatId:={{$json["chatId"]}}text:={{$json["text"]}}
Note
Der Sub-Workflow
elyra_admincheckvergleicht diechatIdmit einer internen Liste autorisierter Nutzer
(z. B. als JSON-Datei, Umgebungsvariable oder Datenbankeintrag).
Ist der Nutzer nicht autorisiert, wird das Feldadmin_erlaubtauffalsegesetzt und die Anfrage verworfen.
👉 Screenshot geeignet: Execute Sub-workflow mit Workflow elyra_admincheck und Variable chatId
Anschlusslogik:
- → weiter mit Node 20 – Antwort generieren (Ollama mit Kontext)
Node 19 – Set (Ablehnungsprompt für nicht erlaubtes Thema)
Zweck: Bereitet den Prompt für eine freundlich-bestimmte Ablehnungsantwort durch Ollama vor.
Dies erfolgt, wenn das Thema vom Klassifizierungsmodell als nicht zulässig eingestuft wurde.
Node-Typ: Set
Name: Elyra – Thema abgelehnt (Prompt vorbereiten)
Felder hinzufügen:
chatId:={{$json["chatId"]}}text:={{$json["text"]}}ablehnungskontext:Die folgende Anfrage konnte keinem zugelassenen Thema zugeordnet werden. Formuliere eine kurze, aber klare Antwort, die dem Nutzer freundlich mitteilt, dass diese Art von Anfrage aktuell nicht unterstützt wird. Die Antwort soll sachlich bleiben, aber höflich und professionell wirken.
👉 Screenshot geeignet: Set-Node mit sichtbarem Feld ablehnungskontext
Anschlusslogik:
- → weiter mit Node 20 – Antwort generieren (Ollama mit Kontext)
Node 20 – HTTP Request (Antwort generieren – Ollama)
Zweck: Sendet die Nutzeranfrage zusammen mit dem relevanten Kontext (z. B. Chatbefehle, Eventinfos, Ablehnungshinweis)
an das lokale Sprachmodell Mistral über den Ollama-Endpunkt und erhält eine formulierte Antwort zurück.
Node-Typ: HTTP Request
Name: Elyra – Antwort generieren (Ollama)
Parameter:
- Method:
POST - URL:
http://ollama.<deine-domain>.tld/api/generate - Headers:
Content-Type:application/json
- Body → JSON:
{ "model": "mistral", "stream": false, "prompt": "{{$json['ablehnungskontext'] || ''}}{{$json['kontext'] || ''}}\n\nNachricht:\n{{$json['text']}}" }
Note
Der Prompt setzt sich aus verschiedenen Quellen zusammen – je nach Pfad:
– beichatbefehl: Liste aller Chatkommandos (kontext)
– beieventinfoodersendezeit: Zusatzinfos aus Sub-Workflows
– beinicht erlaubt: Ablehnungshinweis (ablehnungskontext)Der finale Prompt enthält immer den Originaltext des Nutzers.
Tip
Du kannst über die
prompt:-Zusammensetzung bei Bedarf eigene Regeln einbauen,
z. B. Priorisierungen, stilistische Hinweise oder Sprachwechsel.
👉 Screenshot geeignet: HTTP-Request-Node mit Body-Feld prompt
Anschlusslogik:
- → weiter mit Node 21 – Antwort an WAHA senden
Node 21 – HTTP Request (Antwort über WAHA senden)
Zweck: Sendet die generierte Antwort als WhatsApp-Nachricht über die WAHA‑API an den ursprünglichen Absender.
Node-Typ: HTTP Request
Name: Elyra – Antwort senden (WAHA)
Parameter:
- Method:
POST - URL:
https://waha.<deine-domain>.tld/api/sendText - Headers:
Content-Type:application/jsonAuthorization:Bearer <DEIN_WAHA_API_TOKEN>
- Body → JSON:
{ "chatId": "={{$json[\"chatId\"]}}", "text": "={{$json[\"antwort\"] || $json[\"text\"]}}" }
Important
Der API-Token ist zwingend erforderlich, damit WAHA die Anfrage akzeptiert.
Du findest ihn im WAHA-Webinterface unter Settings → API → Token.
Ohne gültigen Token gibt die API den Fehlercode401 Unauthorizedzurück.
👉 Screenshot geeignet: HTTP-Request-Node mit gesetztem Authorization‑Header
Anschlusslogik:
→ Ende des Haupt-Workflows
Node 22 – Set (Ablehnungsprompt: Ressourcenmangel)
Zweck:
Bereitet den Prompt für eine höfliche, aber bestimmte Ablehnungsantwort durch Ollama vor,
wenn das System aktuell keine ausreichenden Ressourcen (z. B. Rechenkapazität oder Slots) zur Bearbeitung hat.
Node-Typ:
Set
Name:
Elyra – Thema abgelehnt (Ressourcenmangel)
Felder hinzufügen:
chatId:
={{$json["chatId"]}}text:
={{$json["text"]}}ablehnungskontext:Die Anfrage kann derzeit nicht bearbeitet werden, da die verfügbaren Ressourcen (z. B. Rechenkapazität oder Ausführungsslots) vorübergehend ausgelastet sind. Formuliere eine höfliche, aber klare Antwort, die den Nutzer darüber informiert, dass Elyra aktuell keine weiteren Anfragen annehmen kann. Bitte den Nutzer freundlich um Verständnis und erkläre, dass er es zu einem späteren Zeitpunkt erneut versuchen kann.
👉 Screenshot geeignet:
Set-Node mit sichtbarem Feld ablehnungskontext
Anschlusslogik:
→ weiter mit Node 20 – Antwort generieren (Ollama mit Kontext)
Workflow: Elyra – Session Cleanup (automatische Sitzungsbeendigung)
Zweck:
Beendet inaktive Elyra-Sessions automatisch, wenn über 10 Minuten keine Nachricht mehr eingegangen ist.
Dadurch werden belegte Slots im UCC wieder freigegeben und die Systemkapazität bleibt stabil.
Der Workflow wird alle 5 Minuten automatisch gestartet.
Er durchsucht den n8n-Global-Store nach aktiven Sessions (elyra_active_<chatId>)
und prüft anhand des zugehörigen Zeitstempels (elyra_lastmsg_<chatId>),
ob die letzte Nutzerinteraktion länger als 10 Minuten her ist.
Falls ja, wird die Session beendet.
👉 Screenshot geeignet: Diagramm mit Cron-Trigger → Function-Node „Inaktive Sessions schließen“
Node 1 – Cron (Trigger)
Zweck:
Startet den Workflow regelmäßig, um alte Sessions zu bereinigen.
Node-Typ: Cron
Name: Elyra – Cleanup Trigger
Parameter:
- Mode: Every X Minutes
- Every:
5
Note
Der Workflow läuft alle 5 Minuten automatisch.
Du kannst das Intervall bei Bedarf anpassen – z. B. auf 2 Minuten für sehr aktive Systeme.
👉 Screenshot geeignet: Cron-Node mit „Every 5 Minutes“
Anschlusslogik:
→ weiter mit Node 2 – Inaktive Sessions schließen
Node 2 – Function (Inaktive Sessions schließen)
Zweck:
Überprüft alle global gespeicherten Elyra-Sessions und deaktiviert diejenigen,
bei denen seit mehr als 10 Minuten keine Aktivität registriert wurde.
Node-Typ: Function
Name: Elyra – Inaktive Sessions schließen
Code:
const allKeys = Object.keys($global);
const now = Date.now();
const timeout = 10 * 60 * 1000; // 10 Minuten
for (const key of allKeys) {
if (key.startsWith('elyra_active_') && $global.get(key) === true) {
const chatId = key.replace('elyra_active_', '');
const lastMsg = $global.get('elyra_lastmsg_' + chatId) || 0;
if (now - lastMsg > timeout) {
$global.set(key, false);
}
}
}
return [];
Tip
Die Timeout-Dauer (
timeout) lässt sich frei anpassen.
Standardwert sind 10 Minuten (600 000 ms).
Für Livestream- oder Event-Kontexte sind 5–10 Minuten in der Regel sinnvoll.
👉 Screenshot geeignet: Function-Node mit geöffnetem Code-Editor, markierte Zeile if (now - lastMsg > timeout)
Anschlusslogik:
→ Ende des Workflows
Abschluss – WAHA Premium
Mit dem Abschluss dieses Premium-Kapitels hast du WAHA vollständig in dein UCC integriert.
Automatisierte Statusmeldungen via n8n und Netdata sowie eine optionale KI-gestützte Antwortfunktion machen dein System nicht nur informativ, sondern auch interaktiv.
Ergebnisse dieses Kapitels
| Bereich | Umsetzung |
|---|---|
| Statusbenachrichtigung | Netdata-Alarme werden über n8n an WAHA weitergeleitet – du bekommst Warnungen & Fehler direkt auf WhatsApp. |
| KI-Antwortfunktion | Eingehende Nachrichten aktivieren auf Wunsch deine KI-Instanz („Elyra“) und erhalten automatisierte Antworten – lokal und datensouverän. |
| Infrastruktur-Integration | Alles läuft innerhalb deines UCC-Systems: keine externe Cloud-API (sofern gewünscht), volle Kontrolle über Daten und Prozesse. |
Tip:
Dieses Setup lässt sich modular erweitern – z. B. um zusätzliche Trigger, weitere Chat-Kanäle oder erweiterte KI-Funktionalitäten.
Dank klarer Trennung und Standardisierung bleibt dein System wartungsarm und skalierbar.
Damit ist dieses Kapitel abgeschlossen.
Dein UCC verfügt nun über ein vollwertiges, internes WhatsApp-Kommunikations- und Benachrichtigungssystem – von den ersten Setup-Schritten bis zur automatisierten Interaktion.
Viel Erfolg beim Betrieb und bei weiteren Erweiterungen!