← Back to PRs

#12082: feat: implement plugin lifecycle interception hook architecture

by tomismeta open 2026-02-08 20:38 View on GitHub →
docs gateway extensions: lobster commands agents stale size: XL
## Origin This implementation is based on: - Proposal gist: https://gist.github.com/openmetaloom/657c4668c09d235f8da1306e2438904b - OpenClaw discussion: https://github.com/openclaw/openclaw/discussions/9872 ## Summary This PR implements a typed plugin lifecycle interception architecture and wires it to concrete runtime execution points. It includes: - lifecycle API: `api.lifecycle.on(phase, handler, options)` - raw hook API: `api.on(hookName, handler, options)` - canonical + alias phase mapping to runtime hooks - hardened runtime behavior (fail-open/fail-closed propagation, timeout handling, retries, scoping, concurrency controls) - integration wiring in gateway, dispatch/messaging, recall/memory, and tool execution flows - expanded unit/integration tests for mapping, wiring, and failure semantics ## Lifecycle APIs - `api.on("<hook_name>", handler, opts)` for raw runtime hooks - `api.lifecycle.on("<phase>", handler, opts)` for canonical phases and aliases ### Execution options Supported on both APIs: - `priority` - `timeoutMs` - `mode` (`fail-open` | `fail-closed`) - `onTimeout` (`fail-open` | `fail-closed`) - `retry` (`count`, optional `backoffMs`) - `maxConcurrency` - `scope` (`channels`, `agentIds`, `toolNames`) - `condition` ## Canonical phase -> runtime hook mapping - `boot.pre` -> `gateway_pre_start` - `boot.post` -> `gateway_start` - `shutdown.pre` -> `gateway_pre_stop` - `shutdown.post` -> `gateway_stop` - `agent.pre` -> `before_agent_start` - `agent.post` -> `agent_end` - `request.pre` -> `message_received` - `request.post` -> `request_post` - `recall.pre` -> `before_recall` - `recall.post` -> `after_recall` - `message.pre` -> `message_sending` - `message.post` -> `message_sent` - `tool.pre` -> `before_tool_call` - `tool.post` -> `after_tool_call` - `tool.error` -> `tool_error` - `response.error` -> `response_error` - `error` -> `agent_error` - `memory.compaction.pre` -> `before_compaction` - `memory.compaction.post` -> `after_compaction` ## Alias -> canonical -> runtime mapping - `preBoot` -> `boot.pre` -> `gateway_pre_start` - `postBoot` -> `boot.post` -> `gateway_start` - `preShutdown` -> `shutdown.pre` -> `gateway_pre_stop` - `postShutdown` -> `shutdown.post` -> `gateway_stop` - `preAgent` -> `agent.pre` -> `before_agent_start` - `postRequest` -> `agent.post` -> `agent_end` - `preRequest` -> `request.pre` -> `message_received` - `postRequestIngress` -> `request.post` -> `request_post` - `preRecall` -> `recall.pre` -> `before_recall` - `postRecall` -> `recall.post` -> `after_recall` - `preResponse` -> `message.pre` -> `message_sending` - `postResponse` -> `message.post` -> `message_sent` - `preToolExecution` -> `tool.pre` -> `before_tool_call` - `postToolExecution` -> `tool.post` -> `after_tool_call` - `onToolError` -> `tool.error` -> `tool_error` - `onResponseError` -> `response.error` -> `response_error` - `preCompaction` -> `memory.compaction.pre` -> `before_compaction` - `postCompaction` -> `memory.compaction.post` -> `after_compaction` - `onError` -> `error` -> `agent_error` Alias coverage is validated in code to enforce one alias per runtime hook and no overlaps. ## Runtime wiring added/verified - Gateway lifecycle: pre-start/start/pre-stop/stop - Agent lifecycle: pre-start, post-run, error - Recall lifecycle: before recall and after recall - Message lifecycle: inbound (`message_received`), post-ingress (`request_post`), pre-send (`message_sending`), post-send (`message_sent`), send-failure (`response_error`) - Tool lifecycle: before call, after call, tool error - Compaction lifecycle: pre/post compaction ## Reliability and hardening - Structured hook execution errors via `PluginHookExecutionError` - Fail-closed propagation at critical interception points - Timeout behavior configurable independently via `onTimeout` - Retry with optional backoff for transient hook failures - Per-handler concurrency limits - Scope-based gating by channel/agent/tool ## Tests and validation Locally validated with: - `pnpm lint` - `pnpm tsgo` - `pnpm canvas:a2ui:bundle && pnpm test` - `pnpm canvas:a2ui:bundle && bunx vitest run --config vitest.unit.config.ts` Both CI-equivalent test paths passed locally.

Most Similar PRs