Hooks
Hooks bieten ein erweiterbares ereignisgesteuertes System zur Automatisierung von Aktionen als Reaktion auf Agent-Befehle und Events. Hooks werden automatisch aus Verzeichnissen erkannt und können über CLI-Befehle verwaltet werden, ähnlich wie Skills in OpenClaw funktionieren.
Erste Orientierung
Hooks sind kleine Skripte, die ausgeführt werden, wenn etwas passiert. Es gibt zwei Arten:
- Hooks (diese Seite): laufen im Gateway, wenn Agent-Events ausgelöst werden, wie
/new,/reset,/stopoder Lifecycle-Events. - Webhooks: externe HTTP-Webhooks, mit denen andere Systeme Arbeit in OpenClaw auslösen können. Siehe Webhook Hooks oder nutze
openclaw webhooksfür Gmail-Hilfsbefehle.
Hooks können auch in Plugins gebündelt werden; siehe Plugins.
Häufige Anwendungsfälle:
- Speichere einen Memory-Snapshot, wenn du eine Session zurücksetzt
- Führe ein Audit-Log von Befehlen für Troubleshooting oder Compliance
- Löse Follow-up-Automatisierung aus, wenn eine Session startet oder endet
- Schreibe Dateien in den Agent-Workspace oder rufe externe APIs auf, wenn Events ausgelöst werden
Wenn du eine kleine TypeScript-Funktion schreiben kannst, kannst du einen Hook schreiben. Hooks werden automatisch erkannt, und du aktivierst oder deaktivierst sie über die CLI.
Überblick
Das Hook-System ermöglicht dir:
- Session-Context in Memory speichern, wenn
/newausgeführt wird - Alle Befehle für Auditing loggen
- Eigene Automatisierungen bei Agent-Lifecycle-Events auslösen
- OpenClaw-Verhalten erweitern, ohne den Core-Code zu ändern
Erste Schritte
Mitgelieferte Hooks
OpenClaw wird mit vier mitgelieferten Hooks ausgeliefert, die automatisch erkannt werden:
- 💾 session-memory: Speichert Session-Context in deinem Agent-Workspace (Standard:
~/.openclaw/workspace/memory/), wenn du/newausführst - 📝 command-logger: Loggt alle Command-Events nach
~/.openclaw/logs/commands.log - 🚀 boot-md: Führt
BOOT.mdaus, wenn das Gateway startet (erfordert aktivierte interne Hooks) - 😈 soul-evil: Tauscht injizierten
SOUL.md-Content mitSOUL_EVIL.mdwährend eines Purge-Fensters oder zufällig aus
Liste verfügbare Hooks auf:
openclaw hooks list
Aktiviere einen Hook:
openclaw hooks enable session-memory
Prüfe Hook-Status:
openclaw hooks check
Hole detaillierte Informationen:
openclaw hooks info session-memory
Onboarding
Während des Onboardings (openclaw onboard) wirst du aufgefordert, empfohlene Hooks zu aktivieren. Der Wizard erkennt automatisch geeignete Hooks und präsentiert sie zur Auswahl.
Hook-Discovery
Hooks werden automatisch aus drei Verzeichnissen erkannt (in Reihenfolge der Priorität):
- Workspace-Hooks:
<workspace>/hooks/(pro Agent, höchste Priorität) - Managed Hooks:
~/.openclaw/hooks/(benutzerinstalliert, workspace-übergreifend) - Bundled Hooks:
<openclaw>/dist/hooks/bundled/(mit OpenClaw ausgeliefert)
Managed-Hook-Verzeichnisse können entweder ein einzelner Hook oder ein Hook-Pack (Package-Verzeichnis) sein.
Jeder Hook ist ein Verzeichnis mit:
my-hook/
├── HOOK.md # Metadaten + Dokumentation
└── handler.ts # Handler-Implementierung
Hook-Packs (npm/Archive)
Hook-Packs sind Standard-npm-Packages, die einen oder mehrere Hooks über openclaw.hooks in der
package.json exportieren. Installiere sie mit:
openclaw hooks install <path-or-spec>
Beispiel package.json:
{
"name": "@acme/my-hooks",
"version": "0.1.0",
"openclaw": {
"hooks": ["./hooks/my-hook", "./hooks/other-hook"]
}
}
Jeder Eintrag zeigt auf ein Hook-Verzeichnis mit HOOK.md und handler.ts (oder index.ts).
Hook-Packs können Dependencies mitbringen; sie werden unter ~/.openclaw/hooks/<id> installiert.
Hook-Struktur
HOOK.md-Format
Die HOOK.md-Datei enthält Metadaten im YAML-Frontmatter plus Markdown-Dokumentation:
---
name: my-hook
description: "Kurze Beschreibung, was dieser Hook macht"
homepage: https://docs.openclaw.ai/hooks#my-hook
metadata:
{ "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } }
---
# My Hook
Detaillierte Dokumentation kommt hier hin...
## Was er macht
- Hört auf `/new`-Befehle
- Führt eine Aktion aus
- Loggt das Ergebnis
## Anforderungen
- Node.js muss installiert sein
## Konfiguration
Keine Konfiguration nötig.
Metadaten-Felder
Das metadata.openclaw-Objekt unterstützt:
emoji: Display-Emoji für CLI (z. B."💾")events: Array von Events, auf die gehört werden soll (z. B.["command:new", "command:reset"])export: Named Export, der verwendet werden soll (Standard:"default")homepage: Dokumentations-URLrequires: Optionale Anforderungenbins: Erforderliche Binaries im PATH (z. B.["git", "node"])anyBins: Mindestens eine dieser Binaries muss vorhanden seinenv: Erforderliche Umgebungsvariablenconfig: Erforderliche Config-Pfade (z. B.["workspace.dir"])os: Erforderliche Plattformen (z. B.["darwin", "linux"])
always: Eligibility-Checks umgehen (boolean)install: Installationsmethoden (für Bundled Hooks:[{"id":"bundled","kind":"bundled"}])
Handler-Implementierung
Die handler.ts-Datei exportiert eine HookHandler-Funktion:
import type { HookHandler } from "../../src/hooks/hooks.js";
const myHandler: HookHandler = async (event) => {
// Nur bei 'new'-Befehl auslösen
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log(`[my-hook] New-Befehl ausgelöst`);
console.log(` Session: ${event.sessionKey}`);
console.log(` Timestamp: ${event.timestamp.toISOString()}`);
// Deine eigene Logik hier
// Optional Nachricht an User senden
event.messages.push("✨ Mein Hook wurde ausgeführt!");
};
export default myHandler;
Event-Context
Jedes Event enthält:
{
type: 'command' | 'session' | 'agent' | 'gateway',
action: string, // z. B. 'new', 'reset', 'stop'
sessionKey: string, // Session-Identifier
timestamp: Date, // Wann das Event aufgetreten ist
messages: string[], // Pushe Nachrichten hierhin, um sie an User zu senden
context: {
sessionEntry?: SessionEntry,
sessionId?: string,
sessionFile?: string,
commandSource?: string, // z. B. 'whatsapp', 'telegram'
senderId?: string,
workspaceDir?: string,
bootstrapFiles?: WorkspaceBootstrapFile[],
cfg?: OpenClawConfig
}
}
Event-Typen
Command-Events
Werden ausgelöst, wenn Agent-Befehle ausgegeben werden:
command: Alle Command-Events (allgemeiner Listener)command:new: Wenn/new-Befehl ausgegeben wirdcommand:reset: Wenn/reset-Befehl ausgegeben wirdcommand:stop: Wenn/stop-Befehl ausgegeben wird
Agent-Events
agent:bootstrap: Bevor Workspace-Bootstrap-Dateien injiziert werden (Hooks könnencontext.bootstrapFilesmutieren)
Gateway-Events
Werden ausgelöst, wenn das Gateway startet:
gateway:startup: Nachdem Channels gestartet und Hooks geladen wurden
Tool-Result-Hooks (Plugin-API)
Diese Hooks sind keine Event-Stream-Listener; sie ermöglichen Plugins, Tool-Results synchron anzupassen, bevor OpenClaw sie persistiert.
tool_result_persist: transformiert Tool-Results, bevor sie ins Session-Transcript geschrieben werden. Muss synchron sein; gib das aktualisierte Tool-Result-Payload zurück oderundefined, um es unverändert zu lassen. Siehe Agent Loop.
Zukünftige Events
Geplante Event-Typen:
session:start: Wenn eine neue Session beginntsession:end: Wenn eine Session endetagent:error: Wenn ein Agent auf einen Fehler stößtmessage:sent: Wenn eine Nachricht gesendet wirdmessage:received: Wenn eine Nachricht empfangen wird
Eigene Hooks erstellen
1. Ort wählen
- Workspace-Hooks (
<workspace>/hooks/): Pro Agent, höchste Priorität - Managed Hooks (
~/.openclaw/hooks/): Workspace-übergreifend
2. Verzeichnisstruktur erstellen
mkdir -p ~/.openclaw/hooks/my-hook
cd ~/.openclaw/hooks/my-hook
3. HOOK.md erstellen
---
name: my-hook
description: "Macht etwas Nützliches"
metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
---
# My Custom Hook
Dieser Hook macht etwas Nützliches, wenn du `/new` ausführst.
4. handler.ts erstellen
import type { HookHandler } from "../../src/hooks/hooks.js";
const handler: HookHandler = async (event) => {
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log("[my-hook] Läuft!");
// Deine Logik hier
};
export default handler;
5. Aktivieren und testen
# Prüfe, ob Hook erkannt wurde
openclaw hooks list
# Aktiviere ihn
openclaw hooks enable my-hook
# Starte deinen Gateway-Prozess neu (Menüleisten-App-Neustart auf macOS oder dev-Prozess neu starten)
# Löse das Event aus
# Sende /new über deinen Messaging-Channel
Konfiguration
Neues Config-Format (empfohlen)
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"session-memory": { "enabled": true },
"command-logger": { "enabled": false }
}
}
}
}
Pro-Hook-Konfiguration
Hooks können eigene Konfiguration haben:
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"my-hook": {
"enabled": true,
"env": {
"MY_CUSTOM_VAR": "value"
}
}
}
}
}
}
Extra-Verzeichnisse
Lade Hooks aus zusätzlichen Verzeichnissen:
{
"hooks": {
"internal": {
"enabled": true,
"load": {
"extraDirs": ["/path/to/more/hooks"]
}
}
}
}
Legacy-Config-Format (weiterhin unterstützt)
Das alte Config-Format funktioniert noch aus Gründen der Abwärtskompatibilität:
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts",
"export": "default"
}
]
}
}
}
Migration: Nutze das neue Discovery-basierte System für neue Hooks. Legacy-Handler werden nach verzeichnisbasierten Hooks geladen.
CLI-Befehle
Hooks auflisten
# Alle Hooks auflisten
openclaw hooks list
# Nur geeignete Hooks anzeigen
openclaw hooks list --eligible
# Verbose-Output (fehlende Anforderungen anzeigen)
openclaw hooks list --verbose
# JSON-Output
openclaw hooks list --json
Hook-Informationen
# Detaillierte Infos über einen Hook anzeigen
openclaw hooks info session-memory
# JSON-Output
openclaw hooks info session-memory --json
Eligibility prüfen
# Eligibility-Zusammenfassung anzeigen
openclaw hooks check
# JSON-Output
openclaw hooks check --json
Aktivieren/Deaktivieren
# Hook aktivieren
openclaw hooks enable session-memory
# Hook deaktivieren
openclaw hooks disable command-logger
Mitgelieferte Hooks
session-memory
Speichert Session-Context in Memory, wenn du /new ausführst.
Events: command:new
Anforderungen: workspace.dir muss konfiguriert sein
Output: <workspace>/memory/YYYY-MM-DD-slug.md (Standard: ~/.openclaw/workspace)
Was er macht:
- Nutzt den Pre-Reset-Session-Entry, um das korrekte Transcript zu finden
- Extrahiert die letzten 15 Zeilen der Konversation
- Nutzt LLM, um einen beschreibenden Dateinamen-Slug zu generieren
- Speichert Session-Metadaten in eine datierte Memory-Datei
Beispiel-Output:
# Session: 16.01.2026 14:30:00 UTC
- **Session Key**: agent:main:main
- **Session ID**: abc123def456
- **Source**: telegram
Dateinamen-Beispiele:
2026-01-16-vendor-pitch.md2026-01-16-api-design.md2026-01-16-1430.md(Fallback-Timestamp, wenn Slug-Generierung fehlschlägt)
Aktivieren:
openclaw hooks enable session-memory
command-logger
Loggt alle Command-Events in eine zentrale Audit-Datei.
Events: command
Anforderungen: Keine
Output: ~/.openclaw/logs/commands.log
Was er macht:
- Erfasst Event-Details (Command-Action, Timestamp, Session-Key, Sender-ID, Source)
- Hängt an Log-Datei im JSONL-Format an
- Läuft still im Hintergrund
Beispiel-Log-Einträge:
{"timestamp":"2026-01-16T14:30:00.000Z","action":"new","sessionKey":"agent:main:main","senderId":"+1234567890","source":"telegram"}
{"timestamp":"2026-01-16T15:45:22.000Z","action":"stop","sessionKey":"agent:main:main","senderId":"[email protected]","source":"whatsapp"}
Logs ansehen:
# Letzte Befehle ansehen
tail -n 20 ~/.openclaw/logs/commands.log
# Pretty-Print mit jq
cat ~/.openclaw/logs/commands.log | jq .
# Nach Action filtern
grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .
Aktivieren:
openclaw hooks enable command-logger
soul-evil
Tauscht injizierten SOUL.md-Content mit SOUL_EVIL.md während eines Purge-Fensters oder zufällig aus.
Events: agent:bootstrap
Docs: SOUL Evil Hook
Output: Keine Dateien geschrieben; Swaps passieren nur im Speicher.
Aktivieren:
openclaw hooks enable soul-evil
Config:
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"soul-evil": {
"enabled": true,
"file": "SOUL_EVIL.md",
"chance": 0.1,
"purge": { "at": "21:00", "duration": "15m" }
}
}
}
}
}
boot-md
Führt BOOT.md aus, wenn das Gateway startet (nachdem Channels gestartet wurden).
Interne Hooks müssen aktiviert sein, damit dies läuft.
Events: gateway:startup
Anforderungen: workspace.dir muss konfiguriert sein
Was er macht:
- Liest
BOOT.mdaus deinem Workspace - Führt die Anweisungen über den Agent-Runner aus
- Sendet alle angeforderten ausgehenden Nachrichten über das Message-Tool
Aktivieren:
openclaw hooks enable boot-md
Best Practices
Handler schnell halten
Hooks laufen während der Command-Verarbeitung. Halte sie leichtgewichtig:
// ✓ Gut - async work, kehrt sofort zurück
const handler: HookHandler = async (event) => {
void processInBackground(event); // Fire and forget
};
// ✗ Schlecht - blockiert Command-Verarbeitung
const handler: HookHandler = async (event) => {
await slowDatabaseQuery(event);
await evenSlowerAPICall(event);
};
Fehler elegant behandeln
Wickle riskante Operationen immer ein:
const handler: HookHandler = async (event) => {
try {
await riskyOperation(event);
} catch (err) {
console.error("[my-handler] Fehlgeschlagen:", err instanceof Error ? err.message : String(err));
// Nicht werfen - lass andere Handler laufen
}
};
Events früh filtern
Kehre früh zurück, wenn das Event nicht relevant ist:
const handler: HookHandler = async (event) => {
// Nur 'new'-Befehle behandeln
if (event.type !== "command" || event.action !== "new") {
return;
}
// Deine Logik hier
};
Spezifische Event-Keys verwenden
Gib wenn möglich exakte Events in Metadaten an:
metadata: { "openclaw": { "events": ["command:new"] } } # Spezifisch
Statt:
metadata: { "openclaw": { "events": ["command"] } } # Allgemein - mehr Overhead
Debugging
Hook-Logging aktivieren
Das Gateway loggt Hook-Loading beim Start:
Registered hook: session-memory -> command:new
Registered hook: command-logger -> command
Registered hook: boot-md -> gateway:startup
Discovery prüfen
Liste alle erkannten Hooks auf:
openclaw hooks list --verbose
Registrierung prüfen
Logge in deinem Handler, wenn er aufgerufen wird:
const handler: HookHandler = async (event) => {
console.log("[my-handler] Ausgelöst:", event.type, event.action);
// Deine Logik
};
Eligibility verifizieren
Prüfe, warum ein Hook nicht geeignet ist:
openclaw hooks info my-hook
Schau nach fehlenden Anforderungen im Output.
Testing
Gateway-Logs
Überwache Gateway-Logs, um Hook-Ausführung zu sehen:
# macOS
./scripts/clawlog.sh -f
# Andere Plattformen
tail -f ~/.openclaw/gateway.log
Hooks direkt testen
Teste deine Handler isoliert:
import { test } from "vitest";
import { createHookEvent } from "./src/hooks/hooks.js";
import myHandler from "./hooks/my-hook/handler.js";
test("my handler works", async () => {
const event = createHookEvent("command", "new", "test-session", {
foo: "bar",
});
await myHandler(event);
// Assert side effects
});
Architektur
Core-Komponenten
src/hooks/types.ts: Typdefinitionensrc/hooks/workspace.ts: Verzeichnis-Scanning und Loadingsrc/hooks/frontmatter.ts: HOOK.md-Metadaten-Parsingsrc/hooks/config.ts: Eligibility-Checkingsrc/hooks/hooks-status.ts: Status-Reportingsrc/hooks/loader.ts: Dynamischer Modul-Loadersrc/cli/hooks-cli.ts: CLI-Befehlesrc/gateway/server-startup.ts: Lädt Hooks beim Gateway-Startsrc/auto-reply/reply/commands-core.ts: Löst Command-Events aus
Discovery-Flow
Gateway-Start
↓
Verzeichnisse scannen (workspace → managed → bundled)
↓
HOOK.md-Dateien parsen
↓
Eligibility prüfen (bins, env, config, os)
↓
Handler von geeigneten Hooks laden
↓
Handler für Events registrieren
Event-Flow
User sendet /new
↓
Command-Validierung
↓
Hook-Event erstellen
↓
Hook auslösen (alle registrierten Handler)
↓
Command-Verarbeitung geht weiter
↓
Session-Reset
Troubleshooting
Hook nicht erkannt
-
Prüfe Verzeichnisstruktur:
ls -la ~/.openclaw/hooks/my-hook/ # Sollte zeigen: HOOK.md, handler.ts -
Verifiziere HOOK.md-Format:
cat ~/.openclaw/hooks/my-hook/HOOK.md # Sollte YAML-Frontmatter mit name und metadata haben -
Liste alle erkannten Hooks auf:
openclaw hooks list
Hook nicht geeignet
Prüfe Anforderungen:
openclaw hooks info my-hook
Schau nach fehlenden:
- Binaries (prüfe PATH)
- Umgebungsvariablen
- Config-Werten
- OS-Kompatibilität
Hook wird nicht ausgeführt
-
Verifiziere, dass Hook aktiviert ist:
openclaw hooks list # Sollte ✓ neben aktivierten Hooks zeigen -
Starte deinen Gateway-Prozess neu, damit Hooks neu geladen werden.
-
Prüfe Gateway-Logs auf Fehler:
./scripts/clawlog.sh | grep hook
Handler-Fehler
Prüfe auf TypeScript/Import-Fehler:
# Import direkt testen
node -e "import('./path/to/handler.ts').then(console.log)"
Migrations-Guide
Von Legacy-Config zu Discovery
Vorher:
{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts"
}
]
}
}
}
Nachher:
-
Hook-Verzeichnis erstellen:
mkdir -p ~/.openclaw/hooks/my-hook mv ./hooks/handlers/my-handler.ts ~/.openclaw/hooks/my-hook/handler.ts -
HOOK.md erstellen:
--- name: my-hook description: "Mein eigener Hook" metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } } --- # My Hook Macht etwas Nützliches. -
Config aktualisieren:
{ "hooks": { "internal": { "enabled": true, "entries": { "my-hook": { "enabled": true } } } } } -
Verifizieren und Gateway-Prozess neu starten:
openclaw hooks list # Sollte zeigen: 🎯 my-hook ✓
Vorteile der Migration:
- Automatische Discovery
- CLI-Management
- Eligibility-Checking
- Bessere Dokumentation
- Konsistente Struktur