Skip to content

Hooks Mechanism

The Hooks system allows plugins to inject custom logic at key lifecycle events -- message interception, tool call wrapping, session management, audit logging, and more.

Available Hooks

Source: src/plugins/hooks.ts

Hook Reference

Hook NameTriggered WhenTypical Use
gateway-startGateway startup completeInitialize external services
gateway-stopBefore Gateway shutdownClean up resources
session-startSession beginsLoad session context
session-endSession endsSave session state
before-agent-startBefore Agent executionInject context
message-receivedUser message receivedMessage interception, filtering
message-sendingBefore sending a messageMessage modification, auditing
message-sentAfter message sent successfullyLogging
before-tool-callBefore tool executionPermission checks, argument modification
after-tool-callAfter tool executionResult processing, auditing
before-compactionBefore context compactionPreserve important information
after-compactionAfter context compactionRestore state
tool-result-persistWhen tool results are persistedData archiving

Hook Registration

typescript
// src/plugins/hooks.ts (simplified)
interface PluginHookRegistration<K extends PluginHookName> {
  event: K;                    // Hook event name
  handler: PluginHookHandler<K>;  // Handler function
  priority?: number;           // Execution priority (lower = earlier)
}

Plugins register hooks through the API:

typescript
// Example: audit logging hook
api.registerHook({
  event: "message-sent",
  handler: async (ctx) => {
    await auditLog.record({
      sessionKey: ctx.sessionKey,
      channel: ctx.channel,
      direction: ctx.direction,
      timestamp: Date.now(),
    });
  },
  priority: 100,  // Run after other hooks
});

Hook Context Types

Each hook type receives a different context:

Agent Context

typescript
interface PluginHookAgentContext {
  runId: string;           // Agent run ID
  config: AgentConfig;     // Agent configuration
  workspaceDir: string;    // Workspace directory
  agentDir: string;        // Agent directory
}

Message Context

typescript
interface PluginHookMessageContext {
  sessionKey: string;      // Session key
  channel: string;         // Source channel
  senderId: string;        // Sender identifier
  direction: "received" | "sending" | "sent";  // Message direction
}

Tool Context

typescript
interface PluginHookToolContext {
  runId: string;           // Agent run ID
  toolName: string;        // Tool being called
  // before: includes args
  // after: includes result
}

Session Context

typescript
interface PluginHookSessionContext {
  sessionKey: string;      // Session key
  channel: string;         // Channel
}

Execution Model

Key execution characteristics:

CharacteristicDescription
Parallel executionMultiple handlers for the same event run in parallel
Error isolationA single handler throwing does not affect other handlers
Priority orderingLower numbers execute first
Fire-and-forgetMost hooks do not wait for results

Gateway Hooks

Source: src/gateway/hooks.ts, src/gateway/hooks-mapping.ts

The Gateway layer has its own hooks mapping, which maps config-defined hook definitions to runtime registrations:

typescript
// src/gateway/hooks-mapping.ts (simplified)
// Maps config-defined hooks to runtime registrations
// Supports file-based hook definitions
// Validates hook event names and handler paths

Summary

  • 13 hook events cover five lifecycles: Gateway, Session, Agent, Message, and Tool
  • Hooks are sorted by priority, executed in parallel, with error isolation
  • Four context types provide event-relevant data
  • Plugins register hooks via api.registerHook(), supporting dynamic addition
  • The Gateway layer additionally supports config-file-based hook definitions

Next: CLI Overview

OpenClaw Source Code Tutorial