elton d677ef4b3e Anwesenheit anzeigen, und der Boden traegt mit 15 Sekunden
Andreas: "waehrend mmnotify per ws angemeldet ist, kann es dann den
status des agenten auf online setzen?" Ja -- und hive hatte das Muster
schon fertig (channels/team.py): abwesend beim Verbinden, gruen waehrend
der Arbeit, wieder abwesend nach Ruhe, offline beim Beenden. Ein Agent
ohne Status sieht aus, als sei niemand da; einer, der rund um die Uhr
gruen leuchtet, sagt genauso wenig.

Beim Testen fiel ein eigener Fehler auf: Der Boden setzte den Agenten auf
gruen. Routinemaessiges Nachsehen ist aber keine Anwesenheit -- bei Boden
alle 20 s und Frist 25 s blieb er dauerhaft gruen. Jetzt macht nur ein
echtes Ereignis gruen.

Und zur Verzoegerung, die Andreas zu Recht nicht hinnehmen wollte: Statt
weiter zu raten, gemessen. Der eigene Beitrag loest sehr wohl ein posted
aus, ein fremder nie -- die Verbindung hat also die Kanal-Abos, es fehlen
nur fremde Ereignisse. Ausgeschlossen: authentication_challenge, Token im
Authorization-Header, ein echter Bot-Account statt Nutzer-Token, und das
Sitzungs-Cookie wie im Browser. Alle vier gleich. Das Mattermost-Forum
beschreibt dasselbe, dort auch mit System-Admin-Token, ohne Loesung.

Konsequenz: floor_seconds ist der Weg, nicht der Notnagel, und steht
deshalb auf 15 s statt 60. Ein Durchgang kostet einen API-Aufruf -- billig
genug, um es oft zu tun.
2026-09-01 20:50:24 +02:00

mmnotify

Hört am Mattermost-Websocket und weckt einen Agenten, wenn er gemeint ist.

Gegenstück zu goimapnotify für Mail: ein kleiner Prozess, der lauscht und bei einem Ereignis einen Befehl ausführt. Der Agent liest und antwortet danach mit seinen eigenen Werkzeugen — mmnotify schreibt nie in einen Kanal, es klopft nur an.

mmnotify -conf /etc/mmnotify.json

Konfiguration

{
  "url": "https://team.42i.org",
  "token": "<persönliches Zugriffstoken des Agenten>",
  "on_mention": "/root/run-agent.sh team",
  "on_direct": "",
  "debounce_seconds": 5,
  "floor_seconds": 60,
  "ignore_users": []
}

Die Datei enthält ein Token und gehört mit 0600 dem Dienstbenutzer.

Feld Bedeutung
on_mention Befehl bei Erwähnung (@name) im Kanal
on_direct Befehl bei Direktnachricht; leer = on_mention
debounce_seconds Mindestabstand zwischen zwei Läufen (Standard 5)
floor_seconds Nachsehen auch ohne Ereignis (Standard 15, 0 schaltet ab)
ignore_users Absender, die nie wecken
away_after_seconds Wann der grüne Punkt auf abwesend zurückfällt (Standard 120)

Der Befehl bekommt die Ereignisdaten über die Umgebung: MM_TRIGGER (event oder floor), MM_CHANNEL, MM_CHANNEL_NAME, MM_CHANNEL_TYPE, MM_SENDER, MM_POST_ID, MM_ROOT_ID, MM_MESSAGE.

Zwei Wege, und der Boden ist der tragende

Der Websocket ist der Beschleuniger; darunter läuft ein Boden, der ohnehin nachsieht. Die Aufteilung stammt aus hive (hive_runtime/channels/team.py) und ist dort begründet: „A stream that dies quietly must make us LATE, never blind."

Hier ist der Boden nicht nur Vorsicht. Gemessen am 2026-09-01 gegen Mattermost 11.7.10:

eigener Beitrag posted kommt an
Beitrag eines anderen Kontos kommt nie an

Die Verbindung ist also voll funktionsfähig und hat die Kanal-Abos — es fehlen ausschließlich die Ereignisse fremder Konten. Ausgeschlossen wurden: authentication_challenge, Token im Authorization-Header beim Handshake, ein echter Bot-Account statt eines Nutzers mit Token, und das Sitzungs-Cookie MMAUTHTOKEN wie im Browser. Alle vier verhalten sich gleich.

Das Verhalten ist im Mattermost-Forum beschrieben und tritt dort auch mit einem System-Admin-Token auf; eine Lösung steht nicht dabei.

Deshalb ist floor_seconds der Weg und nicht der Notnagel, und der Standard ist kurz: 15 Sekunden. Ein Durchgang kostet einen API-Aufruf — billig genug, um es oft zu tun. Wer den Stream repariert bekommt, kann ihn hochsetzen.

Daraus folgt die zweite Entscheidung: mmnotify liest den Beitrag nicht aus dem Ereignis. Es klopft an; was zu tun ist, entscheidet der Agent, wenn er nachsieht. Zwei Leser wären zwei Antworten.

Anwesenheit

Solange mmnotify verbunden ist, zeigt der Punkt neben dem Namen, woran man ist:

  • abwesend, sobald die Verbindung steht — da, aber untätig
  • grün, während der Befehl wegen einer Erwähnung läuft
  • abwesend wieder, wenn es away_after_seconds still war
  • offline beim Beenden, statt einen grünen Punkt zurückzulassen, hinter dem niemand mehr sitzt

Das routinemäßige Nachsehen des Bodens macht ausdrücklich nicht grün. Läuft der Boden häufiger als die Away-Frist, leuchtete der Agent sonst rund um die Uhr — und ein Punkt, der immer grün ist, sagt genauso wenig wie gar keiner. (Beim Testen genau so passiert: Boden alle 20 s, Frist 25 s, nie abwesend.)

Ein Status ist eine Höflichkeit gegenüber dem, der in die Seitenleiste schaut. Weigert sich der Server, wird das protokolliert und weitergearbeitet: Ein Agent, der aufhört zu antworten, weil er einen Punkt nicht einfärben konnte, wäre absurd.

Robustheit

  • Wiederaufbau mit wachsendem Abstand (1 s bis 60 s). Ein Server, der neu startet, wird nicht von einem Client bestürmt, der im Sekundentakt anklopft.
  • Herzschlag alle 30 s, Lesefrist 90 s. Eine halboffene Verbindung liest sich sonst für immer wie Stille.
  • Höchstens ein Lauf gleichzeitig; wer währenddessen schreibt, wird vom laufenden Durchgang mitgenommen. Ohne das lösen fünf Beiträge in einer Minute fünf Agentenläufe aus, die sich gegenseitig überholen.
  • Eigene Beiträge und system_*-Ereignisse wecken nie — sonst antwortet ein Agent auf sich selbst.
  • SIGTERM beendet sofort und sauber.

Bauen

go build -o mmnotify .

Ein statisches Binary ohne Laufzeitabhängigkeiten — gedacht zum Einbacken in das Agenten-Image, neben goimapnotify.

S
Description
Hoert am Mattermost-Websocket und weckt einen Agenten, wenn er gemeint ist — Gegenstueck zu goimapnotify fuer Mail
Readme
67 KiB
Languages
Go 100%