27 KiB
Rocket.Chat und Nextcloud — Konzept
Zwei neue Tools, ein gemeinsamer Zweck: Rocket.Chat wird der Ort, an dem wir mit den Agenten reden; Nextcloud wird der Ort, an dem die Agenten uns Ergebnisse hinlegen. Der typische Ablauf ist die Kombination aus beidem — „schreib mir die Auswertung und leg sie in die Cloud" im Chat, Datei in Nextcloud, Link zurück in den Chat.
Dieses Dokument prüft die Machbarkeit, legt den Schnitt fest und benennt die Punkte, die vor der Umsetzung entschieden werden müssen. Es ist noch keine Umsetzungsfreigabe.
Verwandt: Taskboard-Konzept (Scanner/Wake), Staging-Konzept (Freigaben), Audit-Konzept, Roadmap (A5 — siehe Konflikt unten).
0 — Kurzfassung des Befunds
| Frage | Antwort |
|---|---|
| Ist es umsetzbar? | Ja, beides. Ohne neue Architektur — die vorhandenen Bausteine tragen. |
| Braucht es Änderungen am Core? | Für Phase 1: nein, nur zwei neue Tool-Projekte + Staging-Defaults. Für den automatischen Rückweg (Antwort landet ohne Zutun des Modells im Raum) und den Notfallkanal: ja, zwei kleine Core-Ergänzungen. |
| Größtes technisches Risiko | Nicht die API — sondern Antwort-Schleifen zwischen Agenten und Kosten durch zu häufiges Wecken. |
| Größte Konzeptkollision | Roadmap A5 sieht Matrix/Element für genau diesen Zweck vor. Rocket.Chat ersetzt A5, oder wir haben zwei Chat-Wege. Muss entschieden werden. |
| „Agent erstellt Dokument direkt über die Nextcloud-API" | So nicht. Nextcloud hat keine API, die Inhalte erzeugt. Der Weg ist: Datei lokal im Workspace erzeugen → hochladen. Für PDF/XLSX kann Collabora als Konverter dienen — das ist der elegante Teil, siehe 5.4. |
1 — Was schon da ist (und deshalb nicht neu gebaut wird)
Der Rückkanal von außen nach innen existiert vollständig:
TaskScanner (60-s-Takt)
└─ Task vom Typ tool_job
└─ EngineTaskDispatcher.DispatchToolJobAsync
└─ IToolJobProvider.ExecuteJobAsync ← kein LLM, kostenlos
└─ ToolJobResult.Wake(text) ← nur wenn wirklich etwas da ist
└─ AgentEngine.ChatAsync ← hier erst kostet es Tokens
Das Telegram-Tool nutzt genau das (telegram_poll). Rocket.Chat bekommt dieselbe
Bauform — rocketchat_poll. Damit gilt automatisch:
- Zustand (letzter gesehener Zeitpunkt) über
IStateStore, überlebt Neustarts. - Ein Takt ohne neue Nachricht kostet nichts.
- Kein eigener Thread, kein eigener Scheduler, keine Sonderbehandlung beim Start.
- Jeder Tool-Aufruf läuft ohnehin durch
StagingGate(A2) und Audit (A3).
Ebenso vorhanden und wiederverwendbar:
- Pro-Agent-Konfiguration (
AgentConfig.Tools["RocketChat"]) — jeder Agent bekommt seine eigenen Zugangsdaten, ohne dass ein Agent die eines anderen sehen kann. ConfigSecretsverschlüsselt Felder nach Namen (token,password,apikey…) — ein Feld namensauthTokenbzw.appPasswordist automatisch geschützt.- Workspace-Prefixe
personal:/shared:samt Path-Traversal-Prüfung — aus dem FTP-Tool wortgleich übernehmbar für Nextcloud-Uploads.
2 — Rocket.Chat: Machbarkeit
Geprüft gegen die REST- und Realtime-API von Rocket.Chat. Alles Folgende ist Standardfunktion einer selbstgehosteten Instanz, kein Enterprise-Feature.
2.1 Identität — ein echter Benutzer je Agent
Die Anforderung „jeder Agent mit eigenem Benutzer, in Gruppen und im Direktkontakt" ist der richtige Ansatz und wird von Rocket.Chat direkt unterstützt.
- Admin legt je Agent einen Benutzer an:
POST /api/v1/users.create({ name, username, email, password, roles: ["bot"] }). - Die Rolle
botist wichtig: Sie markiert den Benutzer als Maschine (relevant für Schleifenschutz, siehe 2.5) und wird in neueren Versionen bei der Sitzplatzzählung nicht als normaler Nutzer gewertet. Gegen die eigene Version zu prüfen. - Für jeden Agenten wird ein Personal Access Token erzeugt
(
POST /api/v1/users.generatePersonalAccessToken, oder im Konto des Benutzers). Dauerhaft gültig, einzeln widerrufbar — deutlich besser als Login mit Passwort, weil kein Session-Ablauf und keine gespeicherten Passwörter im Spiel sind. - Authentifiziert wird jeder Aufruf über zwei Header:
X-Auth-TokenundX-User-Id.
Entscheidung, die ich empfehle: Das Anlegen der Benutzer ist kein Agenten-Tool. Es ist eine einmalige Einrichtungsfunktion in der WinForms-Oberfläche (Instanz-Einstellungen → Rocket.Chat → „Agenten-Benutzer anlegen"). Sonst müsste ein Agent ein Admin-Token halten — und ein Admin-Token in Reichweite einer Prompt-Injection ist genau das, was A2 verhindern soll. Der Admin-Token liegt in der Instanz-Konfiguration, nicht in einer Agenten-Tool-Konfiguration.
2.2 Ausgang — Nachrichten senden
| Zweck | Endpunkt |
|---|---|
| In Kanal/Gruppe/DM schreiben | POST /api/v1/chat.postMessage (roomId oder channel) |
| Auf eine Nachricht antworten (Thread) | dasselbe, mit tmid |
| Datei anhängen | POST /api/v1/rooms.upload/{roomId} (multipart) |
| Reaktion setzen | POST /api/v1/chat.react |
Gesendet wird als der Agenten-Benutzer — Direktnachrichten funktionieren dadurch echt und nicht als „Bot mit Alias".
2.3 Eingang — der Poll-Weg (Phase 1)
Der sparsame Weg, ohne jede neue Infrastruktur:
GET /api/v1/subscriptions.get?updatedSince=<zeitstempel>— ein einziger Aufruf liefert für diesen Agenten alle Räume mit Ungelesen-Zähler, Erwähnungs-Zähler und „zuletzt gesehen"-Marke. Auch bei 50 Räumen bleibt es ein Aufruf.- Nur für Räume mit relevanten Neuigkeiten wird die Historie geholt:
channels.history(öffentlich) /groups.history(privat) /im.history(DM), jeweils mitoldest=<letzte gesehene Zeit>. POST /api/v1/subscriptions.readmarkiert gelesen — der Zähler geht zurück auf null.
Zustand im IStateStore: rocketchat:{agentId}:lastCheck sowie je Raum die zuletzt
verarbeitete Nachrichtenzeit.
Rate-Limits: Rocket.Chat begrenzt REST-Aufrufe (Standard in der Größenordnung von
10 Aufrufen je Minute und Endpunkt). Bei einem Takt von 30–60 Sekunden und einem
Sammelaufruf pro Takt ist das unkritisch — es ist aber der Grund, warum der Entwurf über
subscriptions.get sammelt statt jeden Raum einzeln zu pollen.
Latenz: Bei 60-Sekunden-Takt antwortet ein Agent im Mittel nach ~30 s plus Laufzeit.
Für Gespräche mit Agenten ist das spürbar, aber tragbar. Der Takt lässt sich pro Job
setzen (*/1 * * * * ist das Minimum des Cron-Modells; feiner ginge nur über die
Realtime-API).
2.4 Eingang — die Realtime-Variante (Phase 3, optional)
Rocket.Chat bietet eine WebSocket-/DDP-Schnittstelle (wss://host/websocket): nach
login mit dem Token abonniert man stream-notify-user/{userId}/notification und
bekommt DMs und Erwähnungen sofort gepusht, ohne Polling.
Das ist die richtige Endstufe (Antwortzeit ~1 s statt ~30 s), aber es ist eine dauerhafte Verbindung je Agent mit Wiederverbindungs-Logik — also eine echte Komponente, keine Ergänzung eines Tools. Vorschlag: erst nachrüsten, wenn Phase 1 im Alltag steht und sich die Verzögerung tatsächlich stört.
Eine dritte Möglichkeit — Rocket.Chats Outgoing Webhook auf unsere vorhandene
ClawdDotNetApi (Port 5082) — wäre die einfachste Push-Lösung, setzt aber voraus, dass
der Rocket.Chat-Server den Windows-Rechner über das Netz erreicht. Das ist eine Frage
deiner Netztopologie und keine der Software. Falls erreichbar: der kürzeste Weg zu
niedriger Latenz.
2.5 Die zwei echten Fallen
Diese beiden Punkte sind wichtiger als jede API-Frage.
(a) Mehrere Agenten im selben Raum. Wenn drei Agenten denselben Gruppenchat pollen, antworten drei Agenten auf jede Nachricht. Regel im Entwurf:
Ein Agent wird nur geweckt bei (1) Direktnachrichten an ihn oder (2) Nachrichten, die ihn per
@nameerwähnen. Alles andere liest er nicht einmal.
Ein Raum kann per Konfiguration auf respondToAll: true gestellt werden — das ist die
bewusste Ausnahme für einen Raum mit genau einem Agenten.
(b) Agenten-Schleifen. Agent A schreibt, Agent B wird geweckt, antwortet, weckt A —
und das läuft, bis das Tagesbudget greift. Der LoopGuard schützt nur innerhalb eines
Laufs, nicht über Agenten hinweg. Regel im Entwurf:
Nachrichten von Benutzern mit der Rolle
botwerden ignoriert, außer der Agent ist namentlich erwähnt. Zusätzlich eine Drossel: höchstens N Weckvorgänge je Raum und Stunde (Zähler imIStateStore), danach schweigt der Agent in diesem Raum bis zur nächsten Stunde und protokolliert das.
Das Tagesbudget (K5) ist das letzte Netz, nicht das erste.
2.6 Der Rückweg der Antwort
Der Wake-Mechanismus liefert die Nachricht in den Agenten. Seine Antwort geht heute in den Chat-Verlauf, nicht zurück nach Rocket.Chat. Zwei Wege:
- (a) Der Agent antwortet selbst — die Weck-Nachricht enthält die
roomIdund die Anweisung, mitRocketChat.send_messagezu antworten. Kein Core-Eingriff, funktioniert sofort. Schwäche: Es hängt daran, dass das Modell es tut. Erfahrungsgemäß klappt das gut, aber nicht in 100 % der Fälle. - (b) Automatischer Rückweg — der Tool-Job merkt sich „Antwort gehört nach Raum X",
und der Dispatcher schickt die Abschlussnachricht des Laufs dorthin. Zuverlässig, aber
es braucht einen kleinen Haken in
ToolJobResult/EngineTaskDispatcher(etwa einReplyTo-Feld, das der Dispatcher nach dem Lauf an dasselbe Tool zurückgibt).
Empfehlung: (a) in Phase 1, (b) in Phase 2 nachziehen — denn (b) ist der Unterschied zwischen „meistens antwortet er" und „er antwortet". Für die Hauptkommunikationsschiene ist das am Ende nicht optional.
2.7 Sicherheit
- Nachrichten aus Rocket.Chat sind fremder Text. Sie müssen als
<untrusted_content>gerahmt in den Kontext (Roadmap K2-Rest). Bei Telegram fehlt das bis heute; hier sollte es von Anfang an drin sein, weil Gruppenchats mehrere Absender haben. - Raum-Allowlist je Agent (
allowedRooms), analogallowedChatIdsbeim Telegram-Tool. - Staging-Vorschlag (siehe 6): Senden in erlaubte Räume
auto, alles darüber hinausapprove. - Zugangsdaten heißen im Konfigurationsfeld
authToken→ConfigSecretsverschlüsselt sie automatisch. Der Admin-Token der Instanz muss inConfigSecrets.Apply(InstanceConfig)ergänzt werden. - TLS ist Pflicht; selbstsignierte Zertifikate ausdrücklich konfigurieren müssen statt Validierung generell abschalten.
2.8 Tool-Zuschnitt
Tool: RocketChat
Aktionen: send_message | reply | send_file | list_rooms | read_room
| mark_read | search
Job: rocketchat_poll
Konfiguration je Agent:
"RocketChat": {
"baseUrl": "https://chat.example.org",
"userId": "aBcD…",
"authToken": "…", // von ConfigSecrets geschützt
"allowedRooms": ["GENERAL", "finanz-team"],
"defaultRoom": "finanz-team",
"mentionOnly": true,
"maxWakesPerRoomPerHour": 12
}
3 — Redundanz: was passiert, wenn Rocket.Chat ausfällt
Das ist die Anforderung, die die Architektur bestimmt — nicht der Chat selbst. Der Kern: Rocket.Chat darf ein Kanal sein, nicht der Kanal.
3.1 Was heute schon unabhängig funktioniert
| Kanal | Unabhängig von Rocket.Chat? | Richtung |
|---|---|---|
WinForms-Chat (frm_chat) |
vollständig — läuft in der App selbst | beide |
| Telegram-Bot-Tool | ja — fremde Infrastruktur | beide |
| Mail-Tool | ja, sofern der Mailserver anderswo läuft | beide |
Web-Chat / ClawdDotNetApi |
ja, aber nur im lokalen Netz | beide |
Wir sind also nicht bei null. Was fehlt, ist die Umschaltung — heute muss ein Mensch merken, dass nichts mehr ankommt.
3.2 Vorschlag: ChannelRouter im Core
Eine kleine Komponente im Core (kein neues Tool, keine Tool-zu-Tool-Abhängigkeit —
sie löst Tools über die vorhandene ToolRegistry nach Namen auf, wie es der Dispatcher
schon tut):
- Je Agent eine geordnete Kanalliste, z. B.
["RocketChat", "Telegram", "Mail"]. - Eine Methode „stelle dem Menschen diese Nachricht zu": versucht der Reihe nach, bis einer erfolgreich ist, und protokolliert im Audit-Log, über welchen Kanal zugestellt wurde — inklusive des Hinweises „Primärkanal war nicht erreichbar".
- Genutzt von: Agenten (
notify_user), aber vor allem von systemseitigen Meldungen, die heute keinen Weg nach außen haben: Staging-Vorschlag wartet auf Freigabe, Budget überschritten, Watchdog-Alarm, Task blockiert.
Der zweite Teil ist der wichtigere: Gerade wenn etwas kaputt ist, ist die Meldung darüber diejenige, die ankommen muss.
3.3 Gesundheitsprüfung und Eskalation
Ein Tool-Job rocketchat_health (Takt ~5 Minuten, GET /api/info):
- Nach drei aufeinanderfolgenden Fehlschlägen: einmalige Meldung über den nächsten Kanal der Liste — „Rocket.Chat ist seit HH:MM nicht erreichbar, ich melde mich hier." Einmalig, nicht je Takt.
- Bei Rückkehr: „Rocket.Chat ist wieder da", und der Zustand wird zurückgesetzt.
- Nachrichten, die während des Ausfalls nicht gesendet werden konnten, werden nicht in einer eigenen Warteschlange gehalten — sie gehen über den Ersatzkanal raus. Eine zweite Zustellwarteschlange wäre eine zweite Fehlerquelle.
Eingehend während des Ausfalls: Der Telegram-Poll-Job bleibt dauerhaft aktiv, nur mit langsamem Takt (z. B. alle 5 Minuten). Er kostet nichts, wenn nichts kommt — und ist im Ernstfall der Weg, auf dem du die Agenten erreichst. Der WinForms-Chat ist ohnehin immer da, solange die App läuft.
Entschieden (August 2026): Telegram ist der Notfallkanal. Die Kanalliste lautet damit
["RocketChat", "Telegram"]. Konsequenzen:
- Das Telegram-Tool wird nicht abgebaut und geht nicht in Rocket.Chat auf. Es behält seine Rolle, verliert aber die Rolle als Alltagskanal.
Telegram.send_messagebleibt in der Staging-Policy aufapprove— mit einer Ausnahme: Meldungen, die derChannelRouterselbst erzeugt (Ausfall, Budget, Watchdog, offene Freigabe), laufen ohne Freigabe. Sonst bliebe die Warnung, dass eine Freigabe aussteht, selbst in der Freigabewarteschlange hängen — ein Ringschluss, der genau im Ernstfall zuschlägt.- Der Telegram-Poll bleibt dauerhaft eingerichtet, aber mit langsamem Takt. Ein Kanal, der erst im Notfall eingeschaltet wird, ist im Notfall ungetestet.
- Mail bleibt außen vor. Zwei Ersatzkanäle zu pflegen lohnt nicht; das Mail-Tool behält seinen fachlichen Zweck.
3.4 Was das für die Prompts heißt
Ein Agent soll seinen Kanal nicht selbst wählen. Er sagt „ich möchte dem Nutzer das hier mitteilen", der Router entscheidet. Sonst muss das Modell im Fehlerfall improvisieren — und genau dann ist Improvisation das Letzte, was man will.
4 — Konflikt mit Roadmap A5 (Matrix)
Roadmap-Punkt A5 legt fest: „Die Kommunikation (Benachrichtigungen, Berichte, Chat mit Agenten) wird auf Element/Matrix umgestellt", und der gestrichene Tool-Kandidat Notify geht darin auf.
Rocket.Chat besetzt exakt dieselbe Rolle. Drei mögliche Auflösungen:
- Rocket.Chat ersetzt A5. A5 wird umgeschrieben, Matrix entfällt. Vorteil: eine Schiene, ein Betriebsaufwand, die Instanz läuft bereits.
- A5 bleibt, Rocket.Chat ist nur ein weiteres Tool. Dann bauen wir zweimal dasselbe. Schwer zu begründen.
- Rocket.Chat primär, Matrix als späterer Zweitkanal. Passt formal zur Redundanz-Anforderung, verdoppelt aber den Wartungsaufwand für einen Fall, den Telegram schon abdeckt.
Meine Empfehlung: (1). Der ChannelRouter aus 3.2 ist ohnehin die Verallgemeinerung,
die A5 gebraucht hätte — mit ihm ist ein späterer Matrix-Kanal ein zusätzlicher Eintrag in
der Liste, keine Migration. Das ist eine Entscheidung für dich, keine technische Sachfrage.
5 — Nextcloud: Machbarkeit
5.1 Der Zugriffsweg
Nextcloud hat zwei Schnittstellen, beide brauchen wir:
| Zweck | Schnittstelle |
|---|---|
| Dateien lesen/schreiben/auflisten/verschieben | WebDAV: /remote.php/dav/files/{benutzer}/{pfad} |
| Öffentlichen Link erzeugen | OCS: /ocs/v2.php/apps/files_sharing/api/v1/shares |
Authentifiziert wird mit App-Passwörtern (Nextcloud → Einstellungen → Sicherheit → „Neues App-Passwort erstellen") per Basic-Auth. Ein App-Passwort ist einzeln widerrufbar und lässt das eigentliche Kontopasswort unangetastet — dieselbe Logik wie das Personal Access Token bei Rocket.Chat.
WebDAV braucht keine Bibliothek: HttpClient mit den Methoden PUT, GET, MKCOL,
PROPFIND, MOVE, DELETE. Nur PROPFIND liefert XML (Multistatus), das geparst werden
muss — überschaubar, und es erspart uns eine weitere Abhängigkeit.
5.2 Ein Benutzer je Agent — oder ein Sammelkonto?
Zwei Modelle:
- Je Agent ein Nextcloud-Benutzer. Sauber nachvollziehbar („wer hat das abgelegt"), passt zum Rocket.Chat-Modell, kostet je nach Lizenzmodell Nutzer.
- Ein Dienstkonto
clawd-agentsmit Unterordnern je Agent. Einfacher zu verwalten, Herkunft steht dann im Pfad statt im Konto.
Empfehlung: Ein Dienstkonto mit Ordnerstruktur /ClawdDotNet/{Agent}/…, plus einen
mit dir geteilten Ordner /ClawdDotNet/Berichte/. Begründung: Bei Rocket.Chat ist die
eigene Identität funktional zwingend (DMs, Erwähnungen), bei Dateien ist sie es nicht —
und ein Ordnerbaum ist leichter aufzuräumen als zehn Konten. Falls du die Trennung dennoch
willst, ändert das am Tool nichts, nur an der Konfiguration.
Die Ordnerdurchsetzung gehört ins Tool: eine konfigurierte rootPath, aus der der Agent
nicht ausbrechen kann — dieselbe Prüfung wie in FTPTool.ResolveLocalPath.
5.3 Die ehrliche Antwort zu „direkt über die API erstellen"
Nextcloud hat keine API, die Dokumenteninhalte erzeugt. Es ist ein Dateiablage- und Freigabesystem; Collabora ist ein Editor im Browser (über WOPI angebunden), kein Generator, den man von außen mit „erstelle eine Tabelle mit diesen Zahlen" beauftragen kann.
Der tatsächliche Weg ist deshalb der, den du selbst schon beschrieben hast:
Agent erzeugt die Datei im eigenen Workspace (FileRW-Tool, schon vorhanden)
→ Nextcloud.upload (WebDAV PUT)
→ Nextcloud.share (optional) (OCS, liefert Link)
→ RocketChat.send_message mit dem Link
Das ist kein Umweg, sondern die richtige Aufteilung: Der Agent kann seine Datei lokal prüfen und korrigieren, bevor sie irgendwo landet.
5.4 Formate — und wo Collabora doch nützlich wird
Was ein Agent von sich aus gut schreiben kann: Markdown (Nextcloud rendert .md
direkt in der Weboberfläche — für Berichte oft die beste Wahl), CSV, HTML, JSON.
Was er nicht von sich aus schreiben kann: .xlsx, .docx, .pdf.
Hier gibt es einen eleganten Weg, weil du Collabora ohnehin betreibst: Collabora Online
bringt einen Konvertierungs-Endpunkt mit (POST /cool/convert-to/{format}, multipart).
Damit gilt:
| Ziel | Weg |
|---|---|
| Agent schreibt HTML oder ODT → Collabora → PDF | |
| XLSX | Agent schreibt CSV → Collabora → XLSX |
| DOCX | Agent schreibt HTML/ODT → Collabora → DOCX |
Vorteil: keine zusätzliche PDF- oder Excel-Bibliothek im Projekt (und keine Lizenzfrage, die wir uns damit einhandeln — mehrere verbreitete .NET-Bibliotheken für XLSX und PDF sind für kommerzielle Nutzung nicht frei).
Zu prüfen, bevor wir darauf bauen:
- Ist der Endpunkt in deiner Collabora-Installation erreichbar? Er muss in
coolwsd.xmlfür die IP des ClawdDotNet-Rechners freigegeben sein (net/post_allow-Allowlist). Standardmäßig ist das eng gefasst. - Der Pfad heißt je nach Version
/cool/convert-to/…(neu) oder/lool/convert-to/…(alt).
Falls der Endpunkt nicht freigegeben werden soll: Rückfallebene ist Markdown/CSV — für den Alltag völlig ausreichend, PDF wäre dann ein späterer eigener Punkt.
5.5 Freigabe-Links
POST /ocs/v2.php/apps/files_sharing/api/v1/shares (Header OCS-APIRequest: true),
shareType=3 = öffentlicher Link. Optional password, expireDate, permissions=1
(nur lesen). Die Antwort enthält die fertige URL.
Zwei Hinweise:
- Manche Instanzen erzwingen Passwortschutz für öffentliche Links — dann muss das Tool ein Passwort mitgeben und zurückliefern.
- Ein öffentlicher Link ist irreversibel im Sinne von A2: Einmal geteilt, kann er
weitergegeben worden sein, auch wenn man ihn danach löscht. Deshalb steht er unten in
der Staging-Tabelle auf
approve.
Innerhalb der eigenen Instanz ist die freundlichere Variante shareType=0 (an einen
konkreten Nextcloud-Benutzer) — kein öffentlicher Link nötig, wenn du ohnehin ein Konto
hast. Das sollte der Standard sein, öffentlich die Ausnahme.
5.6 Fallstricke
- Dateisperren (HTTP 423). Wenn du eine Datei gerade in Collabora offen hast, kann ein Upload auf dieselbe Datei scheitern. Das Tool muss 423 sauber melden statt kryptisch zu scheitern — und beim Überschreiben eines Berichts lieber einen neuen Dateinamen mit Zeitstempel vergeben.
- Überschreiben ist nicht destruktiv, solange die Versionierung aktiv ist (Nextcloud
legt automatisch eine Vorversion an). Das ist der Grund, warum
Nextcloud.uploadunten aufautosteht,FTP.uploadaber aufapprove. - Größenbegrenzung. Ein einfaches
PUTreicht für Berichte problemlos; erst bei sehr großen Dateien bräuchte es den Chunked-Upload (/remote.php/dav/uploads/…). Für den angedachten Zweck (Berichte, Tabellen, PDFs) nicht nötig — und wenn doch, meldet der Server einen klaren Fehler. - Quota. Ein Agent, der stündlich Berichte ablegt, füllt das Konto. Ein Aufräum-Task („Berichte älter als 90 Tage") gehört mittelfristig ins Taskboard.
5.7 Tool-Zuschnitt
Tool: Nextcloud
Aktionen: upload | download | list | mkdir | move | delete
| share | unshare | convert (convert nur falls Collabora freigegeben)
Konfiguration je Agent:
"Nextcloud": {
"baseUrl": "https://cloud.example.org",
"username": "clawd-agents",
"appPassword": "…", // von ConfigSecrets geschützt
"rootPath": "/ClawdDotNet/Hermes",
"allowPublicShares": false,
"collaboraUrl": "https://collabora.example.org"
}
appPassword muss der Schlüsselliste in ConfigSecrets hinzugefügt werden — password
allein greift nicht, weil dort auf ganze Feldnamen verglichen wird.
6 — Verzahnung mit Staging (A2) und Audit (A3)
Vorschlag für die StagingPolicy.DefaultRules:
| Aktion | Standard | Begründung |
|---|---|---|
RocketChat.send_message (erlaubter Raum) |
auto | Sonst ist Chat unbenutzbar — jede Antwort bräuchte einen Klick |
RocketChat.send_message (Raum nicht in allowedRooms) |
deny | Wird vom Tool selbst abgewiesen, gar nicht erst vorgelegt |
RocketChat.send_file |
approve | Dateiabfluss in einen Chatraum |
Nextcloud.upload, mkdir, move |
auto | Versioniert, im eigenen Ordner, umkehrbar |
Nextcloud.delete |
approve | wie FileRW.delete |
Nextcloud.share (an Benutzer) |
auto | bleibt innerhalb der Instanz |
Nextcloud.share (öffentlicher Link) |
approve | nicht zurückholbar |
Der Unterschied zu Telegram.send_message (heute approve) ist Absicht: Telegram ist ein
Benachrichtigungskanal nach außen, Rocket.Chat ist der Arbeitsraum. Ein Arbeitsraum, in
dem jede Antwort eine Freigabe braucht, ist kein Arbeitsraum. Der Schutz sitzt hier an der
Raum-Allowlist statt an der Einzelfreigabe.
Für das Audit-Log entstehen keine Sonderfälle — die Tool-Aufrufe laufen ohnehin durch.
7 — Was dieses Konzept nicht vorsieht
Damit der Zuschnitt klar ist:
- Keine Rocket.Chat-App (Apps-Engine, TypeScript im Server) — wir bleiben Client.
- Keine Verwaltung von Rocket.Chat durch Agenten (Benutzer anlegen, Räume erstellen, Rechte vergeben). Das ist Admin-Arbeit in der WinForms-Oberfläche.
- Keine Sprach-/Videofunktionen, keine Nextcloud Talk-Anbindung.
- Kein Ersatz für den WinForms-Chat — der bleibt und ist die unterste Rückfallebene.
- Keine Ende-zu-Ende-Verschlüsselung. Rocket.Chat kann das, aber verschlüsselte Räume sind über die REST-API nicht lesbar. Agenten arbeiten in unverschlüsselten Räumen — das ist eine bewusste Einschränkung, die du kennen solltest.
8 — Vorschlag für den Schnitt
| Phase | Inhalt | Ergebnis |
|---|---|---|
| 1 | Nextcloud-Tool: upload/download/list/mkdir/move/delete/share |
Agent kann Berichte ablegen und einen Link liefern |
| 2 | RocketChat-Tool: senden, lesen, rocketchat_poll-Job, Raum-Allowlist, Erwähnungsfilter, Schleifendrossel |
Gespräch mit Agenten über Rocket.Chat, Antwort per Prompt |
| 3 | Automatischer Rückweg (ReplyTo in ToolJobResult) |
Antwort landet zuverlässig im richtigen Raum/Thread |
| 4 | ChannelRouter + rocketchat_health + Eskalation |
Der Notfallkanal — Ausfall wird erkannt und umschifft |
| 5 | Collabora-Konvertierung (PDF/XLSX) | Berichte in Büroformaten |
| 6 (optional) | Realtime/DDP statt Polling | Antwortzeit ~1 s statt ~30 s |
Nextcloud zuerst, weil es das kleinere, in sich abgeschlossene Stück ist und sofort Nutzen bringt — und weil es sich unabhängig vom Ausgang der A5-Entscheidung lohnt.
Phase 4 ist kein Nice-to-have: Ohne sie ist Rocket.Chat ein Einzelpunkt, dessen Ausfall niemand meldet. Sie sollte nicht hinter Phase 5 rutschen.
Zur Modell-Einstufung im Sinne der Roadmap: Phasen 1, 2 und 5 sind klar spezifizierbare Tool-Arbeit (4.6-tauglich). Phase 3 und 4 fassen Engine bzw. Zustellwege an und sollten mit vorheriger Festlegung der Invarianten und mit Tests gebaut werden.
9 — Offene Punkte für die Diskussion
- A5/Matrix — ersetzt Rocket.Chat den Punkt, oder bleibt Matrix als Ziel bestehen?
(Abschnitt 4; das entscheidet, ob der
ChannelRouterPflicht oder Kür ist.) - Nextcloud-Identität — ein Dienstkonto mit Ordnern je Agent (mein Vorschlag) oder je Agent ein eigener Nextcloud-Benutzer?
- Rückweg der Antwort — reicht Phase 2 (Agent antwortet selbst) für den Anfang, oder soll Phase 3 direkt mitgebaut werden?
Notfallkanal — Telegram oder Mail?Entschieden: Telegram (siehe 3.3). Offen bleibt nur die Kleinigkeit, ob die Reihenfolge instanzweit gilt (mein Vorschlag) oder pro Agent einstellbar sein soll.- Collabora-Konvertierung — ist der
convert-to-Endpunkt für den ClawdDotNet-Rechner freigebbar? Falls nein, bleibt es bei Markdown/CSV. - Versionen — welche Rocket.Chat- und welche Nextcloud-Version läuft bei dir? Einzelne Endpunkte und Rollennamen sind versionsabhängig; das prüfe ich vor der Umsetzung gegen deine Instanz statt gegen die Dokumentation.
- Öffentliche Links — grundsätzlich erlauben (mit Freigabe) oder ganz sperren
(
allowPublicShares: falseals harte Voreinstellung)?