從寫程式碼,到創作下一幕

探索 字節跳動 - 火山方舟 的 AI 程式設計與影片創作活動。

Agent Plan & Coding Plan

一站體驗多款熱門模型,為 AI 程式設計與智能體開發提供更多選擇。新使用者可聯絡(微信: goo_lvyouyou)免費體驗 9.9 agent plan。

Seedance 2.5

讓創意,躍然成片。探索 30 秒影片、多模態參考與局部編輯,把腦海中的畫面變成下一支作品。

繁體中文

鉤子

在 Codex 生命週期中執行確定性指令碼

鉤子是 Codex 的可擴展性框架。你可以藉助它們在智能體迴圈期間執行指令碼或 MCP 工具,從而實現以下功能:

  • 將聊天傳送到自定義日誌記錄/分析引擎
  • 掃描團隊的提示詞,防止意外貼上 API key
  • 彙總聊天內容,自動建立持久記憶
  • 在一輪聊天停止時執行自定義驗證檢查,以強制執行標準
  • 在特定目錄中自定義提示方式

鉤子的執行方式:

  • 來自多個檔案的所有匹配鉤子都會執行。
  • 同一事件的多個匹配命令鉤子會並發啟動, 因此一個鉤子無法阻止另一個匹配鉤子啟動。
  • 非受管鉤子必須先經過審查並受信任,才能執行。

鉤子會在對話的不同階段執行:

時機 鉤子
在一個輪次期間 PreToolUse、PermissionRequest、PostToolUse、PreCompact、PostCompact、UserPromptSubmit、SubagentStop、Stop
當你中斷活躍輪次時 Interrupt(不為子智能體執行)
當會話或子智能體啟動時 SessionStart、SubagentStart
當主聊天結束時 SessionEnd(不為子智能體執行)

Codex 在哪裡尋找鉤子

Codex 會在活躍設定層旁邊尋找以下任一形式的鉤子:

  • hooks.json
  • config.toml 內的內聯 [hooks] 表

已安裝的外掛也可以通過其外掛清單或預設的 hooks/hooks.json 檔案捆綁生命週期設定。 有關外掛打包規則,請參閱建置 外掛。

實際使用中,最有用的四個位置是:

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

如果存在多個鉤子來源,Codex 會載入所有匹配的鉤子。 優先順序較高的設定層不會替換優先順序較低的鉤子。 如果同一層同時包含 hooks.json 和內聯 [hooks],Codex 會合併二者並在啟動時發出警告。每一層最好只使用一種表示方式。

Codex 還可以發現已啟用外掛中捆綁的鉤子。外掛捆綁的 鉤子會與其他鉤子來源一同載入,並採用與 其他非受管鉤子相同的信任審查流程。

僅當專案 .codex/ 層受信任時,才會載入專案本機鉤子。在 不受信任的專案中,Codex 仍會從各自的活躍設定層載入使用者和系統鉤子。

審查和信任鉤子

Codex 會先列出已設定的鉤子,再決定哪些可以執行。在 非受管鉤子執行之前,Codex 要求你審查並信任其確切的鉤子 定義。Codex 會針對鉤子當前的雜湊值記錄信任狀態,因此新增或 更改後的鉤子會被標記為待審查,並在獲得信任前跳過。

在 CLI 中使用 /hooks 可檢查鉤子來源、審查新增或更改的鉤子、 信任鉤子,或停用單個非受管鉤子。如果啟動時有鉤子需要審查, Codex 會輸出警告,提示你開啟 /hooks。

來自系統、MDM、雲端或 requirements.toml 來源的受管鉤子會被標記為 受管項,根據策略受到信任,並且無法從使用者鉤子瀏覽器中停用。

對於已在 Codex 外部審查鉤子來源的一次性自動化任務,可傳入 --dangerously-bypass-hook-trust,從而在該次呼叫中執行已啟用的鉤子,且無需 持久儲存鉤子信任狀態。

設定結構

鉤子分為三個層級:

  • 鉤子 事件,例如 PreToolUse、PostToolUse、PreCompact、 SubagentStart 或 Stop
  • 用於決定該事件何時匹配的匹配器組
  • 匹配器組命中時執行的一個或多個鉤子處理程序
{
  "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",
            "additionalContextLimit": 5000
          }
        ]
      }
    ],
    "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
          }
        ]
      }
    ]
  }
}

注意:

  • description 是 hooks.json 檔案的可選頂層後設資料。它 不會改變要執行哪些鉤子。
  • timeout 的單位為秒。
  • 如果省略 timeout,Codex 會對大多數鉤子使用 600 秒。
    • SessionEnd 和 Interrupt 預設使用 1 秒,最大支援 3 秒。
  • statusMessage 是可選的。
  • additionalContextLimit 設定命令鉤子可向模型傳送多少 additionalContext, 超出後 Codex 會將完整文本儲存到磁碟,並改為傳送較短的 預覽。請參閱大型鉤子輸出。
  • commandWindows 是僅適用於 Windows 的可選命令覆蓋項。在 TOML 中,請使用 command_windows 或 commandWindows。
  • 將 async 設為 true,可在後臺執行命令鉤子。
  • 支援 command 和 mcp_tool 處理程序。prompt 和 agent 處理程序會被解析,但會跳過執行。
  • 命令會以會話的 cwd 作為工作目錄執行。
  • 對於儲存庫本機鉤子,建議從 git 根目錄解析路徑,而不是使用 .codex/hooks/... 之類的相對路徑。Codex 可能從 子目錄啟動,而基於 git 根目錄的路徑可以保持鉤子位置穩定。

config.toml 中等效的內聯 TOML:

[[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"

[[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"

MCP 工具鉤子

MCP 工具鉤子允許生命週期事件呼叫已連線 MCP server上的工具。它會將結構化參數直接傳送給該工具,並採用與命令鉤子 相同的信任審查和輸出約定。

設定 MCP 工具鉤子

此鉤子會要求 scanner MCP server 在 Codex 寫入或 編輯檔案後掃描每個補丁:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "mcp_tool",
            "server": "scanner",
            "tool": "scan_patch",
            "input": { "patch": "${tool_input.command}" },
            "timeout": 30,
            "statusMessage": "Scanning edited files"
          }
        ]
      }
    ]
  }
}
欄位 含義
type 必須為 mcp_tool。
server 已連線 MCP server 的名稱,必填。
tool 該伺服器所公開工具的名稱,必填。
input 可選的參數模板 JSON 物件。預設為 {}。
timeout 可選的活躍執行超時時間,單位為秒。預設為 600。
statusMessage 鉤子 執行時顯示的可選訊息。

根據鉤子事件展開參數

使用 ${field.nested} 讀取鉤子事件中的點號分隔欄位。如果佔位符 填充整個值,則會保留其 JSON 類型。如果佔位符位於較長的 字串中,則會呈現為文本。Codex 會遞迴展開物件和陣列。

對於包含 {"tool_input":{"file_path":"src/main.rs","count":3}} 的事件, 以下參數模板:

{
  "path": "${tool_input.file_path}",
  "count": "${tool_input.count}",
  "message": "Scanning ${tool_input.file_path}"
}

會變為:

{
  "path": "src/main.rs",
  "count": 3,
  "message": "Scanning src/main.rs"
}

執行和生命週期

  • 鉤子使用現有 MCP 連線,不會啟動或重新連線伺服器。
  • 當工具傳回阻止決定時,鉤子可以阻止操作。 錯誤、伺服器缺失和工具不可用不會阻止操作。
  • MCP 工具鉤子會同步執行。它們不會請求工具核准,也不會觸發 其他鉤子。
  • 以鉤子或伺服器中較短的超時時間為準。等待 MCP 引導響應所用的時間不計入超時。
  • SessionStart 鉤子可能在 MCP server 準備就緒前執行。如果發生這種情況, 它們不會阻止會話。
  • SessionEnd 不支援 MCP 工具鉤子。

關閉鉤子

鉤子預設啟用。要在 config.toml 中將其關閉,請設定:

[features]
hooks = false

使用 hooks 作為功能鍵。codex_hooks 仍可用作 已棄用的別名。管理員也可以在 requirements.toml 中使用 [features].hooks = false,以同樣的方式強制關閉鉤子。

來自 requirements.toml 的受管鉤子

啟用受管策略和遠端鉤子後,具有本機存取權限的 Work Cloud 和 dots 會在雲端編排器上使用由管理員管理的遠端 MCP 鉤子。在全域 requirements.toml 中設定 mcp_tool 處理程序。不具有本機存取權限的 Work Cloud 和個人帳戶不使用這些企業鉤子。雲端編排不支援命令/shell、提示詞和智能體處理程序;來自本機設定、外掛或本機目錄的鉤子;限定於環境的鉤子;以及 SessionEnd MCP 鉤子,即使工具在本機執行也是如此。當編排和執行都在本機進行時,現有受支援的鉤子仍可在僅本機執行的 Work 和 Codex 聊天中使用。管理員仍可在 Agent Security 中為這些工作流程設定受支援的受管鉤子。

在依賴這些鉤子之前,請測試回呼連通性、所需事件和失敗時的行為。受支援的顯式拒絕可以阻止操作,但 PreToolUse 回呼出錯、超時或響應格式錯誤可能導致鉤子失敗,卻不會阻止工具執行。MCP 鉤子不提供完整的 Compliance API 審計記錄。

本節中的 Codex 說明仍適用於受支援的 Codex 工作流程。在為 Work Cloud 啟用本機電腦存取之前,請檢視同步設定和 Agent Security 中的相容性警告。參閱受管設定。

在 Codex 中,企業管理的要求可以在 [hooks] 下內聯定義鉤子。 下面的命令鉤子範例僅適用於 Codex。 當管理員希望強制執行鉤子設定,同時 通過 MDM 或其他裝置管理系統分發實際指令碼時,這種方式很有用。 要對在本機停用鉤子的使用者也強制啟用受管鉤子,請 在 requirements.toml 中與 [hooks] 一起固定設定 [features].hooks = true。要忽略 使用者、專案、會話和外掛鉤子,同時仍允許管理員 管理的鉤子,請設定 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 會跳過來自使用者、專案、會話和 外掛來源的鉤子,但仍會載入來自 requirements.toml 和 其他受管設定層的受管鉤子。

外掛捆綁的鉤子

啟用外掛後,Codex 可以載入該外掛中的生命週期鉤子, 並與使用者、專案和受管鉤子一同執行。

預設情況下,Codex 會在外掛根目錄中尋找 hooks/hooks.json。外掛 清單可以使用 .codex-plugin/plugin.json 中的 hooks 條目替代該預設設定。 清單條目可以是以 ./ 為字首的路徑、以 ./ 為字首的路徑陣列、 內聯鉤子物件,或內聯鉤子物件陣列。

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

清單鉤子路徑相對於外掛根目錄解析,且必須位於 該根目錄之內。如果清單定義了 hooks,Codex 將使用這些清單 條目,而不是預設的 hooks/hooks.json。

外掛鉤子命令會收到以下環境變數:

  • PLUGIN_ROOT 是 Codex 專用環境變數,指向已安裝的 外掛根目錄。
  • PLUGIN_DATA 是 Codex 專用環境變數,指向外掛的 可寫資料目錄。
  • Codex 還會設定 CLAUDE_PLUGIN_ROOT 和 CLAUDE_PLUGIN_DATA,以便 與現有外掛鉤子保持相容。

外掛鉤子與其他鉤子使用相同的事件資料結構。安裝或啟用 外掛並不會自動信任其鉤子;在你審查並信任當前鉤子定義前, Codex 會跳過外掛捆綁的鉤子。

匹配器模式

matcher 欄位是一個正規表示式字串,用於篩選鉤子何時觸發。使用 "*"、 "",或完全省略 matcher,即可匹配受支援事件的每次 出現。

目前只有部分 Codex 事件會採用 matcher:

事件 matcher 的篩選物件 說明
PermissionRequest 工具名稱 支援 Bash、apply_patch* 和 MCP 工具名稱
PostToolUse 工具名稱 請參閱工具覆蓋範圍
PostCompact 壓縮觸發方式 值為 manual 或 auto
PreCompact 壓縮觸發方式 值為 manual 或 auto
PreToolUse 工具名稱 參見工具覆蓋範圍
SessionEnd 結束原因 當前僅支援 other
SessionStart 啟動來源 值為 startup、resume、clear、compact 和 fork
SubagentStart 子智能體類型 值取決於所啟動的子智能體
SubagentStop 子智能體類型 值取決於所停止的子智能體
UserPromptSubmit 不支援 為此事件設定的任何 matcher 都會被忽略
Stop 不支援 為此事件設定的任何 matcher 都會被忽略
Interrupt 不支援 為此事件設定的任何 matcher 都會被忽略

*對於 apply_patch,matcher 值也可以使用 Edit 或 Write。

範例:

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

工具覆蓋範圍

PreToolUse 和 PostToolUse 可以觀察 shell 和 MCP 呼叫之外的操作。大多數 本機函式工具都使用相同的鉤子路徑,因此你可以匹配其工具名稱、 檢查其 JSON 參數,並通過 PreToolUse 阻止或重寫呼叫。

工具路徑 PreToolUse PostToolUse 備註
Shell 命令 是 是 匹配為 Bash。
統一執行(exec_command) 是 是 匹配為 Bash。後續 write_stdin 輪詢可在原始命令完成時傳遞其 PostToolUse。
apply_patch 是 是 匹配為 apply_patch、Edit 或 Write。
MCP 工具 是 是 匹配 MCP 工具名稱,例如 mcp__filesystem__read_file。
其他本機函式工具 是 是 匹配函式工具名稱,例如 update_plan。spawn_agent 也會匹配 Agent。
託管工具,例如 WebSearch 否 否 這些工具不使用本機函式工具鉤子路徑。

write_stdin 是現有統一執行會話的傳輸機制。它在傳送輸入或輪詢 已通過 PreToolUse 的命令時,不會再次執行 PreToolUse。

某些專用工具路徑可以選擇不使用預設鉤子路徑。請將工具 鉤子視為實用的防護機制,而不是完整的強制執行邊界。

通用輸入欄位

每個命令鉤子都會在 stdin 上接收一個 JSON 物件。

以下是通常會用到的共享欄位:

欄位 類型 含義
session_id string 當前 Codex 會話 ID。子智能體鉤子使用父會話 ID。
transcript_path string | null 會話轉錄檔案的路徑(如果有)
cwd string 會話的工作目錄
hook_event_name string 當前鉤子事件名稱
model string Codex 專用欄位。活躍模型 slug

輪次範圍的鉤子會在其事件專用表中將 turn_id 列為 Codex 專用欄位。

SessionStart、PreToolUse、PermissionRequest、PostToolUse、 UserPromptSubmit、SubagentStart、SubagentStop、Stop 和 Interrupt 還會包含 permission_mode,用於描述當前權限模式,其值為 default、 acceptEdits、plan、dontAsk 或 bypassPermissions。

為了方便使用,transcript_path 指向聊天轉錄,但 轉錄格式並非鉤子的穩定介面,可能會隨時間變化。

如需完整的傳輸格式,請參閱資料結構。

通用輸出欄位

SessionStart、PreCompact、PostCompact、UserPromptSubmit、 SubagentStop 和 Stop 支援以下共享 JSON 欄位。SubagentStart 為 systemMessage 和鉤子專用上下文接受相同的結構,但 continue: false 不會停止子智能體:

{
  "continue": true,
  "stopReason": "optional",
  "systemMessage": "optional",
  "suppressOutput": false
}
欄位 效果
continue 如果為 false,將該次鉤子執行標記為已停止
stopReason 記錄為停止原因
systemMessage 在 UI 或事件流中顯示為警告
suppressOutput 目前會被解析,但尚未實現

退出碼為 0 且沒有輸出時會被視為成功,Codex 將繼續執行。

PreToolUse 和 PermissionRequest 支援 systemMessage,但目前這些事件不支援 continue、stopReason 和 suppressOutput。 如果 PreToolUse 鉤子傳回其中一個不受支援的欄位,Codex 會將 該次鉤子執行標記為失敗、報告錯誤,然後繼續工具呼叫。

PostToolUse 支援 systemMessage、continue: false 和 stopReason。 suppressOutput 會被解析,但目前不支援用於該事件。

大型鉤子輸出

預設情況下,Codex 會將每條模型可見的鉤子輸出訊息限制在約 2,500 個 token。如果鉤子傳回的內容更多,Codex 會將完整文本儲存到 <temp_dir>/hook_outputs/<session_id>/<uuid>.txt 下,並向模型提供包含已儲存檔案路徑的 首尾預覽。此行為稱為 溢位:Codex 將過大的輸出儲存到磁碟,並替換為 模型可見的較短預覽。如果檔案無法寫入,模型仍會 收到截斷後的預覽。

對於任何傳回 additionalContext 的命令鉤子,可在處理程序上設定 additionalContextLimit,以自定義大致的 token 閾值:

{
  "type": "command",
  "command": "python3 ~/.codex/hooks/session_start.py",
  "additionalContextLimit": 5000
}

省略 additionalContextLimit 即可使用預設的 2500 token 閾值。使用 正整數可選擇其他閾值,使用 0 則可將處理程序的 完整附加上下文直接傳給模型。Codex 會單獨評估每個 匹配的處理程序。對於無法生成附加 上下文的事件,Codex 會忽略 additionalContextLimit 並報告設定 警告。

該設定僅適用於 additionalContext。工具回饋和續接 提示詞仍使用預設限制。

由於過大的輸出可能會寫入磁碟,請避免在鉤子輸出中傳回金鑰或 其他敏感資料。

在後臺執行鉤子

預設情況下,Codex 會等待命令鉤子完成,再繼續執行 觸發它的操作。將 async 設為 true,即可在 Codex 繼續執行的同時, 在後臺執行命令鉤子。

設定後臺鉤子

在 hooks.json 的命令處理程序中新增 "async": true:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.codex/hooks/post_tool_use.py",
            "async": true,
            "timeout": 120
          }
        ]
      }
    ]
  }
}

對於 config.toml 中的內聯鉤子,請設定 async = true:

[[hooks.PostToolUse]]
matcher = "Bash"

[[hooks.PostToolUse.hooks]]
type = "command"
command = "python3 ~/.codex/hooks/post_tool_use.py"
async = true
timeout = 120

後臺鉤子與同步命令鉤子使用相同的輸入、matcher、信任審查、超時和 大型輸出處理方式。與其他命令鉤子一樣,timeout 以秒為單位,預設值為 600。Interrupt 鉤子的預設超時時間為一秒,上限為三秒, 在後臺執行時也是如此。

後臺鉤子的執行方式

後臺鉤子完成後,Codex 會在對話中的下一個安全時機傳遞 受支援的資訊性輸出:

  • 如果一輪對話正在進行,Codex 會等待當前模型請求和工具呼叫 完成,然後讓該輸出可供本輪中的下一次模型請求使用。
  • 如果當前沒有進行中的輪次,Codex 會等到下一個使用者輪次。後臺 鉤子完成不會啟動新的輪次。

請使用與同步鉤子相同的事件專用 JSON 輸出。Codex 會將 additionalContext 新增到模型上下文,並將 systemMessage 顯示為 警告。

限制

  • Codex 在每個會話中最多並發運行八個後臺鉤子。其他 鉤子會等待執行中的鉤子完成。
  • 每次匹配的呼叫都會獨立執行,後臺鉤子完成的 順序可能與啟動順序不同。
  • 會話結束時,Codex 會取消尚未完成的後臺鉤子,並丟棄 尚未傳遞的輸出。
  • SessionEnd 鉤子始終同步執行。

鉤子

SessionStart

此事件會將 matcher 應用於 source。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
source string 會話的啟動方式:startup、resume、clear、compact 或 fork

派生的執行緒使用 source: "fork"。使用提供的歷史記錄恢復執行緒時, 仍使用 source: "resume"。

stdout 上的純文本會被新增為額外的開發者上下文。

stdout 中的 JSON 支援通用輸出欄位以及 以下鉤子專用結構:

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

其中的 additionalContext 文本會被新增為額外的開發者上下文。

Codex 壓縮根會話後,匹配 source: "compact" 的 SessionStart 鉤子會在下一次模型請求前執行。這也適用於 在一輪對話中途發生自動壓縮的情況:Codex 會將鉤子的 附加上下文傳遞給緊隨其後的續接過程,而不是等待 後續使用者輪次。如果鉤子傳回 continue: false,Codex 會結束該輪, 不再傳送模型請求。

SessionEnd

SessionEnd 允許你在會話結束時執行命令,例如儲存最終 備註或清理檔案。它會在以下情況下為主聊天執行:你歸檔或 刪除仍處於開啟狀態的對話、Codex 正常關閉,或某個 對話已閒置 30 分鐘且未在任何已連線的客戶端中開啟。 它不會為子智能體執行。

切換到其他對話或呼叫 thread/unsubscribe 不會立即結束 會話,因此不會立即執行 SessionEnd。鉤子 在執行時 仍可讀取會話轉錄。

此事件使用 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 鉤子始終同步執行,即使 async 為 true。它們 僅提供建議,因此其輸出不會引導 Codex,也不會讓執行緒保持開啟。如果 命令超時或以錯誤退出,Codex 會將其報告為鉤子失敗。

SubagentStart

此事件會將 matcher 應用於 agent_type。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
turn_id string Codex 專用欄位。活躍的 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

PreToolUse 可以攔截 Bash、通過 apply_patch 執行的檔案編輯、 MCP 工具呼叫以及其他本機函式工具。有關受支援的路徑和例外情況, 請參閱工具覆蓋範圍。

matcher 會應用於 tool_name 及匹配器別名。對於通過 apply_patch 進行的檔案編輯,matcher 值可以使用 apply_patch、Edit 或 Write;鉤子輸入 仍會報告 tool_name: "apply_patch"。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
turn_id string Codex 專用欄位。活躍的 Codex 輪次 ID
tool_name string 規範鉤子工具名稱,例如 Bash、apply_patch,或 mcp__fs__read 之類的 MCP 名稱
tool_use_id string 此次呼叫的工具呼叫 ID
tool_input JSON value 工具專用輸入。Bash 和 apply_patch 使用 tool_input.command。MCP 和其他本機函式工具會傳送其參數。

stdout 上的純文本會被忽略。

stdout 上的 JSON 可以使用 systemMessage。要拒絕受支援的工具呼叫,請傳回 以下鉤子專用結構:

{
  "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."
  }
}

要在不阻止操作的情況下重寫受支援的工具呼叫,請傳回 包含 updatedInput 的 permissionDecision: "allow":

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

對於 Bash 命令和 apply_patch,updatedInput 必須包含字串 command 欄位。對於 MCP 和其他本機函式工具,updatedInput 是 替代參數物件。僅將 updatedInput 與 permissionDecision: "allow" 一同傳回;其他 updatedInput 結構會被報告為 錯誤。

permissionDecision: "ask"、舊版 decision: "approve"、continue: false、 stopReason 和 suppressOutput 會被解析,但尚不受支援。Codex 會將 該次鉤子執行標記為失敗、報告錯誤,然後繼續工具呼叫。

PermissionRequest

當 Codex 即將請求核准時(例如 shell 權限提升或受管網路核准), PermissionRequest 會執行。它可以允許請求、拒絕請求, 也可以不作決定,讓正常的核准提示繼續出現。 對於無需核准的命令,它不會執行。

matcher 會應用於 tool_name 及匹配器別名。目前的規範 值包括 Bash、apply_patch 和 mcp__server__tool 等 MCP 工具名稱; apply_patch 也會匹配 Edit 和 Write。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
turn_id string Codex 專用欄位。活躍的 Codex 輪次 ID
tool_name string 規範鉤子工具名稱,例如 Bash、apply_patch,或 mcp__fs__read 之類的 MCP 名稱
tool_input JSON value 工具專用輸入。Bash 和 apply_patch 使用 tool_input.command,而 MCP 工具會傳送所有參數。
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."
    }
  }
}

如果多個匹配鉤子傳回決定,則任何 deny 都優先。否則, allow 會讓請求繼續,而不顯示核准提示。如果沒有 匹配的鉤子作出決定,Codex 會使用正常的核准流程。

請勿為 PermissionRequest 傳回 updatedInput、updatedPermissions 或 interrupt; 這些欄位為未來行為預留,目前會拒絕請求並終止相應操作。

PostToolUse

PostToolUse 會在受支援的工具產生輸出後執行,包括 Bash、 apply_patch、MCP 工具呼叫及其他本機函式工具。對於 Bash, 它也會在命令以非零狀態退出後執行。它無法撤銷 已執行工具產生的副作用。有關受支援的路徑和例外情況, 請參閱工具覆蓋範圍。

matcher 會應用於 tool_name 及匹配器別名。對於通過 apply_patch 進行的檔案編輯,matcher 值可以使用 apply_patch、Edit 或 Write;鉤子輸入 仍會報告 tool_name: "apply_patch"。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
turn_id string Codex 專用欄位。活躍的 Codex 輪次 ID
tool_name string 規範鉤子工具名稱,例如 Bash、apply_patch,或 mcp__fs__read 之類的 MCP 名稱
tool_use_id string 此次呼叫的工具呼叫 ID
tool_input JSON value 工具專用輸入。Bash 和 apply_patch 使用 tool_input.command。MCP 和其他本機函式工具會傳送其參數。
tool_response JSON value 工具專用輸出。MCP 工具會傳送 MCP 呼叫結果。其他本機函式工具通常會傳送面向模型的輸出。

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 會記錄回饋、用該回饋替換工具結果, 並從鉤子提供的訊息處繼續執行模型。

你也可以使用退出碼 2,並將回饋原因寫入 stderr。

要在命令已經執行後停止對原始工具結果的正常處理, 請傳回 continue: false。Codex 會用你的回饋或停止文本替換工具結果, 然後從此處繼續。

updatedMCPToolOutput 和 suppressOutput 會被解析,但尚不受支援。 Codex 會將該次鉤子執行標記為失敗、報告錯誤,然後繼續 正常處理工具結果。

程式碼模式中的工具呼叫

當模型在程式碼模式下通過 JavaScript 呼叫工具時,鉤子決定會應用於 該巢狀呼叫。PreToolUse 可以在工具執行前將其停止或重寫 其輸入。具有阻止作用的 PostToolUse 無法撤銷工具的副作用,但可以 阻止原始結果到達正在執行的指令碼。

鉤子 結果 程式碼模式看到的內容
PreToolUse 阻止 工具 promise 會在工具執行前被拒絕。
PreToolUse 傳回 updatedInput 工具使用重寫後的輸入執行,promise 以該結果兌現。
PostToolUse 傳回 decision: "block" 或以結束代碼 2 退出 工具先執行,然後 promise 會以鉤子原因為由被拒絕。
PostToolUse 傳回 continue: false Codex 將鉤子回饋用作模型可見結果,但不會拒絕巢狀工具 promise。

PreCompact

PreCompact 會在 Codex 壓縮聊天前執行。matcher 會應用於 trigger,其值為 manual 和 auto。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
turn_id string Codex 專用欄位。活躍的 Codex 輪次 ID
trigger string 壓縮的觸發方式:manual 或 auto

stdout 上的純文本會被忽略。

stdout 上的 JSON 支援通用輸出欄位。如果匹配的 PreCompact 鉤子傳回 continue: false,Codex 會在壓縮前停止。

PostCompact

PostCompact 會在 Codex 壓縮聊天後執行。matcher 會應用於 trigger,其值為 manual 和 auto。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
turn_id string Codex 專用欄位。活躍的 Codex 輪次 ID
trigger string 壓縮的觸發方式:manual 或 auto

stdout 上的純文本會被忽略。

stdout 上的 JSON 支援通用輸出欄位。如果匹配的 PostCompact 鉤子傳回 continue: false,Codex 會在壓縮後停止。

UserPromptSubmit

matcher 目前不用於此事件。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
turn_id string Codex 專用欄位。活躍的 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。

SubagentStop

此事件會將 matcher 應用於 agent_type。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
turn_id string Codex 專用欄位。當前 Codex 輪次 ID
agent_id string 子智能體的識別符
agent_type string 子智能體類型或設定檔
agent_transcript_path string | null 子智能體記錄檔案的路徑(如有)
stop_hook_active boolean 此子智能體是否已繼續執行
last_assistant_message string | null 最新的子智能體助手訊息(如有)

SubagentStop 退出 0 時,要求在 stdout 上輸出 JSON。對於此事件, 純文本輸出無效。

stdout 上的 JSON 支援通用輸出欄位。若要讓 Codex 繼續子智能體流程,請傳回:

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

你也可以使用結束代碼 2,並將繼續執行的原因寫入 stderr。

如果任一匹配的 SubagentStop 鉤子傳回 continue: false,其優先順序將 高於其他匹配的 SubagentStop 鉤子所作的繼續執行決定。

Stop

matcher 目前不用於此事件。

除通用輸入欄位外,還包含以下欄位:

欄位 類型 含義
turn_id string Codex 專用欄位。當前 Codex 輪次 ID
stop_hook_active boolean 此輪次是否已由 Stop 繼續執行
last_assistant_message string | null 最新的助手訊息文本(如有)

Stop 退出 0 時,要求在 stdout 上輸出 JSON。對於此事件,純文本輸出 無效。

stdout 上的 JSON 支援通用輸出欄位。若要讓 Codex 繼續執行,請傳回:

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

你也可以使用結束代碼 2,並將繼續執行的原因寫入 stderr。

對於此事件,decision: "block" 不會拒絕該輪次。相反,它會指示 Codex 繼續執行,並自動建立一個新的繼續提示詞;該提示詞將作為 新的使用者提示詞,並以你的 reason 作為提示詞文本。

如果任一匹配的 Stop 鉤子傳回 continue: false,其優先順序將高於 其他匹配的 Stop 鉤子所作的繼續執行決定。

Interrupt

當你中斷主聊天上正在進行的輪次時,Interrupt 會執行。可使用它 記錄中斷,或清理由鉤子啟動的工作。它不會針對空閒聊天或子智能體執行, 並且會忽略任何已設定的 matcher。

除通用輸入欄位外,該事件還包括 turn_id(被中斷輪次的 id)和 permission_mode。

命令鉤子的預設超時時間為一秒。設定的超時時間 僅限一至三秒。鉤子輸出無法阻止 中斷或重新啟動輪次。以 0 退出且不輸出任何內容,或者傳回包含 可選 systemMessage 的 JSON 以顯示警告。純文本輸出對此事件無效。

{ "systemMessage": "Saved the interrupted turn to the local audit log." }

資料結構

如果需要當前準確的傳輸格式,請參閱 Codex GitHub 儲存庫中生成的資料結構。

純文本別名

  • string | null