Aller au contenu

Hooks

Les hooks fournissent un système événementiel extensible pour automatiser les actions en réponse aux commandes et événements de l’agent. Les hooks sont découverts automatiquement à partir des répertoires et peuvent être gérés via les commandes CLI, de manière similaire au fonctionnement des compétences dans OpenClaw.

Les hooks sont de petits scripts qui s’exécutent lorsqu’un événement se produit. Il en existe deux types :

  • Hooks (cette page) : s’exécutent à l’intérieur du Gateway lorsque des événements d’agent se déclenchent, comme /new, /reset, /stop, ou des événements de cycle de vie.
  • Webhooks : webhooks HTTP externes qui permettent à d’autres systèmes de déclencher des travaux dans OpenClaw. Voir Webhook Hooks ou utilisez openclaw webhooks pour les commandes d’aide Gmail.

Les hooks peuvent également être regroupés dans des plugins ; voir Plugins.

Cas d’usage courants :

  • Enregistrer un instantané de la mémoire lorsque vous réinitialisez une session
  • Garder une trace d’audit des commandes pour le dépannage ou la conformité
  • Déclencher une automatisation de suivi lorsqu’une session commence ou se termine
  • Écrire des fichiers dans l’espace de travail de l’agent ou appeler des API externes lorsque des événements se déclenchent

Si vous savez écrire une petite fonction TypeScript, vous pouvez écrire un hook. Les hooks sont découverts automatiquement et vous les activez ou désactivez via le CLI.

Le système de hooks vous permet de :

  • Sauvegarder le contexte de la session en mémoire lorsque /new est émis
  • Enregistrer toutes les commandes pour l’audit
  • Déclencher des automations personnalisées sur les événements du cycle de vie de l’agent
  • Étendre le comportement de OpenClaw sans modifier le code principal

OpenClaw est fourni avec quatre hooks inclus qui sont découverts automatiquement :

  • 💾 session-memory : Enregistre le contexte de la session dans votre espace de travail de l’agent (par défaut ~/.openclaw/workspace/memory/) lorsque vous émettez /new
  • 📝 command-logger : Enregistre tous les événements de commande dans ~/.openclaw/logs/commands.log
  • 🚀 boot-md : Exécute BOOT.md au démarrage de la passerelle (nécessite l’activation des hooks internes)
  • 😈 soul-evil : Remplace le contenu SOUL.md injecté par SOUL_EVIL.md pendant une fenêtre de purge ou par hasard

Lister les hooks disponibles :

Fenêtre de terminal
openclaw hooks list

Activer un hook :

Fenêtre de terminal
openclaw hooks enable session-memory

Vérifier l’état du hook :

Fenêtre de terminal
openclaw hooks check

Obtenir des informations détaillées :

Fenêtre de terminal
openclaw hooks info session-memory

Pendant l’onboarding (openclaw onboard), vous serez invité à activer les hooks recommandés. L’assistant détecte automatiquement les hooks éligibles et les présente pour sélection.

Les hooks sont automatiquement découverts dans trois répertoires (par ordre de priorité) :

  1. Hooks de l’espace de travail : <workspace>/hooks/ (par agent, priorité la plus élevée)
  2. Hooks gérés : ~/.openclaw/hooks/ (installés par l’utilisateur, partagés entre les espaces de travail)
  3. Hooks intégrés : <openclaw>/dist/hooks/bundled/ (fournis avec OpenClaw)

Les répertoires de hooks gérés peuvent contenir soit un hook unique soit un pack de hooks (répertoire de package).

Chaque hook est un répertoire contenant :

my-hook/
├── HOOK.md # Metadata + documentation
└── handler.ts # Handler implementation

Les packs de hooks sont des packages npm standard qui exportent un ou plusieurs hooks via openclaw.hooks dans package.json. Installez-les avec :

Fenêtre de terminal
openclaw hooks install <path-or-spec>

Exemple package.json :

{
"name": "@acme/my-hooks",
"version": "0.1.0",
"openclaw": {
"hooks": ["./hooks/my-hook", "./hooks/other-hook"]
}
}

Chaque entrée pointe vers un répertoire de hook contenant HOOK.md et handler.ts (ou index.ts). Les packs de hooks peuvent inclure des dépendances ; elles seront installées sous ~/.openclaw/hooks/<id>.

Le fichier HOOK.md contient des métadonnées dans le frontmatter YAML ainsi que de la documentation Markdown :

---
name: my-hook
description: "Short description of what this hook does"
homepage: https://docs.openclaw.ai/hooks#my-hook
metadata: { "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } }
---
# My Hook
Detailed documentation goes here...
## What It Does
- Listens for `/new` commands
- Performs some action
- Logs the result
## Requirements
- Node.js must be installed
## Configuration
No configuration needed.

L’objet metadata.openclaw prend en charge :

  • emoji : Emoji d’affichage pour la CLI (par exemple, "💾")
  • events : Tableau des événements à écouter (par exemple, ["command:new", "command:reset"])
  • export : Export nommé à utiliser (par défaut "default")
  • homepage : URL de la documentation
  • requires : Prérequis facultatifs
    • bins : Binaires requis dans le PATH (ex. : ["git", "node"])
    • anyBins : Au moins l’un de ces binaires doit être présent
    • env : Variables d’environnement requises
    • config : Chemins de configuration requis (ex. : ["workspace.dir"])
    • os : Plateformes requises (ex. : ["darwin", "linux"])
  • always : Contourner les vérifications d’éligibilité (booléen)
  • install : Méthodes d’installation (pour les hooks groupés : [{"id":"bundled","kind":"bundled"}])

Le fichier handler.ts exporte une fonction HookHandler :

import type { HookHandler } from "../../src/hooks/hooks.js";
const myHandler: HookHandler = async (event) => {
// Only trigger on 'new' command
if (event.type !== "command" || event.action !== "new") {
return;
}
console.log(`[my-hook] New command triggered`);
console.log(` Session: ${event.sessionKey}`);
console.log(` Timestamp: ${event.timestamp.toISOString()}`);
// Your custom logic here
// Optionally send message to user
event.messages.push("✨ My hook executed!");
};
export default myHandler;

Chaque événement inclut :

{
type: 'command' | 'session' | 'agent' | 'gateway',
action: string, // e.g., 'new', 'reset', 'stop'
sessionKey: string, // Session identifier
timestamp: Date, // When the event occurred
messages: string[], // Push messages here to send to user
context: {
sessionEntry?: SessionEntry,
sessionId?: string,
sessionFile?: string,
commandSource?: string, // e.g., 'whatsapp', 'telegram'
senderId?: string,
workspaceDir?: string,
bootstrapFiles?: WorkspaceBootstrapFile[],
cfg?: OpenClawConfig
}
}

Déclenchés lorsque des commandes d’agent sont émises :

  • command : Tous les événements de commande (écouteur général)
  • command:new : Lorsque la commande /new est émise
  • command:reset : Lorsque la commande /reset est émise
  • command:stop : Lorsque la commande /stop est émise
  • agent:bootstrap : Avant l’injection des fichiers d’amorçage de l’espace de travail (les hooks peuvent modifier context.bootstrapFiles)

Déclenchés au démarrage de la passerelle :

  • gateway:startup : Après le démarrage des canaux et le chargement des hooks

Ces hooks ne sont pas des écouteurs de flux d’événements ; ils permettent aux plugins d’ajuster de manière synchrone les résultats des outils avant que OpenClaw ne les persiste.

  • tool_result_persist: transformer les résultats des outils avant qu’ils ne soient écrits dans la transcription de session. Doit être synchrone ; renvoyer la charge utile du résultat de l’outil mise à jour ou undefined pour la laisser telle quelle. Voir Agent Loop.

Types d’événements prévus :

  • session:start: Lorsqu’une nouvelle session commence
  • session:end: Lorsqu’une session se termine
  • agent:error: Lorsqu’un agent rencontre une erreur
  • message:sent: Lorsqu’un message est envoyé
  • message:received: Lorsqu’un message est reçu
  • Hooks de l’espace de travail (<workspace>/hooks/) : Par agent, priorité la plus élevée
  • Hooks gérés (~/.openclaw/hooks/) : Partagés entre les espaces de travail
Fenêtre de terminal
mkdir -p ~/.openclaw/hooks/my-hook
cd ~/.openclaw/hooks/my-hook
---
name: my-hook
description: "Does something useful"
metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
---
# My Custom Hook
This hook does something useful when you issue `/new`.
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] Running!");
// Your logic here
};
export default handler;
Fenêtre de terminal
# Verify hook is discovered
openclaw hooks list
# Enable it
openclaw hooks enable my-hook
# Restart your gateway process (menu bar app restart on macOS, or restart your dev process)
# Trigger the event
# Send /new via your messaging channel
{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"session-memory": { "enabled": true },
"command-logger": { "enabled": false }
}
}
}
}

Les hooks peuvent avoir une configuration personnalisée :

{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"my-hook": {
"enabled": true,
"env": {
"MY_CUSTOM_VAR": "value"
}
}
}
}
}
}

Charger les hooks à partir de répertoires supplémentaires :

{
"hooks": {
"internal": {
"enabled": true,
"load": {
"extraDirs": ["/path/to/more/hooks"]
}
}
}
}

Format de configuration hérité (Toujours pris en charge)

Section intitulée « Format de configuration hérité (Toujours pris en charge) »

L’ancien format de configuration fonctionne toujours pour la compatibilité descendante :

{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts",
"export": "default"
}
]
}
}
}

Migration : Utilisez le nouveau système basé sur la découverte pour les nouveaux hooks. Les gestionnaires hérités sont chargés après les hooks basés sur les répertoires.

Fenêtre de terminal
# List all hooks
openclaw hooks list
# Show only eligible hooks
openclaw hooks list --eligible
# Verbose output (show missing requirements)
openclaw hooks list --verbose
# JSON output
openclaw hooks list --json
Fenêtre de terminal
# Show detailed info about a hook
openclaw hooks info session-memory
# JSON output
openclaw hooks info session-memory --json
Fenêtre de terminal
# Show eligibility summary
openclaw hooks check
# JSON output
openclaw hooks check --json
Fenêtre de terminal
# Enable a hook
openclaw hooks enable session-memory
# Disable a hook
openclaw hooks disable command-logger

Enregistre le contexte de la session dans la mémoire lorsque vous émettez /new.

Événements : command:new

Conditions requises : workspace.dir doit être configuré

Sortie : <workspace>/memory/YYYY-MM-DD-slug.md (par défaut ~/.openclaw/workspace)

Ce qu’il fait :

  1. Utilise l’entrée de session pré-réinitialisée pour localiser la transcription correcte
  2. Extrait les 15 dernières lignes de la conversation
  3. Utilise LLM pour générer un slug de nom de fichier descriptif
  4. Enregistre les métadonnées de la session dans un fichier de mémoire daté

Exemple de sortie :

# Session: 2026-01-16 14:30:00 UTC
- **Session Key**: agent:main:main
- **Session ID**: abc123def456
- **Source**: telegram

Exemples de noms de fichiers :

  • 2026-01-16-vendor-pitch.md
  • 2026-01-16-api-design.md
  • 2026-01-16-1430.md (horodatage de secours si la génération de slug échoue)

Activer :

Fenêtre de terminal
openclaw hooks enable session-memory

Enregistre tous les événements de commande dans un fichier d’audit centralisé.

Événements : command

Conditions requises : Aucune

Sortie : ~/.openclaw/logs/commands.log

Ce qu’il fait :

  1. Capture les détails de l’événement (action de commande, horodatage, clé de session, ID de l’expéditeur, source)
  2. Ajoute au fichier journal au format JSONL
  3. S’exécute en silence en arrière-plan

Exemples d’entrées de journal :

{"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"}

Voir les journaux :

Fenêtre de terminal
# View recent commands
tail -n 20 ~/.openclaw/logs/commands.log
# Pretty-print with jq
cat ~/.openclaw/logs/commands.log | jq .
# Filter by action
grep '"action":"new"' ~/.openclaw/logs/commands.log | jq .

Activer :

Fenêtre de terminal
openclaw hooks enable command-logger

Échange le contenu SOUL.md injecté avec SOUL_EVIL.md pendant une fenêtre de purge ou par hasard.

Événements : agent:bootstrap

Documentation : SOUL Evil Hook

Sortie : Aucun fichier écrit ; les échanges se produisent uniquement en mémoire.

Activer :

Fenêtre de terminal
openclaw hooks enable soul-evil

Configuration :

{
"hooks": {
"internal": {
"enabled": true,
"entries": {
"soul-evil": {
"enabled": true,
"file": "SOUL_EVIL.md",
"chance": 0.1,
"purge": { "at": "21:00", "duration": "15m" }
}
}
}
}
}

Exécute BOOT.md lorsque la passerelle démarre (après le démarrage des canaux). Les hooks internes doivent être activés pour que cela s’exécute.

Événements : gateway:startup

Conditions requises : workspace.dir doit être configuré

Ce qu’il fait :

  1. Lit BOOT.md depuis votre espace de travail
  2. Exécute les instructions via l’exécuteur d’agent
  3. Envoie tous les messages sortants demandés via l’outil de message

Activer :

Fenêtre de terminal
openclaw hooks enable boot-md

Les hooks s’exécutent pendant le traitement des commandes. Gardez-les légers :

// ✓ Good - async work, returns immediately
const handler: HookHandler = async (event) => {
void processInBackground(event); // Fire and forget
};
// ✗ Bad - blocks command processing
const handler: HookHandler = async (event) => {
await slowDatabaseQuery(event);
await evenSlowerAPICall(event);
};

Enveloppez toujours les opérations risquées :

const handler: HookHandler = async (event) => {
try {
await riskyOperation(event);
} catch (err) {
console.error("[my-handler] Failed:", err instanceof Error ? err.message : String(err));
// Don't throw - let other handlers run
}
};

Retournez tôt si l’événement n’est pas pertinent :

const handler: HookHandler = async (event) => {
// Only handle 'new' commands
if (event.type !== "command" || event.action !== "new") {
return;
}
// Your logic here
};

Spécifiez les événements exacts dans les métadonnées lorsque cela est possible :

metadata: { "openclaw": { "events": ["command:new"] } } # Specific

Plutôt que :

metadata: { "openclaw": { "events": ["command"] } } # General - more overhead

La passerelle enregistre le chargement des hooks au démarrage :

Registered hook: session-memory -> command:new
Registered hook: command-logger -> command
Registered hook: boot-md -> gateway:startup

Lister tous les hooks découverts :

Fenêtre de terminal
openclaw hooks list --verbose

Dans votre gestionnaire, enregistrez quand il est appelé :

const handler: HookHandler = async (event) => {
console.log("[my-handler] Triggered:", event.type, event.action);
// Your logic
};

Vérifiez pourquoi un hook n’est pas éligible :

Fenêtre de terminal
openclaw hooks info my-hook

Recherchez les conditions requises manquantes dans la sortie.

Surveillez les journaux de la passerelle pour voir l’exécution des hooks :

Fenêtre de terminal
# macOS
./scripts/clawlog.sh -f
# Other platforms
tail -f ~/.openclaw/gateway.log

Test your handlers in isolation:

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
});
  • src/hooks/types.ts: Type definitions
  • src/hooks/workspace.ts: Directory scanning and loading
  • src/hooks/frontmatter.ts: HOOK.md metadata parsing
  • src/hooks/config.ts: Eligibility checking
  • src/hooks/hooks-status.ts: Status reporting
  • src/hooks/loader.ts: Dynamic module loader
  • src/cli/hooks-cli.ts: CLI commands
  • src/gateway/server-startup.ts: Loads hooks at gateway start
  • src/auto-reply/reply/commands-core.ts: Triggers command events
Gateway startup
Scan directories (workspace → managed → bundled)
Parse HOOK.md files
Check eligibility (bins, env, config, os)
Load handlers from eligible hooks
Register handlers for events
User sends /new
Command validation
Create hook event
Trigger hook (all registered handlers)
Command processing continues
Session reset
  1. Check directory structure:

    Fenêtre de terminal
    ls -la ~/.openclaw/hooks/my-hook/
    # Should show: HOOK.md, handler.ts
  2. Verify HOOK.md format:

    Fenêtre de terminal
    cat ~/.openclaw/hooks/my-hook/HOOK.md
    # Should have YAML frontmatter with name and metadata
  3. List all discovered hooks:

    Fenêtre de terminal
    openclaw hooks list

Check requirements:

Fenêtre de terminal
openclaw hooks info my-hook

Look for missing:

  • Binaries (check PATH)
  • Environment variables
  • Config values
  • OS compatibility
  1. Verify hook is enabled:

    Fenêtre de terminal
    openclaw hooks list
    # Should show ✓ next to enabled hooks
  2. Restart your gateway process so hooks reload.

  3. Check gateway logs for errors:

    Fenêtre de terminal
    ./scripts/clawlog.sh | grep hook

Check for TypeScript/import errors:

Fenêtre de terminal
# Test import directly
node -e "import('./path/to/handler.ts').then(console.log)"

Before:

{
"hooks": {
"internal": {
"enabled": true,
"handlers": [
{
"event": "command:new",
"module": "./hooks/handlers/my-handler.ts"
}
]
}
}
}

After:

  1. Create hook directory:

    Fenêtre de terminal
    mkdir -p ~/.openclaw/hooks/my-hook
    mv ./hooks/handlers/my-handler.ts ~/.openclaw/hooks/my-hook/handler.ts
  2. Create HOOK.md:

    ---
    name: my-hook
    description: "My custom hook"
    metadata: { "openclaw": { "emoji": "🎯", "events": ["command:new"] } }
    ---
    # My Hook
    Does something useful.
  3. Update config:

    {
    "hooks": {
    "internal": {
    "enabled": true,
    "entries": {
    "my-hook": { "enabled": true }
    }
    }
    }
    }
  4. Verify and restart your gateway process:

    Fenêtre de terminal
    openclaw hooks list
    # Should show: 🎯 my-hook ✓

Benefits of migration:

  • Automatic discovery
  • CLI management
  • Eligibility checking
  • Better documentation
  • Consistent structure