本页内容
本页内容
构建插件
工具调用策略挂钩
工具端挂钩:参数重写、阻止、批准、执行环境贡献和转录持久性。 插件挂钩 指南的一部分。
工具调用策略
before_tool_call 接收:
event.toolNameevent.params- 可选
event.toolKind和event.toolInputKind,有意共享名称的工具的主机权威鉴别器;例如,外部代码模式exec调用使用toolKind: "code_mode_exec"并包含toolInputKind: "javascript"来接受代码模式输入 - 可选的
event.derivedPaths,由宿主尽力推导的目标路径提示, 适用于apply_patch等已知工具封装;这些路径可能不完整,或过度近似工具实际会修改的内容 (例如,对于格式错误或不完整的输入) - 可选的
event.runId - 可选的
event.toolCallId - 上下文字段,例如
ctx.agentId、ctx.sessionKey、ctx.sessionId、ctx.runId、ctx.toolKind、ctx.toolInputKind,以及诊断用的ctx.trace - 可选的
ctx.abortSignal,在所属工具调用被取消时触发;处理器应将其传递给可取消的 I/O,并移除其注册的任何监听器 - 可选
ctx.requester,发起当前消息运行的主机派生请求者。它可以包括channel、accountId、senderId、senderIsOwner和提供商本机roleIds。缺失的字段是未经证实的,不是虚假的保证;如果策略需要这些字段,则拒绝该操作。
它可以返回:
类型化生命周期钩子的守卫行为:
block: true是终结性的,并会跳过更低优先级的处理器。block: false视为没有决策。- 返回
params重写主机拥有的工具参数。每个处理程序都会看到原始事件的独立副本,而不是先前返回的重写。最后返回的params获胜,直到请求批准。 - 第一个
requireApproval获胜,其插件 id 由主机盖章。它冻结选定的参数快照:以后的处理程序可以阻止但不能更改已批准的参数。 - 原生工具继电器可以有更窄的合约。 Codex 原生工具支持阻塞和观察,但拒绝参数重写;请参阅 Codex 挂钩边界。
requireApproval会暂停代理运行,并通过插件审批请求用户。/approve可以同时批准 exec 和插件审批。在 Codex app-server report-mode 原生PreToolUse转发中,这会委托给匹配的 app-server 审批请求;参见 Codex harness runtime。- 更低优先级的
block: true即使在更高优先级钩子请求了批准之后,仍然可以阻止执行。 onResolution接收已解析的决策:allow-once、allow-always、deny、timeout或cancelled。
例如,将其添加到 register(api) 中以在主机拥有的 exec 调用之前进行询问。 before_tool_call 不需要选择加入对话访问:
单文件中的发送者感知策略
独立插件文件可以将部署特定的策略保存在代码中,而无需添加其他配置模式。此示例为所有者提供每个工具的访问权限,让已配置的维护者使用一组保守的工具和消息操作,并向已获得频道配置授权的发送者开放 /fix:
将文件添加到plugins.load.paths并启用;默认混合重新加载模式应用更改。独立文件使用其文件名作为插件 ID(maintenance-access.ts 是 maintenance-access),因此请使其等于传递给 definePluginEntry 的 id:
AGENT_ID 必须命名绑定到维护会话的代理。绑定选择正常消息和 /fix 的代理;独立文件仍然是所有者与维护者工具策略的单一所有者。编辑文件本身后,运行 openclaw plugins reload maintenance-access。
requireAuth: true 重用每个通道的现有发送者准入。对于 Discord,公会或频道 users/roles 白名单可以授权维护受众。其他渠道可以使用稳定的发件人 ID。然后,该挂钩将更精细的每个工具决策应用于运行中的每个工具调用,包括 Codex 本机 PreToolUse 调用。它可以否决模型看到的工具,但不能添加主机省略的工具。现有的沙箱、执行审批、仅限所有者的核心工具和渠道政策仍然适用;钩子无法通过它们。
将发送者和角色 ID 范围限定为精确的 channel/account 对,如图所示;两者都是提供者本地命名空间。保持许可名单保守。仅当部署的沙箱和批准策略确保安全时才添加写入或执行工具。对于自动化或系统运行,明确决定是否应通过不存在的 ctx.requester;该示例拒绝为作用域代理进行此操作。
参见插件权限请求,了解审批路由、决策行为,以及何时应使用 requireApproval 而不是可选工具或 exec 审批。
需要宿主级策略的插件可以通过 api.registerTrustedToolPolicy(...) 注册受信任的工具策略。这些策略会在普通的 before_tool_call 钩子之前以及正常钩子决策之前运行。捆绑的受信任策略最先运行;已安装插件的受信任策略随后按插件加载顺序运行;普通的 before_tool_call 钩子在它们之后运行。捆绑插件保留现有的受信任策略路径。已安装插件必须显式启用,并在 contracts.trustedToolPolicies 中声明每个策略 id;未声明的 id 会在注册前被拒绝。策略 id 仅在注册该策略的插件范围内有效,因此不同插件可以重用相同的本地 id。仅在工作区策略、预算执行或保留工作流安全等宿主信任的门控场景中使用这一层。
可信策略可以将 matcher 设置为 before_tool_call 接受的相同标准工具 ID 列表。省略匹配器以保留全部匹配行为。
当可信策略批准内联完成时,普通 before_tool_call 挂钩会收到已批准参数的独立副本。参数未更改的调用仍然被允许,但要受到普通否决和稍后的执行检查。转换这些参数的普通挂钩必须返回 requireApproval 及其最终的 params,以便替换得到单独的批准。如果没有该批准请求,更改后的呼叫将被 Tool call parameters changed after trusted approval 阻止。
当升级将可信批准与普通参数重写相结合的插件时,请更新转换钩子以请求单独的批准。第一次批准并不授权替换参数。此内联边界不会改变上述较窄的本机中继合约。
工具调用观察
after_tool_call 观察到已运行的工具调用。它是 before_tool_call 的另一半,用于记录门控调用所做的事情。它接收与before_tool_call(PluginHookToolContext)相同的上下文类型;可用的上下文字段取决于发射harness。其事件包含:
event.toolName:工具名称。event.params:工具参数,包括before_tool_call的调整。- 可选
event.runId:所属运行标识符。 - 可选
event.toolCallId:工具调用标识符。 - 可选
event.result:harness提供的工具结果。 - 可选
event.error:harness提供或提取的错误消息。 - 可选
event.durationMs:已知开始时间时经过的毫秒数。
它是一个观察钩子,所以它不能改变已经发生的事情:
- Handlers 并发运行,并且它们的返回值被忽略。
- A 抛出或超时的处理程序被记录,并继续执行。
matcher接受与before_tool_call相同的标准工具 ID 列表。
result 和 error 都是可选的,因此两者都不包含的事件并不能证明该工具成功。通过缺少 error 来推断成功的处理程序可以将失败的调用记录为成功的调用;将不可读的结果视为未知,而不是任一结果。 result 为 exec 和 bash 系列工具携带的内容在 #102961 中单独跟踪。
不要使用此挂钩来执行策略。正如 hook 参考文献 所说,使用一个在错误时阻止操作的门,而不是假设观察或传递钩子会在失败时拒绝操作。
Exec 环境钩子
resolve_exec_env 允许插件在命令运行之前向 OpenClaw exec 工具调用提供环境变量。它并不是适用于所有harness-native shell 的钩子。它接收:
event.sessionKeyevent.toolName,始终为"exec"event.host,取值为"gateway"、"sandbox"或"node"- 上下文字段,例如
ctx.agentId、ctx.sessionKey、ctx.sessionId、ctx.messageProvider和ctx.channelId
返回一个 Record<string, string> 以合并到 exec 环境中。处理器按优先级顺序运行;后面的结果会覆盖较早结果中相同的键。
在合并之前,钩子输出通过主机执行环境密钥策略进行过滤。 PATH 始终被丢弃(命令解析和安全箱检查取决于它)。无效密钥和危险主机覆盖密钥,例如 LD_*、DYLD_*、NODE_OPTIONS、代理变量(HTTP_PROXY、HTTPS_PROXY、ALL_PROXY、NO_PROXY)和 TLS 覆盖变量(NODE_TLS_REJECT_UNAUTHORIZED、SSL_CERT_FILE 和类似)已被删除。过滤后的插件环境包含在网关 approval/audit 元数据中,并转发到节点主机执行请求。
工具结果持久化
tool_result_persist和before_message_write是同步钩子。不要让他们的处理程序 async:返回的承诺将被忽略并带有警告。每个处理程序都会接收前一个处理程序返回的消息。 tool_result_persist 返回 { message } 替换工具结果; before_message_write 可以返回 { message } 或 { block: true } 以防止转录写入。阻止持久性并不是工具执行否决权。
这些挂钩对 OpenClaw- 拥有的转录本写入进行操作。它们不会重写 Codex-native 工具记录;请参阅 Codex 转录本边界 。
工具结果可以包含用于 UI 渲染、诊断、媒体路由或插件自有元数据的结构化 details。请将 details 视为运行时元数据,而不是提示词内容:
- OpenClaw 会在提供方回放和压缩输入之前剥离
toolResult.details,因此元数据不会成为模型上下文。 - 持久化的会话条目只保留有界的
details。过大的 details 会被替换为紧凑摘要和persistedDetailsTruncated: true。 tool_result_persist和before_message_write在最终持久化上限之前运行。请保持返回的details较小,并避免只把与提示相关的文本放在details中;应将模型可见的工具输出放在content中。