惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
D
DataBreaches.Net
GbyAI
GbyAI
Microsoft Security Blog
Microsoft Security Blog
博客园_首页
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Engineering at Meta
Engineering at Meta
IT之家
IT之家
MongoDB | Blog
MongoDB | Blog
The GitHub Blog
The GitHub Blog
月光博客
月光博客
U
Unit 42
Hugging Face - Blog
Hugging Face - Blog
博客园 - 叶小钗
腾讯CDC
B
Blog RSS Feed
博客园 - Franky
爱范儿
爱范儿

Recent Commits to openclaw:main

test: merge chat side-result checks · openclaw/openclaw@ddd2c2a test: merge cron history checks · openclaw/openclaw@f7eb746 test: merge responsive navigation shell checks · openclaw/openclaw@c2e4b47 docs(changelog): add codex oauth fixes · openclaw/openclaw@628e6cd test: merge navigation routing cases · openclaw/openclaw@5d8cecb Tests: mock channel registry bundled fallback · openclaw/openclaw@2b08233 Secrets: avoid broad web search discovery for single plugin config · openclaw/openclaw@a464f59 test: merge config view browser checks · openclaw/openclaw@20cf511 fix(status): align oauth health with runtime · openclaw/openclaw@eed7116 feat: add macOS screen snapshots for monitor preview (#67954) thanks … · openclaw/openclaw@f377db1 fix: report shared auth scopes in hello-ok (#67810) thanks @BunsDev · openclaw/openclaw@0b6c39b Auto-reply: avoid eager bundled route fallback · openclaw/openclaw@3ea1bf4 Tests: narrow session binding contract setup · openclaw/openclaw@54e4e16 fix(macOS): enable undo/redo in webchat composer text input (#34962) · openclaw/openclaw@00951dc Tests: speed up channel setup promotion · openclaw/openclaw@82b529a Docs: refresh agent instructions · openclaw/openclaw@5775fe2 fix(auth): serialize OAuth refresh across agents to fix #26322 (#67876) · openclaw/openclaw@8e79080 test: allow ollama public surface boundary test · openclaw/openclaw@7d4f1a6 Docs: add test performance guardrails · openclaw/openclaw@89706d3 Tests: restore context-engine usage proof · openclaw/openclaw@e4c4f95 Tests: slim context engine runtime coverage · openclaw/openclaw@74c198f ci: retry failed custom checkouts · openclaw/openclaw@0ee5baf test: trim duplicate provider auth onboarding cases · openclaw/openclaw@1ffc02e matrix: fix sessions_spawn --thread subagent session spawning (#67643) · openclaw/openclaw@1ce2596 test: reduce auth choice fixture churn · openclaw/openclaw@857b9cd test: mock health status config boundaries · openclaw/openclaw@9d5ab4a test: mock onboard config io boundary · openclaw/openclaw@299694d test: mock legacy state plugin boundaries · openclaw/openclaw@2713089 test: mock channel install boundaries · openclaw/openclaw@b945248 test: mock doctor preview channel boundaries · openclaw/openclaw@b1a3ad4
docs: add plugin hooks reference · openclaw/openclaw@7330a0c
steipete · 2026-04-25 · via Recent Commits to openclaw:main

@@ -0,0 +1,188 @@

1+

---

2+

summary: "Plugin hooks: intercept agent, tool, message, session, and Gateway lifecycle events"

3+

title: "Plugin hooks"

4+

read_when:

5+

- You are building a plugin that needs before_tool_call, before_agent_reply, message hooks, or lifecycle hooks

6+

- You need to block, rewrite, or require approval for tool calls from a plugin

7+

- You are deciding between internal hooks and plugin hooks

8+

---

9+10+

Plugin hooks are in-process extension points for OpenClaw plugins. Use them

11+

when a plugin needs to inspect or change agent runs, tool calls, message flow,

12+

session lifecycle, subagent routing, installs, or Gateway startup.

13+14+

Use [internal hooks](/automation/hooks) instead when you want a small

15+

operator-installed `HOOK.md` script for command and Gateway events such as

16+

`/new`, `/reset`, `/stop`, `agent:bootstrap`, or `gateway:startup`.

17+18+

## Quick start

19+20+

Register typed plugin hooks with `api.on(...)` from your plugin entry:

21+22+

```typescript

23+

import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";

24+25+

export default definePluginEntry({

26+

id: "tool-preflight",

27+

name: "Tool Preflight",

28+

register(api) {

29+

api.on(

30+

"before_tool_call",

31+

async (event) => {

32+

if (event.toolName !== "web_search") {

33+

return;

34+

}

35+36+

return {

37+

requireApproval: {

38+

title: "Run web search",

39+

description: `Allow search query: ${String(event.params.query ?? "")}`,

40+

severity: "info",

41+

timeoutMs: 60_000,

42+

timeoutBehavior: "deny",

43+

},

44+

};

45+

},

46+

{ priority: 50 },

47+

);

48+

},

49+

});

50+

```

51+52+

Hook handlers run sequentially in descending `priority`. Same-priority hooks

53+

keep registration order.

54+55+

## Common hooks

56+57+

| Hook | Use it for |

58+

| ---------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |

59+

| `before_tool_call` | Rewrite tool params, block execution, or request user approval before a tool runs. |

60+

| `after_tool_call` | Observe tool results, errors, and duration after execution. |

61+

| `before_prompt_build` | Add dynamic context or system prompt text before the model call. |

62+

| `before_model_resolve` | Override provider or model before session messages are loaded. |

63+

| `before_agent_reply` | Short-circuit the model turn with a synthetic reply or silence. |

64+

| `llm_input` / `llm_output` | Observe provider input/output for conversation-aware plugins. |

65+

| `agent_end` | Observe final messages, success state, and run duration. |

66+

| `message_received` | Observe inbound channel messages after channel parsing. |

67+

| `message_sending` | Rewrite or cancel outbound channel messages. |

68+

| `message_sent` | Observe outbound delivery success or failure. |

69+

| `session_start` / `session_end` | Track session lifecycle boundaries. |

70+

| `before_compaction` / `after_compaction` | Observe or annotate compaction cycles. |

71+

| `subagent_spawning` / `subagent_delivery_target` / `subagent_spawned` / `subagent_ended` | Coordinate subagent routing and completion delivery. |

72+

| `gateway_start` / `gateway_stop` | Start or stop plugin services with the Gateway. |

73+

| `before_install` | Inspect skill or plugin install scans and optionally block. |

74+75+

## Tool call policy

76+77+

`before_tool_call` receives:

78+79+

- `event.toolName`

80+

- `event.params`

81+

- optional `event.runId`

82+

- optional `event.toolCallId`

83+

- context fields such as `ctx.agentId`, `ctx.sessionKey`, `ctx.sessionId`, and

84+

diagnostic `ctx.trace`

85+86+

It can return:

87+88+

```typescript

89+

type BeforeToolCallResult = {

90+

params?: Record<string, unknown>;

91+

block?: boolean;

92+

blockReason?: string;

93+

requireApproval?: {

94+

title: string;

95+

description: string;

96+

severity?: "info" | "warning" | "critical";

97+

timeoutMs?: number;

98+

timeoutBehavior?: "allow" | "deny";

99+

onResolution?: (decision: string) => Promise<void> | void;

100+

};

101+

};

102+

```

103+104+

Rules:

105+106+

- `block: true` is terminal and skips lower-priority handlers.

107+

- `block: false` is treated as no decision.

108+

- `params` rewrites the tool parameters for execution.

109+

- `requireApproval` pauses the agent run and asks the user through plugin

110+

approvals. The `/approve` command can approve both exec and plugin approvals.

111+

- A lower-priority `block: true` can still block after a higher-priority hook

112+

requested approval.

113+114+

## Prompt and model hooks

115+116+

Use the phase-specific hooks for new plugins:

117+118+

- `before_model_resolve`: receives only the current prompt and attachment

119+

metadata. Return `providerOverride` or `modelOverride`.

120+

- `before_prompt_build`: receives the current prompt and session messages.

121+

Return `prependContext`, `systemPrompt`, `prependSystemContext`, or

122+

`appendSystemContext`.

123+124+

`before_agent_start` remains for compatibility. Prefer the explicit hooks above

125+

so your plugin does not depend on a legacy combined phase.

126+127+

Non-bundled plugins that need `llm_input`, `llm_output`, or `agent_end` must set:

128+129+

```json

130+

{

131+

"plugins": {

132+

"entries": {

133+

"my-plugin": {

134+

"hooks": {

135+

"allowConversationAccess": true

136+

}

137+

}

138+

}

139+

}

140+

}

141+

```

142+143+

Prompt-mutating hooks can be disabled per plugin with

144+

`plugins.entries.<id>.hooks.allowPromptInjection=false`.

145+146+

## Message hooks

147+148+

Use message hooks for channel-level routing and delivery policy:

149+150+

- `message_received`: observe inbound content, sender, `threadId`, and metadata.

151+

- `message_sending`: rewrite `content` or return `{ cancel: true }`.

152+

- `message_sent`: observe final success or failure.

153+154+

Prefer typed `threadId` and `replyToId` fields before using channel-specific

155+

metadata.

156+157+

Decision rules:

158+159+

- `message_sending` with `cancel: true` is terminal.

160+

- `message_sending` with `cancel: false` is treated as no decision.

161+

- Rewritten `content` continues to lower-priority hooks unless a later hook

162+

cancels delivery.

163+164+

## Install hooks

165+166+

`before_install` runs after the built-in scan for skill and plugin installs.

167+

Return additional findings or `{ block: true, blockReason }` to stop the

168+

install.

169+170+

`block: true` is terminal. `block: false` is treated as no decision.

171+172+

## Gateway lifecycle

173+174+

Use `gateway_start` for plugin services that need Gateway-owned state. The

175+

context exposes `ctx.config`, `ctx.workspaceDir`, and `ctx.getCron?.()` for

176+

cron inspection and updates. Use `gateway_stop` to clean up long-running

177+

resources.

178+179+

Do not rely on the internal `gateway:startup` hook for plugin-owned runtime

180+

services.

181+182+

## Related

183+184+

- [Building plugins](/plugins/building-plugins)

185+

- [Plugin SDK overview](/plugins/sdk-overview)

186+

- [Plugin entry points](/plugins/sdk-entrypoints)

187+

- [Internal hooks](/automation/hooks)

188+

- [Plugin architecture internals](/plugins/architecture-internals)