本页内容
本页内容
构建插件
挂钩参考
注册规则、执行合同、每个处理程序的预算以及完整的类型化挂钩目录。 插件挂钩 指南的一部分。
注册执行
保持 register(api) 同步并在那里注册处理程序。除了两个同步持久性挂钩之外,处理程序本身可以是异步的。
处理程序默认优先级为 0;优先级较高的优先级优先,注册顺序打破了平局。执行取决于钩子类型:
| 类型 | 执行合同 |
|---|---|
| 调整 | 顺序;结果根据下面的钩子合同进行合并。返回重写通常不会更改传递给后续处理程序的事件。 |
| 宣称 | 顺序;第一个 { handled: true } 获胜并跳过剩余的处理程序。 |
| 闸门 | 顺序;一个块会停止剩余的处理程序。 |
| 观察 | 处理程序同时运行;返回值被忽略。发射器可以等待完成或调度即发即弃。 |
| 同步modify/gate | 同步,按优先顺序;每个处理程序都会看到最新的消息。承诺被忽略并带有警告。 |
| 评价 | 技能评估器同时运行并产生单独的归因结果。 |
优先级不会对观察副作用进行序列化。即发即弃事件可以与后续事件重叠,并且回调不是持久的事件队列。显式返回修改,而不是依赖就地突变。
api.on(name, handler, opts?) 接受:
| 选项 | 作用 |
|---|---|
matcher |
由 before_tool_call 或 after_tool_call 处理的标准 OpenClaw 工具 ID 的非空列表,例如 exec、apply_patch 或 spawn_agent。省略匹配所有工具。空列表、通配符、空白和特定于提供商的别名无效。 |
priority |
排序;数值越高越先运行。 |
registrationId |
插件内一次注册的稳定身份。技能评估者将其用作evaluatorId;否则使用插件 ID。 |
timeoutMs |
每个处理程序异步等待预算。过期应用下面的钩子失败策略;它不会取消处理程序或其副作用。忽略使用跑步者的默认值(如果有)。 |
eligibleTriggers |
仅适用于 before_agent_reply,将宿主分发限制为 cron、heartbeat 或 user 中的一个或多个触发器。 |
eligibleDispatchKinds |
仅适用于 reply_dispatch,将主机调度限制为 agent、acp 或两者。省略处理所有调度类型。 |
requiresToolAuthority |
仅适用于 before_prompt_build,在主机完成当前回合的工具表面并提供临时 ctx.toolAuthority 后运行处理程序。使用它进行必须遵循工具策略的上下文检索。 |
触发器资格由宿主在调用处理器之前强制执行。因此,使用 eligibleTriggers: ["heartbeat", "cron"] 注册的钩子对于用户轮次处于非活动状态,包括恢复的用户轮次。省略、为空、格式错误或部分包含未知值的列表仍不受限制,因此钩子会在这些轮次中运行。其他钩子类型不接受此选项。
运维人员可以在不修改插件代码的情况下设置钩子预算:
hooks.timeouts.<hookName> 会覆盖 hooks.timeoutMs,后者会覆盖插件编写的 api.on(..., { timeoutMs }) 值。两个操作员配置字段接受最多 600000 毫秒的正整数。对于已知的慢钩子,更喜欢按钩子覆盖,这样一个插件就不会在任何地方都获得更长的预算。
超时处理程序 Promise 会继续运行,因为挂钩回调不会收到超时拥有的取消信号。 before_tool_call 可以接收所属工具调用的 ctx.abortSignal,但钩子超时到期不会中止它。当插件工作仍在进行时,钩子调度可以释放其网关许可。拥有长时间运行工作的插件必须提供自己的取消和关闭生命周期。
在结果变得不合格后,提示构建处理程序可以使用 ctx.hookInvocation.assertActive() 拒绝副作用。请参阅 Handler 生命周期。
标准运行程序应用这些默认值 per handler:
| 钩子 | 默认超时 | 抛出错误或超时时 |
|---|---|---|
before_agent_run, before_tool_call, before_install |
15秒 | 阻止运行、工具调用或安装 |
before_agent_finalize, before_prompt_build, message_sending, reply_payload_sending, resolve_exec_env |
15秒 | 记录并跳过失败的处理程序;保留其他成功结果 |
agent_end, before_compaction, after_compaction, skill_changed |
30 秒 | 记录并继续 |
channel_pairing_requested |
2秒 | 记录并继续 |
gateway_stop |
5秒 | 记录并继续关闭 |
| 其他异步钩子,包括声明钩子 | 除非配置,否则没有跑步者超时 | 记录并继续 |
tool_result_persist, before_message_write |
无异步超时 | 记录同步错误;失败的结果将被忽略 |
发射器可以施加更严格的整体生命周期预算,例如下面的关闭 session_end 排水。超时仅限制异步等待;它不能中断同步JavaScript。对于策略要求,请使用一个阻止错误操作的门,而不是假设观察或交付挂钩将拒绝失败的操作。
对于声明挂钩,继续意味着尝试下一个处理程序。如果无人认领,则由呼叫者决定如何处理;绑定对话失败的 inbound_claim 可以生成绑定通知而不是普通代理回复。
使用 createReplyDispatcher 的通道插件同样可以通过 beforeDeliverOptions: { timeoutMs } 声明更大的正向每阶段预算,或者在通过 dispatcher.appendBeforeDeliver(handler, { timeoutMs }) 追加工作时指定。若没有所有者声明的预算,这些回调会使用相同的 15 秒默认值,这样一个卡住的回调就不会占用序列化交付通道。
钩子目录
钩子按其延伸的表面进行分组。种类参见上述执行合同;修改钩子不是观察钩子。
Agent 回合
| 钩子 | 类型 | 用途 |
|---|---|---|
before_model_resolve |
调整 | 在加载会话消息之前覆盖提供程序、模型或运行的后备链 |
agent_turn_prepare |
调整 | 检查耗尽的插件转注入并在提示钩子之前添加上下文 |
before_prompt_build |
调整 | 添加提示上下文,缩小当前回合提交的工具范围,或执行授权的策略后充实 |
before_agent_run |
闸门 | 在模型提交之前检查提示和会话消息;节点在工作本地上下文组装之前打开门网关输入 |
before_agent_reply |
宣称 | 使用合成回复或静默来提前结束模型回合 |
before_agent_finalize |
调整 | 检查自然生成的最终答案,并请求模型再次处理 |
agent_end |
观察 | 观察最终消息、成功状态和运行时长 |
heartbeat_prompt_contribution |
调整 | 为后台监控和生命周期插件添加仅用于心跳的上下文 |
对话观察
| 钩子 | 类型 | 用途 |
|---|---|---|
model_call_started / model_call_ended |
观察 | 净化的 provider/model 调用元数据:计时、结果、有界请求 ID 哈希值。无提示或响应内容。 |
llm_input |
观察 | 提供方输入:系统提示词、提示词、历史记录 |
llm_output |
观察 | 提供方输出、用量,以及可用时解析得到的 contextTokenBudget |
工具
| 钩子 | 类型 | 用途 |
|---|---|---|
before_tool_call |
修改/门 | 重写工具参数、阻止执行或要求批准 |
after_tool_call |
观察 | 观察工具结果、错误和持续时间 |
resolve_exec_env |
调整 | 为 exec 提供插件拥有的环境变量 |
tool_result_persist |
同步修改 | 在转录持久化之前重写 toolResult 消息 |
before_message_write |
同步修改/门控 | 在转录持久化之前重写或阻止消息 |
消息与传递
| 钩子 | 类型 | 用途 |
|---|---|---|
inbound_claim |
宣称 | 为拥有该消息会话绑定的插件认领入站消息 |
channel_pairing_requested |
观察 | 观察新创建的 DM 配对请求 |
message_received |
观察 | 观察入站内容、发送者、线程和元数据 |
message_sending |
修改/门 | 重写出站内容或取消传递 |
reply_payload_sending |
修改/门 | 在传递前修改或取消规范化的回复负载 |
message_sent |
观察 | 观察出站传递的成功或失败 |
before_dispatch |
宣称 | 在正常模型调度之前处理入站消息 |
reply_dispatch |
宣称 | 自己的回复生成和发送,而不是默认的模型路径 |
inbound_claim 不是全局预路由广播。 OpenClaw 仅针对拥有消息的核心管理对话绑定的插件调用它。要在模型输入之前抑制普通代理转动而不保留转录中的原始提示,请在受支持的运行器上使用 before_agent_run。要通过合成回复或静音来短路代理回合,请使用 before_agent_reply。
对于心跳轮换,当主机知道底层系统事件队列时,before_agent_reply 会收到 ctx.heartbeatEventQueueSessionKey。这可能与隔离心跳运行的 ctx.sessionKey 不同。使用提供的键进行事件查找;不要通过删除 :heartbeat 后缀来派生基本会话,因为配置的会话可以命名为 heartbeat。对于较旧的主机,该字段是可选的。没有它,插件只能检查 ctx.sessionKey;他们无法推断隔离运行的基本队列。该字段标识现有队列并且不授予额外的访问权限。
会话与压缩
| 钩子 | 类型 | 用途 |
|---|---|---|
session_start / session_end |
观察 | 跟踪会话生命周期边界 |
before_compaction / after_compaction |
观察 | 观察压实边界;没有重写或否决结果 |
before_reset |
观察 | 观察会话重置事件(/reset、程序化重置) |
即使没有历史记录更改,成功的引擎拥有的内置本机压缩尝试也会发出 after_compaction,并带有 compactedCount: 0。本机跳过包括仅心跳记录和自动保留策略无操作。完成意味着尝试完成;它不保证历史重写。失败或中止的尝试不会发出该完成挂钩。
session_end.reason 是 new、reset、idle、daily、compaction、deleted、shutdown、restart 之一,或unknown。 session_start 无原因字段;它可以包括 resumedFrom。 Shutdown/restart 事件来自活动会话的网关终结器,因此插件可以在进程退出之前关闭会话状态。
在当前主机上,session_end 上下文包括 endedTranscript。当 OpenClaw 具有不可变的结束会话源时,具有会话访问权限的插件会接收 { available: true, readTail }。看涨期权必须提供正值 maxMessages 和 maxBytes; OpenClaw 强制执行主机上限并返回 { messages, totalMessages, truncated }。当允许的处理程序处于活动状态时,读取器仍然有效。处理程序解决、其配置的挂钩超时、所属插件实例强制退出或 shutdown/restart 耗尽截止时间后,保留或仍待处理的读取会被拒绝。
当不存在安全源时,值为{ available: false, reason }。当前的原因包括缺少对话权限、没有稳定截止的生命周期、已删除的隐身状态、不可用的存档以及不受支持的源。这是一个明确的非结果,而不是一个空的成绩单。根据此合同编译的插件仍应将缺失的字段视为较旧的主机。
session_end 本身仍然是元数据挂钩,无需对话访问即可注册。对于非捆绑插件,plugins.entries.<id>.hooks.allowConversationAccess=true 仅授予有界的结束转录阅读器。捆绑插件遵循相同的有效策略,可以通过 allowConversationAccess: false 拒绝。权限更改适用于成功发布的插件运行时替换所承认的处理程序。已经运行的处理程序保留其生成的授权,同时其有界调用仍然被允许;处理程序结算、挂钩超时、强制实例退役或关闭耗尽到期都会结束租约。前一个版本和后续版本可能会重叠。
关闭和重新启动在所有活动会话和插件处理程序中共享一个 2 秒总计 session_end 消耗预算;预算不是每个处理程序的。快速返回或保持最终确定有界和持久性崩溃一致。如果预算到期,OpenClaw 会记录 shutdown session-end drain timed out 并继续关闭,因此可以中断未完成的插件工作。
对于 sessions.create 与 parentSessionKey 和 emitCommandHooks: true 的调用,不同的子级始终接收 session_start。调用者声明父级是否也接收终端 session_end 和 succeedsParent:true 表示后继,false 表示并行子级。省略保留了遗留的父级翻转行为。在这两种情况下,command:new 和 before_reset 挂钩仍然描述请求的 /new 操作。
子代理
subagent_spawned/subagent_ended- 观察子代理的启动和完成。subagent_progress- 观察便携式started/ended后台子运行的进度;包括runId、childSessionKey、可选请求者路由以及ended上的结果。subagent_delivery_target- 当没有核心会话绑定可以投影路线时,修改兼容性挂钩以完成交付。第一个返回的origin获胜。subagent_spawned在 OpenClaw 已在启动前解析出子会话原生模型时,会包含resolvedModel和resolvedProvider。subagent_ended包含targetSessionKey(标识 - 与subagent_spawned.childSessionKey匹配)、targetKind("subagent"或"acp")、reason、可选的outcome("ok"、"error"、"timeout"、"killed"、"reset"或"deleted")、可选的error、runId、endedAt、accountId和sendFarewell。它不包含agentId或childSessionKey;请使用targetSessionKey与匹配的subagent_spawned事件进行关联。
生命周期
| 钩子 | 类型 | 用途 |
|---|---|---|
gateway_start / gateway_stop |
观察 | 与 Gateway 一同启动或停止插件拥有的服务 |
cron_reconciled |
观察 | 在启动或重新加载后与完整的 Gateway cron 状态进行协调 |
cron_changed |
观察 | 观察 Gateway 拥有的 cron 生命周期变化(添加、更新、移除、启动、完成、计划) |
before_install |
修改/门 | 从已加载的插件运行时检查暂存的技能或插件安装材料 |
skill_changed |
观察 | 观察已提交的实时技能创建、更新和移除事件 |
技能生命周期
skill_changed 在实时技能创建、更新或删除提交后触发,并包括带有内容和树哈希的可选 before/after 工件,以及可用的声明版本和源版本。
频道配对请求
当未配对的 DM 发送者创建待处理的配对请求后,插件需要通知操作员或写入审核记录时,请使用 channel_pairing_requested。该钩子在创建请求时调度;配对回复的通道传递不会因缓慢或失败的挂钩处理程序而延迟。
该钩子仅用于观察。它不会批准、拒绝、抑制或重写配对回复。有效负载包含通道、可选的 accountId、按通道范围的 senderId、配对 code 以及通道元数据。请将配对代码视为实时一次性批准凭证,并仅将其交付给受信任的操作员接收端。请将 metadata 视为不受信任的、由发送者提供的身份文本。该钩子不包含传入消息正文或媒体。