跳转到内容

钩子

Codex 中文站说明: 本页围绕“钩子”重新补充了中文使用场景和验证重点。界面名称可能随 Codex 版本更新,请以当前客户端为准。

在 Codex 生命周期中运行确定性的脚本

钩子是 Codex 的一套扩展框架。它允许你把自己的脚本插入智能体循环中,从而实现例如以下能力:

  • 把聊天发送到自定义日志或分析系统
  • 扫描团队提示词,阻止误粘贴 API key
  • 自动总结聊天,生成持久记忆
  • 在聊天轮次结束时运行自定义校验检查,强制执行团队标准
  • 当工作目录匹配特定路径时,动态调整提示词策略

需要留意这些运行时行为:

  • 来自多个文件的匹配钩子都会运行。
  • 对同一事件命中的多个命令型钩子会并发启动,因此一个钩子不能阻止其他已命中的钩子启动。
  • 非托管命令型钩子必须经过审核并被信任后才会运行。

Hooks 会在对话的不同阶段运行:

阶段 Hooks
会话轮次期间 PreToolUsePermissionRequestPostToolUsePreCompactPostCompactUserPromptSubmitSubagentStopStop
会话或子智能体启动时 SessionStartSubagentStart
主对话线程结束时 SessionEnd(不会为子智能体运行)

Codex 会在当前激活配置层旁边查找以下任一形式的钩子配置:

  • hooks.json
  • config.toml 中的内联 [hooks]

已安装插件也可以通过插件 manifest 或默认的 hooks/hooks.json 文件打包生命周期配置。插件打包规则请参见构建插件

实际使用中,最常见也最有用的四个位置是:

  • ~/.codex/hooks.json
  • ~/.codex/config.toml
  • <repo>/.codex/hooks.json
  • <repo>/.codex/config.toml

如果存在多个钩子来源,Codex 会加载所有命中的钩子。高优先级配置层不会替换低优先级配置层里的钩子。如果同一配置层同时包含 hooks.json 和内联 [hooks],Codex 会合并它们,并在启动时给出警告。建议每个配置层只使用其中一种表示方式。

Codex 也可以发现已启用插件中打包的 hooks。插件打包的 hooks 会和其他 hook 来源一起加载,并使用和其他非托管 hooks 相同的信任审核流程。

项目本地钩子只会在项目 .codex/ 配置层受信任时加载。在不受信任的项目中,Codex 仍会加载用户层和系统层中各自激活的钩子。

Codex 会在决定哪些 hooks 可以运行之前列出已配置 hooks。非托管 command hook 运行前,Codex 要求你审核并信任精确的 hook 定义。Codex 会把信任记录绑定到该 hook 当前 hash;新增或变更后的 hooks 会重新标记为待审核,并在被信任前跳过。

在 CLI 中使用 /hooks 可以检查 hook 来源、审核新增或已变更 hooks、信任 hooks,或禁用单个非托管 hook。如果启动时有 hooks 需要审核,Codex 会打印警告,提示你打开 /hooks

来自 system、MDM、cloud 或 requirements.toml 来源的 managed hooks 会被标记为托管,由策略信任,并且不能从用户 hook 浏览器中禁用。

对于已经在 Codex 外部审核 hook 来源的一次性自动化,可以传入 --dangerously-bypass-hook-trust,让已启用的 hooks 在本次调用中无需持久化 hook trust 也能运行。

Hooks 分成三层:

  • 事件名,例如 PreToolUsePostToolUsePreCompactSubagentStartStop
  • 决定该事件何时命中的 matcher 分组
  • 当 matcher 命中时实际执行的一个或多个钩子处理器
{
"description": "Optional lifecycle hooks for this workspace.",
"hooks": {
"SessionStart": [
{
"matcher": "startup|resume",
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_start.py",
"statusMessage": "Loading session notes"
}
]
}
],
"SessionEnd": [
{
"hooks": [
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_end.py",
"timeout": 3
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/pre_tool_use_policy.py\"",
"statusMessage": "Checking Bash command"
}
]
}
],
"PermissionRequest": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/permission_request.py\"",
"statusMessage": "Checking approval request"
}
]
}
],
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use_review.py\"",
"statusMessage": "Reviewing Bash output"
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/user_prompt_submit_data_flywheel.py\""
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "/usr/bin/python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/stop_continue.py\"",
"timeout": 30
}
]
}
]
}
}

说明:

  • descriptionhooks.json 可选的顶层元数据,不会改变哪些 hooks 会运行。
  • timeout 的单位是秒。
  • 如果省略 timeout,大多数 hooks 会使用 600 秒。
  • SessionEnd 默认使用 1 秒,最大支持 3 秒。
  • statusMessage 是可选的。
  • commandWindows 是可选的 Windows 专用命令覆盖。在 TOML 中可以使用 command_windowscommandWindows
  • Codex 会解析 async 选项,但目前还不支持异步命令型钩子。
  • 目前只有 type: "command" 的处理器会运行。promptagent 处理器会被解析,但会被跳过。
  • 命令会以当前会话的 cwd 作为工作目录运行。
  • 对仓库级钩子,优先使用基于 Git 根目录解析的路径,而不是 .codex/hooks/... 这类相对路径。Codex 可能从子目录启动,基于 Git 根目录的写法更稳定。

config.toml 中等价的内联 TOML 写法如下:

[[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"
[[hooks.PostToolUse]]
matcher = "^Bash$"
[[hooks.PostToolUse.hooks]]
type = "command"
command = '/usr/bin/python3 "$(git rev-parse --show-toplevel)/.codex/hooks/post_tool_use_review.py"'
timeout = 30
statusMessage = "Reviewing Bash output"

Hooks 默认启用。若要在 config.toml 中关闭,请设置:

[features]
hooks = false

请把 hooks 作为标准功能键。codex_hooks 仍可作为已弃用别名使用。管理员也可以在 requirements.toml 中通过 [features].hooks = false 强制关闭钩子。

企业托管的 requirements 也可以在 [hooks] 下内联定义钩子。当管理员希望强制执行钩子配置,同时通过 MDM 或其他设备管理系统分发实际脚本时,这种方式很有用。若要即使用户在本地关闭 hooks 也强制执行托管 hooks,请在 requirements.toml 中把 [features].hooks = true[hooks] 一起固定下来。若要忽略用户、项目、会话和插件 hooks,同时仍允许管理员托管 hooks,请设置 allow_managed_hooks_only = true

allow_managed_hooks_only = true
[features]
hooks = true
[hooks]
managed_dir = "/enterprise/hooks"
windows_managed_dir = 'C:\enterprise\hooks'
[[hooks.PreToolUse]]
matcher = "^Bash$"
[[hooks.PreToolUse.hooks]]
type = "command"
command = "python3 /enterprise/hooks/pre_tool_use_policy.py"
command_windows = 'py -3 C:\enterprise\hooks\pre_tool_use_policy.py'
timeout = 30
statusMessage = "Checking managed Bash command"

托管钩子的注意事项:

  • managed_dir 用于 macOS 和 Linux。
  • windows_managed_dir 用于 Windows。
  • Codex 不会分发 managed_dir 中的脚本;你的企业管理工具需要单独安装并更新这些脚本。
  • 托管钩子命令应使用配置的托管目录下的绝对脚本路径。
  • allow_managed_hooks_only = true 会跳过来自用户、项目、会话和插件来源的 hooks,但仍会加载 requirements.toml 和其他托管配置层中的托管 hooks。

当插件启用后,Codex 可以把该插件里的生命周期 hooks 与用户、项目和托管 hooks 一起加载。

默认情况下,Codex 会在插件根目录中查找 hooks/hooks.json。插件 manifest 可以通过 .codex-plugin/plugin.json 中的 hooks 条目覆盖这个默认位置。manifest 条目可以是一个 ./ 前缀路径、./ 前缀路径数组、内联 hooks 对象,或内联 hooks 对象数组。

{
"name": "repo-policy",
"hooks": "./hooks/hooks.json"
}

Manifest hook 路径会相对于插件根目录解析,并且必须留在该根目录内。如果 manifest 定义了 hooks,Codex 会使用这些 manifest 条目,而不是默认的 hooks/hooks.json

Plugin hook 命令会收到这些环境变量:

  • PLUGIN_ROOT 是 Codex 专用扩展,指向已安装插件根目录。
  • PLUGIN_DATA 是 Codex 专用扩展,指向插件的可写数据目录。
  • 为了兼容现有 plugin hooks,Codex 还会设置 CLAUDE_PLUGIN_ROOTCLAUDE_PLUGIN_DATA

Plugin hooks 使用和其他 hooks 相同的事件 schema。安装或启用插件并不会自动信任它的 hooks;Codex 会跳过 plugin-bundled hooks,直到你审核并信任当前 hook 定义。

matcher 字段是一个正则表达式字符串,用来过滤 hook 何时触发。使用 "*""",或完全省略 matcher,都表示匹配该事件的所有支持触发。

当前只有部分 Codex 事件真正会使用 matcher

事件 matcher 过滤的对象 说明
PermissionRequest 工具名 支持 Bashapply_patch* 和 MCP tool names。
PostToolUse 工具名 参见工具覆盖范围
PostCompact compact 触发源 值为 manualauto
PreCompact compact 触发源 值为 manualauto
PreToolUse 工具名 参见工具覆盖范围
SessionEnd 结束原因 当前只有 other
SessionStart 启动来源 值为 startupresumeclearcompact
SubagentStart 子智能体类型 值取决于启动的子智能体。
SubagentStop 子智能体类型 值取决于停止的子智能体。
UserPromptSubmit 不支持 该事件中配置的 matcher 会被忽略。
Stop 不支持 该事件中配置的 matcher 会被忽略。
  • apply_patchmatcher 值也可以使用 EditWrite

示例:

  • Bash
  • ^apply_patch$
  • Edit|Write
  • mcp__filesystem__read_file
  • mcp__filesystem__.*
  • startup|resume|clear|compact
  • manual|auto

PreToolUsePostToolUse 不只能够观察 shell 与 MCP 调用。大多数本地 function tools 使用同一条 hook 路径,因此你可以匹配工具名、检查其 JSON 参数,并通过 PreToolUse 阻止或改写调用。

工具路径 PreToolUse PostToolUse 说明
Shell 命令 Bash 匹配。
Unified exec(exec_command Bash 匹配。命令结束时,后续一次 write_stdin 轮询可能会送达原命令的 PostToolUse
apply_patch 可用 apply_patchEditWrite 匹配。
MCP tools 匹配 MCP tool name,例如 mcp__filesystem__read_file
其他本地 function tools 匹配 function tool name,例如 update_planspawn_agent 也会匹配 Agent
WebSearch 等托管工具 这些工具不使用本地 function-tool hook 路径。

write_stdin 是已有 unified-exec 会话的传输通道。它向已通过 PreToolUse 的命令发送输入或轮询状态时,不会再次运行 PreToolUse

某些专用工具路径可以选择不使用默认 hook 路径。请把工具 hooks 视为有用的护栏,而不是完整的强制边界。

每个命令型钩子都会通过 stdin 收到一个 JSON 对象。

这些共享字段通常最常用:

字段 类型 含义
session_id string 当前 Codex 会话 ID。子智能体 hooks 使用父会话 ID。
transcript_path string | null 会话 transcript 文件路径;如果不存在则为 null
cwd string 当前会话的工作目录。
hook_event_name string 当前 hook 事件名。
model string Codex 扩展字段。当前激活模型的 slug。

按会话轮次作用域运行的 hooks 会在各自的事件专属字段表里额外列出 turn_id

SessionStartPreToolUsePermissionRequestPostToolUseUserPromptSubmitSubagentStartSubagentStopStop 也会包含 permission_mode,表示当前权限模式,值可能是 defaultacceptEditsplandontAskbypassPermissions

transcript_path 只是为了方便指向聊天 transcript;transcript 格式不是 hooks 的稳定接口,未来可能变化。

如果你需要完整的当前线格式,请参见 Schema 定义

SessionStartPreCompactPostCompactUserPromptSubmitSubagentStopStop 支持以下共享 JSON 字段。SubagentStartsystemMessage 和 hook-specific context 接受相同结构,但 continue: false 不会阻止子智能体启动:

{
"continue": true,
"stopReason": "optional",
"systemMessage": "optional",
"suppressOutput": false
}
字段 作用
continue 若为 false,表示该次 hook 运行被标记为停止。
stopReason 记录为停止原因。
systemMessage 作为警告显示在界面或事件流中。
suppressOutput 当前会被解析,但尚未真正实现。

退出码为 0 且没有任何输出,会被视为成功,Codex 会继续执行。

PreToolUsePermissionRequest 支持 systemMessage,但当前不支持 continuestopReasonsuppressOutput。如果 PreToolUse hook 返回了这些不支持的字段,Codex 会把这次 hook 运行标记为失败、报告错误,并继续执行工具调用。

PostToolUse 支持 systemMessagecontinue: falsestopReasonsuppressOutput 虽然会被解析,但当前仍未真正支持。

Codex 会把每一条模型可见 hook 输出限制在大约 2,500 tokens。如果 hook 返回更多内容,Codex 会把完整文本保存到 <temp_dir>/hook_outputs/<session_id>/<uuid>.txt,并把包含文件路径的首尾预览交给模型。如果文件无法写入,模型仍会收到截断后的预览。

该限制适用于来自 SessionStartSubagentStartPreToolUsePostToolUseUserPromptSubmit 的额外上下文,来自 PostToolUse 的反馈,以及来自 StopSubagentStop 的继续提示。限制按每一条额外上下文或继续提示分别计算;对 PostToolUse 反馈,Codex 会先合并所有匹配 hooks 的反馈,再对合并后的消息应用限制。

由于过长输出可能写入磁盘,请避免在 hook 输出中返回 secrets 或其他敏感数据。

这个事件中的 matcher 会作用在 source 上。

通用输入字段 外,还会额外提供:

字段 类型 含义
source string 会话启动方式:startupresumeclearcompact

写到 stdout 的纯文本会被追加为额外的 开发者上下文。

如果向 stdout 输出 JSON,则支持 通用输出字段,以及下面这个该事件专属结构:

{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "Load the workspace conventions before editing."
}
}

其中 additionalContext 会被加入为额外的 开发者上下文。

SessionEnd 允许你在会话结束时运行命令,例如保存最终笔记或清理文件。它会在以下情况下为主对话线程运行:归档或删除仍处于打开状态的对话、Codex 正常关闭,或对话已空闲且在所有已连接客户端中均未打开达 30 分钟。它不会为子智能体运行。

切换到其他对话或调用 thread/unsubscribe 不会立即结束会话,因此也不会立即运行 SessionEnd。Hook 运行期间仍可读取会话 transcript。

该事件的 matcher 会过滤 reason。目前 reason 始终为 other。你可以省略 matcher,或使用 other 来匹配每个 SessionEnd 事件。

通用输入字段外,还会额外提供:

字段 类型 含义
reason string 会话结束原因:other

例如,SessionEnd 命令会收到:

{
"session_id": "thr_123",
"transcript_path": "/workspace/.codex/rollout.jsonl",
"cwd": "/workspace",
"hook_event_name": "SessionEnd",
"reason": "other"
}

SessionEnd hooks 只提供通知性质的结果。它们的输出不会引导 Codex,也不会让对话线程保持打开。如果命令超时或以错误退出,Codex 会把它报告为 hook failure。

这个事件中的 matcher 会作用在 agent_type 上。

通用输入字段 外,还会额外提供:

字段 类型 含义
turn_id string Codex 扩展字段。当前激活会话轮次的 ID。
agent_id string 子智能体标识。
agent_type string 子智能体类型或配置档案。
permission_mode string 当前权限模式。

写到 stdout 的纯文本会被追加为该子智能体的额外开发者上下文。

如果向 stdout 输出 JSON,则支持 systemMessage 和下面这个事件专属结构:

{
"hookSpecificOutput": {
"hookEventName": "SubagentStart",
"additionalContext": "Review the repository test conventions first."
}
}

其中 additionalContext 会被加入为该子智能体的额外开发者上下文。continue: false 会为了兼容而解析,但不会阻止子智能体启动。

PreToolUse 可以拦截 Bash、通过 apply_patch 完成的文件编辑、MCP tool calls 和其他本地 function tools。支持的路径与例外请参见工具覆盖范围

matcher 会作用在 tool_name 和 matcher aliases 上。对于通过 apply_patch 完成的文件编辑,matcher 值可以使用 apply_patchEditWrite;hook input 中仍会报告 tool_name: "apply_patch"

通用输入字段 外,还会额外提供:

字段 类型 含义
turn_id string Codex 扩展字段。当前激活会话轮次的 ID。
tool_name string 标准 hook 工具名,例如 Bashapply_patch,或 mcp__fs__read 这类 MCP 名称。
tool_use_id string 本次调用对应的 tool-call id。
tool_input JSON value 工具专属输入。Bashapply_patch 使用 tool_input.command,MCP 与其他本地 function tools 会发送各自的参数。

写到 stdout 的纯文本会被忽略。

如果向 stdout 输出 JSON,可以使用 systemMessage,也可以通过下面这个事件专属结构阻止 Bash 命令执行:

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

Codex 也接受旧版阻止格式:

{
"decision": "block",
"reason": "Destructive command blocked by hook."
}

你也可以直接使用退出码 2,并把阻止原因写到 stderr

如需在不阻止调用的情况下追加模型可见上下文,请返回 hookSpecificOutput.additionalContext

{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "The pending command touches generated files."
}
}

若要在不阻止调用的情况下改写受支持的工具调用,请返回 permissionDecision: "allow" 并附带 updatedInput

{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"command": "echo rewritten"
}
}
}

对于 Bash 命令和 apply_patchupdatedInput 必须包含字符串类型的 command 字段。对于 MCP 与其他本地 function tools,updatedInput 是替换后的参数对象。只应在 permissionDecision: "allow" 时返回 updatedInput;其他 updatedInput 形态会被报告为错误。

permissionDecision: "ask"、旧版 decision: "approve"continue: falsestopReasonsuppressOutput 虽然会被解析,但目前尚未支持。Codex 会把这次 hook 运行标记为失败、报告错误,并继续执行工具调用。

PermissionRequest 会在 Codex 即将请求审批时运行,例如 shell 提权或托管网络审批。它可以允许请求、拒绝请求,或者不做决定并让常规审批提示继续显示。它不会在不需要审批的命令上运行。

matcher 会作用在 tool_name 和 matcher aliases 上。当前标准值包括 Bashapply_patch,以及 mcp__server__tool 这类 MCP tool names;apply_patch 也会匹配 EditWrite

通用输入字段 外,还会额外提供:

字段 类型 含义
turn_id string Codex 扩展字段。当前激活会话轮次的 ID。
tool_name string 标准 hook 工具名,例如 Bashapply_patch,或 mcp__fs__read 这类 MCP 名称。
tool_input JSON value 工具专属输入。Bashapply_patch 使用 tool_input.command,MCP tools 会发送所有参数。
tool_input.description string | null Codex 提供时的人类可读审批原因。

写到 stdout 的纯文本会被忽略。

某些工具输入可能包含人类可读的说明,但不要假设每个工具都会提供 tool_input.description 字段。

如需批准请求,请返回:

{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "allow"
}
}
}

如需拒绝请求,请返回:

{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "deny",
"message": "Blocked by repository policy."
}
}
}

如果多个命中的 hook 都返回了 decision,任意 deny 都会优先生效。否则,一个 allow 会让请求继续执行,并且不再显示审批提示。如果没有命中的 hook 做出决定,Codex 会使用正常审批流程。

不要为 PermissionRequest 返回 updatedInputupdatedPermissionsinterrupt;这些字段预留给未来行为,目前会按关闭失败处理。

PostToolUse 会在受支持工具产生输出后运行,包括 Bash、apply_patch、MCP tool calls 和其他本地 function tools。对 Bash 来说,命令以非零状态退出后也会运行。它无法撤销已经执行过的工具副作用。支持的路径与例外请参见工具覆盖范围

matcher 会作用在 tool_name 和 matcher aliases 上。对于通过 apply_patch 完成的文件编辑,matcher 值可以使用 apply_patchEditWrite;hook input 中仍会报告 tool_name: "apply_patch"

通用输入字段 外,还会额外提供:

字段 类型 含义
turn_id string Codex 扩展字段。当前激活会话轮次的 ID。
tool_name string 标准 hook 工具名,例如 Bashapply_patch,或 mcp__fs__read 这类 MCP 名称。
tool_use_id string 本次调用对应的 tool-call id。
tool_input JSON value 工具专属输入。Bashapply_patch 使用 tool_input.command,MCP 与其他本地 function tools 会发送各自的参数。
tool_response JSON value 工具专属输出。MCP tools 会发送 MCP 调用结果;其他本地 function tools 通常发送模型可见输出。

写到 stdout 的纯文本会被忽略。

如果向 stdout 输出 JSON,可以使用 systemMessage,并支持下面这个事件专属结构:

{
"decision": "block",
"reason": "The Bash output needs review before continuing.",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "The command updated generated files."
}
}

其中 additionalContext 会被加入为额外的 开发者上下文。

对这个事件来说,decision: "block" 不会撤销已经完成的 Bash 命令。相反,Codex 会记录这条反馈,用该反馈替换原始工具结果,并从 hook 提供的消息继续驱动模型。

你也可以使用退出码 2,并把反馈原因写到 stderr

如果你想在命令已经执行后,阻止对原始工具结果的正常处理,可以返回 continue: false。Codex 会用你的反馈或停止文本替换原始工具结果,然后从那里继续。

updatedMCPToolOutputsuppressOutput 会被解析,但当前尚未真正支持。Codex 会把这次 hook 运行标记为失败、报告错误,并继续正常处理工具结果。

模型通过 code mode 在 JavaScript 中调用工具时,hook decision 会应用到该嵌套调用。PreToolUse 可以在工具运行前阻止调用或改写输入。阻止型 PostToolUse 无法撤销工具副作用,但可以阻止原始结果送达正在运行的脚本。

Hook 结果 Code mode 收到的行为
PreToolUse 阻止调用 工具运行前,tool promise 会 reject。
PreToolUse 返回 updatedInput 工具使用改写后的输入运行,promise 以该结果 resolve。
PostToolUse 返回 decision: "block" 或以退出码 2 结束 工具先运行,随后 promise 会以 hook 原因 reject。
PostToolUse 返回 continue: false Codex 使用 hook 反馈作为模型可见结果,但不会 reject 嵌套 tool promise。

PreCompact 会在 Codex 压缩对话之前运行。matcher 会作用在 trigger 上,取值为 manualauto

通用输入字段 外,还会额外提供:

字段 类型 含义
turn_id string Codex 扩展字段。当前激活会话轮次的 ID。
trigger string 触发压缩的来源:manualauto

写到 stdout 的纯文本会被忽略。

写到 stdout 的 JSON 支持通用输出字段。如果匹配的 PreCompact hook 返回 continue: false,Codex 会在压缩前停止。

PostCompact 会在 Codex 压缩对话之后运行。matcher 会作用在 trigger 上,取值为 manualauto

通用输入字段 外,还会额外提供:

字段 类型 含义
turn_id string Codex 扩展字段。当前激活会话轮次的 ID。
trigger string 触发压缩的来源:manualauto

写到 stdout 的纯文本会被忽略。

写到 stdout 的 JSON 支持通用输出字段。如果匹配的 PostCompact hook 返回 continue: false,Codex 会在压缩后停止。

matcher 当前对这个事件不起作用。

通用输入字段 外,还会额外提供:

字段 类型 含义
turn_id string Codex 扩展字段。当前激活会话轮次的 ID。
prompt string 即将发送的用户提示词。

写到 stdout 的纯文本会被加入为额外的开发者上下文。

如果向 stdout 输出 JSON,则支持 通用输出字段 和下面这个事件专属结构:

{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "Ask for a clearer reproduction before editing files."
}
}

其中 additionalContext 会被加入为额外的 开发者上下文。

如果你想阻止这条提示词,可返回:

{
"decision": "block",
"reason": "Ask for confirmation before doing that."
}

你也可以使用退出码 2,并把阻止原因写到 stderr

这个事件中的 matcher 会作用在 agent_type 上。

通用输入字段 外,还会额外提供:

字段 类型 含义
turn_id string Codex 扩展字段。当前激活会话轮次的 ID。
agent_id string 子智能体标识。
agent_type string 子智能体类型或配置档案。
agent_transcript_path string | null 子智能体 transcript 文件路径;如果不存在则为 null
stop_hook_active boolean 这个子智能体是否已经被继续过。
last_assistant_message string | null 最新子智能体 assistant 消息;如果不可用则为 null

SubagentStop 在退出码为 0 时需要向 stdout 输出 JSON。对于这个事件,纯文本输出是无效的。

输出 JSON 时,支持通用输出字段。如果你想让 Codex 继续子智能体流程,可返回:

{
"decision": "block",
"reason": "Run one more focused pass inside the subagent."
}

你也可以使用退出码 2,并把继续执行的原因写到 stderr

如果有任意一个匹配的 SubagentStop hook 返回 continue: false,它会优先于其他匹配 SubagentStop hooks 的 continuation 决策生效。

matcher 当前对这个事件不起作用。

通用输入字段 外,还会额外提供:

字段 类型 含义
turn_id string Codex 扩展字段。当前激活会话轮次的 ID。
stop_hook_active boolean 当前这个会话轮次是否已经被 Stop 继续过一次。
last_assistant_message string | null 最新 assistant 消息文本;如果不可用则为 null

Stop 要求在退出码为 0 时向 stdout 输出 JSON。对于这个事件,纯文本输出是无效的。

输出 JSON 时,支持 通用输出字段。如果你想让 Codex 继续运行,可返回:

{
"decision": "block",
"reason": "Run one more pass over the failing tests."
}

你也可以使用退出码 2,并把继续执行的原因写到 stderr

对这个事件来说,decision: "block" 并不会拒绝当前会话轮次。相反,它会告诉 Codex 继续,并自动创建一条继续执行提示词,把你的 reason 当作新的用户提示词发送下去。

如果有任意一个命中的 Stop hook 返回 continue: false,它会优先于其他 Stop hooks 的 continuation 决策生效。

链接指向的 main 分支 schema 可能包含当前版本尚未提供的 hook 字段。请以本页说明作为当前版本的行为参考。

如果你需要当前精确的线格式,请查看 Codex GitHub 仓库 中生成的 schema。

使用“钩子”扩展 Codex 时,只启用当前任务需要的能力,并检查其可访问的数据与可执行操作。团队共享前应先完成权限和失败场景测试。

在实践“钩子”相关功能时,如需为 Codex 配置 OpenAI-compatible API,可以前往 APIBest 获取 API Key。第三方服务的模型映射、价格、额度和数据处理方式以 APIBest 当前说明为准。