16 KiB
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
- Discord-Bot verbindet sich mit einem Server (Token wird beim Setup angegeben)
- DisClaw erstellt beim ersten Start automatisch seinen eigenen Management-Kanal (
#disclaw) /new-agent-Befehl im Management-Kanal -- legt neuen Discord-Kanal, Workspace-Ordner und Agenten-Identitaet an- Jeder Agent-Kanal hat seinen eigenen Ordner, eigene
CLAUDE.md, eigene.claude/-Konfiguration - Nachrichten in Agent-Kanaelen werden direkt von Claude Code beantwortet (kein @mention noetig)
- Keine Berechtigungseinschraenkungen -- jeder Agent hat vollen Zugriff
- Setup ueber
/setupCustom Command in Claude Code - Agenten-Erstellung ueber
/new-agentCustom Command in Claude Code (ohne Discord)
Explizit zurueckgestellt (siehe "Zukuenftige Phasen")
- Berechtigungssystem / rollenbasierter Zugriff
- Weitere Slash-Commands ueber
/new-agenthinaus - 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.
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).
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
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)
# 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)
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 "<prompt>" --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.mdwerden sofort wirksam (bei der naechsten Nachricht) - Benutzer koennen die
CLAUDE.mddirekt bearbeiten, um das Verhalten anzupassen - Die gleiche
CLAUDE.mdfunktioniert 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:
agent.yaml-- Routing-MetadatenCLAUDE.md-- Reichhaltige Identitaetsdatei mit Rolle, Persoenlichkeit und Richtlinien.claude/commands/-- Verzeichnis fuer agenten-spezifische Custom Commands.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:
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:
- Berechtigungssystem -- Rollenbasierter Zugriff, definieren welche Agenten welche Dateien / Befehle nutzen duerfen
- Weitere Slash-Commands --
/list-agents,/delete-agent,/agent-config - Agent-zu-Agent-Kommunikation -- Agenten koennen einander Aufgaben delegieren
- Docker-Isolation -- Jeder Agent laeuft in einem eigenen Container
- Streaming-Antworten -- Teilantworten waehrend Claude arbeitet in Discord anzeigen
- Web-Dashboard -- Uebersicht ueber Agenten, Konversationen und Nutzung
- Dateisystem-Watcher -- Agenten reagieren auf Datei-Aenderungen in ihrem Workspace