# DisClaw -- Architektur ## Projektuebersicht DisClaw ist ein Discord-Bot, der einen Discord-Server in einen Multi-Agenten-Arbeitsbereich verwandelt. Jeder Discord-Kanal wird einem lokalen Workspace-Ordner zugeordnet, in dem ein eigenstaendiger Claude-Code-Agent lebt. Ein zentraler Management-Agent (DisClaw selbst) orchestriert das Erstellen neuer Agenten und deren Kanaele. Die Kommunikation mit den Agenten erfolgt ausschliesslich ueber Discord-Nachrichten. **Engine: Claude Code CLI** -- DisClaw verwendet die lokal installierte Claude Code CLI (`claude`) als KI-Engine. Es wird kein API-Key benoetigt. Die CLI wird pro Nachricht als Kindprozess gestartet und liest die `CLAUDE.md` im Workspace-Ordner automatisch als Agenten-Identitaet. --- ## MVP-Umfang ### Enthalten 1. Discord-Bot verbindet sich mit einem Server (Token wird beim Setup angegeben) 2. DisClaw erstellt beim ersten Start automatisch seinen eigenen Management-Kanal (`#disclaw`) 3. `/new-agent`-Befehl im Management-Kanal -- legt neuen Discord-Kanal, Workspace-Ordner und Agenten-Identitaet an 4. Jeder Agent-Kanal hat seinen eigenen Ordner, eigene `CLAUDE.md`, eigene `.claude/`-Konfiguration 5. Nachrichten in Agent-Kanaelen werden direkt von Claude Code beantwortet (kein @mention noetig) 6. Keine Berechtigungseinschraenkungen -- jeder Agent hat vollen Zugriff 7. Setup ueber `/setup` Custom Command in Claude Code 8. Agenten-Erstellung ueber `/new-agent` Custom Command in Claude Code (ohne Discord) ### Explizit zurueckgestellt (siehe "Zukuenftige Phasen") - Berechtigungssystem / rollenbasierter Zugriff - Weitere Slash-Commands ueber `/new-agent` hinaus - Agent-zu-Agent-Koordination / Delegation - Docker-Isolation - Kostentracking / Budgetlimits - Web-UI - Dateisystem-Watcher --- ## Systemarchitektur ``` Discord Server | v +-------------------+ | Discord Bot | discord.js v14 -- empfaengt Nachrichten und Slash-Commands +-------------------+ | v +-------------------+ | Message Router | Ordnet Nachrichten dem richtigen Agent zu (anhand channel_id) +-------------------+ | +---> Management-Kanal? ---> DisClaw Command Handler (/new-agent) | +---> Agent-Kanal? -------> Agent Runner | v +-------------------+ | Agent Runner | Startet Claude Code CLI als Kindprozess +-------------------+ | v +-------------------+ | Claude Code CLI | claude -p "prompt" --output-format json +-------------------+ cwd = workspace-ordner (liest CLAUDE.md) | v Antwort --> Discord-Kanal ``` ### Komponentenverantwortlichkeiten | Komponente | Verantwortlichkeit | |---|---| | **Discord Bot** | Verbindung zum Server, Empfang von Events, Senden von Antworten | | **Message Router** | Entscheidet anhand der `channel_id`, ob eine Nachricht an den DisClaw-Handler oder einen Agent Runner geht | | **Command Handler** | Verarbeitet `/new-agent` -- erstellt Kanal, Ordner, DB-Eintrag, `agent.yaml`, `CLAUDE.md`, `.claude/` | | **Agent Runner** | Startet `claude` CLI als Kindprozess mit dem Workspace als cwd, parst JSON-Ausgabe | | **SQLite DB** | Speichert Kanal-Workspace-Zuordnungen und Konversationshistorie | --- ## Ordnerstruktur ``` disclaw/ src/ index.ts # Einstiegspunkt -- Bot starten, Events registrieren bot.ts # Discord-Bot-Setup und Event-Handler router.ts # Message Router -- Nachricht -> Handler-Zuordnung commands/ new-agent.ts # /new-agent Slash-Command-Handler agent/ runner.ts # Agent Runner -- Claude CLI als Kindprozess starten identity.ts # CLAUDE.md und agent.yaml erstellen und laden db/ database.ts # SQLite-Verbindung und Queries config/ loader.ts # .env und disclaw.yaml laden workspaces/ # Dynamisch erzeugt -- ein Unterordner pro Agent agent-name/ CLAUDE.md # Agenten-Identitaet (wird von Claude Code automatisch gelesen) agent.yaml # DisClaw-Routing-Metadaten (Name, Rolle, Channel-ID) .claude/ commands/ # Agenten-spezifische Custom Commands (leer fuer den Anfang) settings.json # Agenten-spezifische Claude-Code-Einstellungen ... # Arbeitsdateien des Agenten .claude/ commands/ setup.md # /setup -- Gefuehrtes Erstsetup new-agent.md # /new-agent -- Agent ueber CLI erstellen CLAUDE.md # Projekt-CLAUDE.md (DisClaw-Beschreibung fuer Claude Code) disclaw.yaml # Globale Konfiguration .env # DISCORD_BOT_TOKEN, DISCORD_GUILD_ID, CLAUDE_PATH package.json tsconfig.json ``` --- ## Datenmodell (SQLite) ### Tabelle: `workspaces` Bildet Discord-Kanaele auf lokale Workspace-Ordner ab. ```sql CREATE TABLE workspaces ( id INTEGER PRIMARY KEY AUTOINCREMENT, channel_id TEXT NOT NULL UNIQUE, -- Discord Channel-ID guild_id TEXT NOT NULL, -- Discord Server-ID agent_name TEXT NOT NULL UNIQUE, -- Eindeutiger Agentenname workspace_path TEXT NOT NULL, -- Absoluter Pfad zum Workspace-Ordner created_at TEXT NOT NULL DEFAULT (datetime('now')) ); ``` ### Tabelle: `conversations` Speichert die Konversationshistorie pro Agent (fuer Kontext bei Neustart). ```sql CREATE TABLE conversations ( id INTEGER PRIMARY KEY AUTOINCREMENT, workspace_id INTEGER NOT NULL REFERENCES workspaces(id), discord_msg_id TEXT NOT NULL UNIQUE, -- Discord Message-ID (Deduplizierung) role TEXT NOT NULL, -- 'user' oder 'assistant' content TEXT NOT NULL, author_name TEXT, -- Discord-Username des Absenders created_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX idx_conversations_workspace ON conversations(workspace_id, created_at); ``` Entscheidung: Die Konversationstabelle dient primaer dazu, bei einem Bot-Neustart den Kontext wiederherstellen zu koennen. Sie ist kein Chat-Archiv -- alte Eintraege koennen bei Bedarf gekuerzt werden. --- ## Konfiguration ### `.env` ```env DISCORD_BOT_TOKEN=... DISCORD_GUILD_ID=... # Optionaler Fallback, wenn nur ein Server unterstuetzt wird CLAUDE_PATH=... # Optional: Pfad zur claude CLI (Standard: "claude" im PATH) ``` **Kein ANTHROPIC_API_KEY noetig.** DisClaw verwendet die Claude Code CLI, die mit einem Claude Pro/Max-Abonnement funktioniert. ### `disclaw.yaml` (globale Konfiguration) ```yaml # Pfad, unter dem Workspace-Ordner erstellt werden workspaces_root: "./workspaces" # Name des Management-Kanals management_channel: "disclaw" # Claude Code CLI Befehl (Standard: "claude") claude_command: "claude" # Timeout in Sekunden fuer Claude-CLI-Prozesse (Standard: 120) claude_timeout_seconds: 120 ``` ### `agent.yaml` (pro Workspace -- nur DisClaw-Metadaten) ```yaml name: "frontend-dev" display_name: "Frontend Dev" role: "Frontend-Entwickler fuer das Webprojekt" channel_id: "1234567890" ``` ### `CLAUDE.md` (pro Workspace -- Agenten-Identitaet) Die `CLAUDE.md`-Datei ist der primaere Identitaetsmechanismus. Claude Code liest sie automatisch, wenn der Workspace als Arbeitsverzeichnis gesetzt wird. Sie enthaelt: - Name und Rolle des Agenten - Persoenlichkeitsmerkmale - Verhaltensrichtlinien - Projektspezifischen Kontext --- ## Nachrichtenfluss Schritt-fuer-Schritt-Ablauf, wenn ein Benutzer eine Nachricht in einem Agent-Kanal schreibt: ``` 1. Discord Event: messageCreate - Bot prueft: Nachricht von einem Bot? -> Ignorieren - Bot prueft: Nachricht in einem bekannten Kanal? -> Weiter 2. Message Router - DB-Abfrage: SELECT * FROM workspaces WHERE channel_id = ? - Kein Treffer? -> Nachricht ignorieren - Treffer im Management-Kanal? -> Command Handler - Treffer in Agent-Kanal? -> Agent Runner 3. Agent Runner - Lade agent.yaml aus dem Workspace-Ordner (Validierung) - Baue Prompt zusammen: - Konversationshistorie aus der DB - Laufzeitkontext (Channel-Name, Datum) - Neue Benutzernachricht - Starte Claude Code CLI als Kindprozess: claude -p "" --output-format json mit cwd = workspace_path - Claude Code liest automatisch die CLAUDE.md im Workspace - Parse JSON-Ausgabe und extrahiere Textantwort 4. Antwort zurueck - Speichere User-Nachricht in conversations (role: 'user') - Speichere Agent-Antwort in conversations (role: 'assistant') - Sende Antwort in den Discord-Kanal - Bei langen Antworten: automatisch aufteilen (Discord-Limit: 2000 Zeichen) ``` ### Sonderfaelle - **Lange Antworten**: Nachrichten ueber 2000 Zeichen werden an sinnvollen Stellen aufgeteilt (Zeilenumbrueche bevorzugt) - **Typing-Indikator**: Bot zeigt "tippt..." an, waehrend Claude arbeitet - **Fehlerbehandlung**: Bei CLI-Fehlern wird eine verstaendliche Nachricht im Kanal gepostet - **Timeout**: Claude-CLI-Prozesse werden nach 120 Sekunden (konfigurierbar) abgebrochen - **CLI nicht gefunden**: Verstaendliche Fehlermeldung mit Installationshinweis --- ## Agenten-Identitaet Jeder Agent hat eine eigene Identitaet, die aus der `CLAUDE.md`-Datei im Workspace-Ordner geladen wird. Claude Code liest diese Datei automatisch. ### Identitaetsmechanismus ``` CLAUDE.md (im Workspace) = Primaere Identitaet - Name, Rolle, Persoenlichkeit - Verhaltensrichtlinien - Projektspezifischer Kontext agent.yaml (im Workspace) = DisClaw-Routing-Metadaten - Name (fuer DB-Lookup) - Channel-ID (fuer Kanal-Zuordnung) - Display-Name (fuer Anzeige) Konversationshistorie (aus DB) = Laufzeitkontext - Letzte 30 Nachrichten werden dem Prompt vorangestellt ``` Im Gegensatz zur vorherigen Architektur (Claude Agent SDK mit System-Prompt) wird die Identitaet nicht programmatisch zusammengebaut, sondern direkt von Claude Code aus der `CLAUDE.md` gelesen. Das bedeutet: - Aenderungen an der `CLAUDE.md` werden sofort wirksam (bei der naechsten Nachricht) - Benutzer koennen die `CLAUDE.md` direkt bearbeiten, um das Verhalten anzupassen - Die gleiche `CLAUDE.md` funktioniert auch, wenn man Claude Code interaktiv im Workspace-Ordner startet ### Workspace-Erstellung Beim `/new-agent`-Befehl werden Name und Rolle als Parameter uebergeben. Daraus werden generiert: 1. `agent.yaml` -- Routing-Metadaten 2. `CLAUDE.md` -- Reichhaltige Identitaetsdatei mit Rolle, Persoenlichkeit und Richtlinien 3. `.claude/commands/` -- Verzeichnis fuer agenten-spezifische Custom Commands 4. `.claude/settings.json` -- Claude-Code-Einstellungen ``` /new-agent name:frontend-dev role:Frontend-Entwickler ``` --- ## Setup-Ablauf ### Voraussetzungen - Node.js v20+ - Claude Code CLI (`npm install -g @anthropic-ai/claude-code`) - Claude Pro oder Max Abonnement (fuer die CLI) - Discord-Bot-Token ### Ersteinrichtung Die einfachste Methode ist der `/setup` Custom Command in Claude Code: ```bash cd disclaw/ claude # Dann im Claude-Code-Chat: /setup ``` Alternativ manuell: ``` 1. Benutzer erstellt Discord-Bot ueber Discord Developer Portal 2. Benutzer konfiguriert .env (DISCORD_BOT_TOKEN, DISCORD_GUILD_ID) 3. Benutzer fuehrt `npm install && npm run build && npm run start` aus 4. Bot startet: a. Laedt .env und disclaw.yaml b. Initialisiert SQLite-Datenbank (erstellt Tabellen falls noetig) c. Verbindet sich mit Discord d. Prueft: Existiert der Management-Kanal (#disclaw)? - Nein -> Erstellt ihn, speichert channel_id in der DB - Ja -> Laedt bestehende Zuordnung e. Registriert /new-agent Slash-Command f. Sendet Begruessungsnachricht im Management-Kanal 5. Bot wartet auf Events (messageCreate, interactionCreate) ``` ### /new-agent Ablauf ``` 1. Benutzer schreibt /new-agent name:researcher role:Recherche-Agent 2. Command Handler: a. Validiert: Name eindeutig? Keine Sonderzeichen? b. Erstellt Discord-Kanal: #researcher c. Erstellt Ordner: workspaces/researcher/ d. Generiert: workspaces/researcher/CLAUDE.md (Agenten-Identitaet) e. Generiert: workspaces/researcher/agent.yaml (Metadaten) f. Generiert: workspaces/researcher/.claude/ (Konfiguration) g. Speichert Zuordnung in DB (workspaces-Tabelle) h. Antwortet im Management-Kanal: "Agent 'researcher' erstellt in #researcher" 3. Ab sofort: Nachrichten in #researcher werden vom Researcher-Agent beantwortet ``` --- ## Architekturentscheidungen ### ADR-001: Claude Code CLI statt Agent SDK **Status**: Akzeptiert (ersetzt vorherige Entscheidung fuer Claude Agent SDK) **Kontext**: Agenten koennten ueber das Claude Agent SDK (`@anthropic-ai/claude-agent-sdk`), durch die Claude Code CLI oder direkt ueber die Anthropic API angesprochen werden. **Entscheidung**: Wir verwenden die Claude Code CLI (`claude -p "prompt" --output-format json`). Vorteile: - Kein API-Key noetig -- funktioniert mit Claude Pro/Max-Abonnement - Automatische CLAUDE.md-Erkennung als Identitaetsmechanismus - Zugang zu allen Claude-Code-Tools (Dateisystem, Bash, etc.) - Einfacherer Setup-Prozess fuer Endbenutzer **Konsequenzen**: Pro Nachricht wird ein neuer Prozess gestartet (kein persistenter Agent-Zustand). Die Konversationshistorie wird ueber die DisClaw-Datenbank verwaltet und dem Prompt vorangestellt. Leichter Overhead durch Prozess-Spawn, aber akzeptabel fuer den Chat-Anwendungsfall. ### ADR-002: SQLite statt reiner Dateispeicherung **Status**: Akzeptiert **Kontext**: Kanal-Zuordnungen und Konversationen koennten in JSON-Dateien oder in SQLite gespeichert werden. **Entscheidung**: SQLite ueber better-sqlite3. Synchrone API passt zum Message-Handler-Modell, atomare Schreibvorgaenge verhindern Datenverlust. **Konsequenzen**: Eine Abhaengigkeit mehr (better-sqlite3 ist eine native Erweiterung). Dafuer zuverlaessige Persistenz, einfache Abfragen und gute Performance bei kleinen bis mittleren Datenmengen. ### ADR-003: Ein Bot-Prozess, CLI-Prozesse pro Nachricht **Status**: Akzeptiert (aktualisiert) **Kontext**: Man koennte pro Agent einen persistenten Prozess starten, alle Agenten in einem Bot-Prozess verwalten, oder pro Nachricht einen CLI-Prozess starten. **Entscheidung**: Ein einzelner Bot-Prozess (Node.js) empfaengt Discord-Nachrichten und startet pro Nachricht einen `claude` CLI-Prozess. Der CLI-Prozess terminiert nach der Antwort. **Konsequenzen**: Einfacheres Ressourcenmanagement -- kein Speicher fuer idle Agenten. Leichter Overhead durch Prozess-Spawn. Konversationskontext muss explizit ueber die DB verwaltet werden. Ein abgestuerzter CLI-Prozess betrifft nur eine einzelne Nachricht, nicht den gesamten Bot. ### ADR-004: CLAUDE.md als Identitaetsmechanismus **Status**: Akzeptiert **Kontext**: Die Agenten-Identitaet (Name, Rolle, Persoenlichkeit, Anweisungen) muss Claude mitgeteilt werden. Optionen: System-Prompt via API, CLAUDE.md-Datei, oder beides. **Entscheidung**: Die `CLAUDE.md`-Datei im Workspace-Ordner ist der primaere Identitaetsmechanismus. Claude Code liest sie automatisch. Kein programmatisch zusammengebauter System-Prompt mehr. **Konsequenzen**: Benutzer koennen Agenten-Verhalten durch direkte Bearbeitung der `CLAUDE.md` anpassen. Die gleiche Konfiguration funktioniert interaktiv und ueber DisClaw. Weniger Code in der Identity-Schicht. --- ## Zukuenftige Phasen In der Reihenfolge der voraussichtlichen Prioritaet: 1. **Berechtigungssystem** -- Rollenbasierter Zugriff, definieren welche Agenten welche Dateien / Befehle nutzen duerfen 2. **Weitere Slash-Commands** -- `/list-agents`, `/delete-agent`, `/agent-config` 3. **Agent-zu-Agent-Kommunikation** -- Agenten koennen einander Aufgaben delegieren 4. **Docker-Isolation** -- Jeder Agent laeuft in einem eigenen Container 5. **Streaming-Antworten** -- Teilantworten waehrend Claude arbeitet in Discord anzeigen 6. **Web-Dashboard** -- Uebersicht ueber Agenten, Konversationen und Nutzung 7. **Dateisystem-Watcher** -- Agenten reagieren auf Datei-Aenderungen in ihrem Workspace