Skip to content

Read this in other languages: English, 简体中文.

Event Hooks Architecture

Overview

The Event Hooks system provides a plugin-based architecture for reacting to events in HotPlex. It enables:

  • Audit Logging: Record all session events for compliance
  • Notifications: Send alerts to Slack, Feishu, DingTalk
  • Webhooks: Forward events to external services
  • Custom Logic: Implement custom reactions to events

Architecture

┌─────────────────────────────────────────────────────────────┐
│                      HotPlex Engine                          │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐        │
│  │ Session │  │  Tool   │  │ Danger  │  │ Stream  │        │
│  │  Pool   │  │  Use    │  │   WAF   │  │  I/O    │        │
│  └────┬────┘  └────┬────┘  └────┬────┘  └────┬────┘        │
│       │            │            │            │              │
│       └────────────┴────────────┴────────────┘              │
│                          │                                   │
│                          ▼                                   │
│               ┌──────────────────┐                          │
│               │   Hook Manager    │                          │
│               │                  │                          │
│               │  ┌────────────┐  │                          │
│               │  │ Event Chan │  │                          │
│               │  │ (buffered) │  │                          │
│               │  └─────┬──────┘  │                          │
│               │        │         │                          │
│               │        ▼         │                          │
│               │  ┌────────────┐  │                          │
│               │  │ Event Loop │  │                          │
│               │  └─────┬──────┘  │                          │
│               └────────┼─────────┘                          │
│                        │                                     │
└────────────────────────┼─────────────────────────────────────┘

          ┌──────────────┼──────────────┐
          │              │              │
          ▼              ▼              ▼
    ┌──────────┐  ┌──────────┐  ┌──────────┐
    │ Webhook  │  │ Logging  │  │ Slack    │
    │  Hook    │  │  Hook    │  │  Hook    │
    └──────────┘  └──────────┘  └──────────┘

Event Types

EventDescriptionWhen Fired
session.startSession createdNew CLI process started
session.endSession terminatedProcess cleanup
session.errorSession errorUnrecoverable error
tool.useTool invokedAgent uses Bash, Edit, etc.
tool.resultTool completedTool execution finished
danger.blockedSecurity blockWAF blocked dangerous command
stream.startStream begunFirst token received
stream.endStream finishedTurn completed
turn.startTurn begunUser prompt received
turn.endTurn completedAI response finished

Hook Interface

go
type Hook interface {
    Name() string
    Handle(ctx context.Context, event *Event) error
    Events() []EventType
}

Usage

Basic Hook Registration

go
import "github.com/hrygo/hotplex/hooks"

mgr := hooks.NewManager(logger, 1000)
defer mgr.Close()

loggingHook := hooks.NewLoggingHook("audit-log", logger, nil)
mgr.Register(loggingHook, hooks.HookConfig{
    Enabled: true,
    Async:   true,
})

Webhook Hook

go
webhook := hooks.NewWebhookHook("slack-webhook", hooks.WebhookConfig{
    URL:     "https://hooks.slack.com/services/xxx",
    Secret:  "your-signing-secret",
    Timeout: 5 * time.Second,
    FilterEvents: []hooks.EventType{
        hooks.EventDangerBlocked,
        hooks.EventSessionError,
    },
}, logger)

mgr.Register(webhook, hooks.HookConfig{
    Enabled: true,
    Async:   true,
    Retry:   3,
})

Custom Hook

go
type MetricsHook struct{}

func (h *MetricsHook) Name() string { return "metrics" }
func (h *MetricsHook) Events() []hooks.EventType {
    return []hooks.EventType{hooks.EventTurnEnd}
}
func (h *MetricsHook) Handle(ctx context.Context, event *hooks.Event) error {
    metrics.RecordTurn(event.SessionID)
    return nil
}

Event Flow

  1. Event Source (Engine, Session, WAF) creates an Event
  2. Hook Manager receives event via Emit() or EmitSync()
  3. Event Loop processes events from buffered channel
  4. Registered Hooks are invoked for matching event types
  5. Async Hooks run in goroutines, don't block main flow
  6. Sync Hooks block until completion (for critical events)

Configuration

HookConfig

FieldTypeDefaultDescription
EnabledbooltrueWhether hook is active
AsyncboolfalseRun in goroutine
TimeoutDuration5sPer-hook timeout
Retryint0Retry attempts on failure

Manager Options

OptionDefaultDescription
bufferSize1000Event channel buffer size
loggerslog.Default()Logger for hook events

Thread Safety

  • Hook Manager is thread-safe via sync.RWMutex
  • Hooks can be registered/unregistered at runtime
  • Event emission is non-blocking (drops if buffer full)
  • Each hook execution is isolated

Error Handling

  • Failed hooks are logged with retry attempts
  • Errors don't propagate to caller (fire-and-forget)
  • Retry uses exponential backoff: 100ms * attempt

Performance

  • Event emission: O(1) channel send
  • Hook lookup: O(n) where n = hooks for event type
  • Memory: ~200 bytes per event
  • No blocking on main execution path (async mode)

Future Extensions

  • Persistent Hooks: Store hook configs in database
  • Hook Chaining: Chain multiple hooks with ordering
  • Rate Limiting: Per-hook rate limits
  • Circuit Breaker: Disable failing hooks automatically

Released under the MIT License.