TellWorldAI 世界档案
问档案English

首页›实践›实践

实践

Codex Hooks

Codex Hooks 让你在智能体循环的固定节点运行脚本或 MCP 工具:配置在哪里、怎么信任、怎么拦截一次工具调用。

这篇适合谁

适合想给 Codex 加上自己规则的读者,比如拦截危险的 Bash 命令、扫描提示词里误粘贴的 API key、记录会话,或者在一轮结束时跑一次检查。读完,你能配置一个 PreToolUse 钩子,把它信任下来,并知道它在什么时候生效。

Hooks 是什么

Hooks 是 Codex 的扩展机制,让你在智能体循环中运行脚本或 MCP 工具[1]。官方给出的例子包括:把对话发送到自定义的日志或分析系统,扫描提示词以阻止误粘贴的 API key,把对话总结成持久记忆,以及在一轮结束时执行校验[1]。

所有匹配的钩子都会运行。同一事件下有多个匹配的命令钩子时,它们会并发启动,一个钩子不会阻止另一个钩子启动[1]。

钩子在什么时候运行

一次会话里,钩子事件分布在几个节点[1]:

  • 一轮之内:PreToolUse、PermissionRequest、PostToolUse、PreCompact、PostCompact、UserPromptSubmit、SubagentStop 和 Stop。
  • 每次模型请求尝试:PreModelRequest 和 PostModelRequest。
  • 中断正在进行的一轮:Interrupt。
  • 会话或子智能体启动:SessionStart 和 SubagentStart。
  • 主线程结束:SessionEnd。

配置放在哪里

Codex 会在生效的配置层旁边查找钩子,形式有两种:hooks.json 文件,或 config.toml 里的内联 [hooks] 表[1]。最常用的四个位置是 ~/.codex/hooks.json、~/.codex/config.toml、<repo>/.codex/hooks.json 和 <repo>/.codex/config.toml[1]。同一层里两种写法都有时,Codex 会合并它们并在启动时发出警告,所以每层只用一种写法[1]。

一个钩子分三层:事件、决定何时匹配的 matcher 组,以及一个或多个 handler[1]。只有 command 和 mcp_tool 类型的 handler 会运行,prompt 和 agent 类型会被解析但跳过[1]。下面是在 config.toml 里用内联表写的版本:一个 SessionStart 钩子,加一个检查 Bash 命令的 PreToolUse 钩子:

[[hooks.SessionStart]]
matcher = "^compact$"

[[hooks.SessionStart.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/session_start.py"'
additionalContextLimit = 5000

[[hooks.PreToolUse]]
matcher = "^Bash$"

[[hooks.PreToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py"'
timeout = 30
statusMessage = "Checking Bash command"

仓库内的钩子,脚本路径要从 git 根目录解析,不要用 .codex/hooks/... 这样的相对路径,因为 Codex 可能从子目录启动[1]。命令以会话的工作目录作为 cwd 运行[1]。timeout 以秒为单位。大多数钩子默认 600 秒;SessionEnd 和 Interrupt 默认 1 秒,最多可设为 3 秒[1]。

先信任,再运行

非托管的钩子在你信任之前不会运行。Codex 把信任记录在每个钩子的哈希值上,新增或改过的钩子会被标记为待审核,在你批准前直接跳过[1]。在 CLI 里运行 /hooks,可以查看钩子来源、审核变更、信任或单独停用钩子[1]。--dangerously-bypass-hook-trust 参数会让单次运行跳过持久化的信任检查,官方说明它只适用于已经在 Codex 外部审核过钩子来源的一次性自动化[1]。

关闭钩子

钩子默认开启。要关闭,在 config.toml 里加上:

[features]
hooks = false

开关的键名是 hooks。旧的 codex_hooks 仍然可用,但已被标记为弃用的别名[1]。

拦截一次工具调用

PreToolUse 可以拦截 Bash 命令、通过 apply_patch 进行的文件编辑、MCP 工具调用,以及其他本地函数工具。WebSearch 这类托管工具不走这条路径[1]。要拒绝一次调用,就输出这样的 JSON:

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Destructive command blocked by hook."
  }
}

退出码为 2、并把原因写到 stderr,同样能拦截该调用[1]。钩子也可以返回 permissionDecision: "allow" 加上 updatedInput,改写调用内容。对 Bash 和 apply_patch,updatedInput 必须包含字符串类型的 command 字段[1]。官方把工具钩子定位为有用的护栏,而不是完整的强制执行边界[1]。

PermissionRequest 在 Codex 即将请求审批时运行,比如 shell 提权。它可以允许或拒绝请求;多个钩子给出决定时,任何一个 deny 都会生效[1]。

让一轮继续,以及后台运行

Stop 钩子可以让 Codex 继续工作。返回 decision: "block" 加上 reason,Codex 会把这段理由当作新的用户提示继续下一步,而不是拒绝这一轮[1]。在命令 handler 上设置 "async": true 可以放到后台运行。每个会话最多同时运行八个后台钩子,但它们无法阻止或改写触发它的操作,所以策略类判断要用同步钩子[1]。

写一个钩子的步骤

先确定在哪个节点介入。想拦截工具调用,就用 PreToolUse;想在一轮结束时做检查,就用 Stop;想在会话开始时执行脚本,就用 SessionStart[1]。接着用 matcher 缩小范围,比如只匹配 Bash。matcher 是正则表达式,省略时,该事件的每一次触发都会匹配[1]。

脚本从标准输入读取一个 JSON 对象。每个命令钩子都会收到 session_id、transcript_path、cwd、hook_event_name 和 model 这几个共同字段,脚本可以据此判断当前会话和工作目录[1]。钩子命令以会话的工作目录运行,所以仓库内的脚本路径应从 git 根目录解析,而不是依赖 .codex/hooks/... 这样的相对路径[1]。

写完之后,在 CLI 里运行 /hooks,检查钩子来源并信任它。Codex 按钩子定义的哈希记录信任,所以之后改动过的钩子会被重新标记,在再次信任前会被跳过。团队里改脚本时最容易忘掉这一步,最好在提交说明里提醒同事[1]。

几个容易踩的坑

  • 改过的钩子会被重新标记。团队里有人改了脚本,但没有重新运行 /hooks,钩子就会被跳过,表现为"规则没生效"[1]。
  • 项目级钩子只在项目被信任时加载。在未信任的项目里,你以为生效的钩子其实没有运行,只有用户和系统层的钩子会运行[1]。
  • UserPromptSubmit 和 Stop 会忽略 matcher。给它们写一个过滤条件不会有任何效果[1]。
  • 后台钩子不能阻止或改写触发它的操作。需要做策略判断时,要用同步钩子[1]。
  • 钩子只是有用的护栏。官方文档强调它不是完整的强制执行边界,不能把安全完全押在钩子上[1]。

输出大小

默认情况下,Codex 把每条模型可见的钩子输出限制在约 2,500 个 token。超出的内容会存到文件里,给模型的是一段预览[1]。

matcher 与托管钩子

matcher 是正则表达式。"*"、空字符串或不写,都表示匹配所支持事件的每一次触发。UserPromptSubmit 和 Stop 忽略 matcher[1]。在企业环境里,requirements.toml 中设置 allow_managed_hooks_only = true,会跳过用户、项目、会话和插件来源的钩子,只保留托管钩子[1]。

下一步

先给 Bash 配一个 PreToolUse 钩子,用 /hooks 确认它生效,再逐步增加其他事件。完整的事件输入和输出格式,请看官方 Hooks 页面[1]。

来源

  1. 1
    HooksOpenAI Codex docs

引用本页: Codex Hooks. TellWorld, https://www.tellworld.net/zh/practice/practice-codex-hooks. 更新于 2026-11-14

相关动态