Tiếng Việt

Hook

Chạy các tập lệnh có tính xác định trong vòng đời Codex

Hook là một khung mở rộng dành cho Codex. Hook cho phép bạn chèn các tập lệnh của riêng mình vào vòng lặp tác nhân, qua đó hỗ trợ các tính năng như:

  • Gửi cuộc trò chuyện đến một công cụ ghi nhật ký/phân tích tùy chỉnh
  • Quét prompt của nhóm để ngăn việc vô tình dán API key
  • Tóm tắt các cuộc trò chuyện để tự động tạo bộ nhớ lâu dài
  • Chạy một bước kiểm tra xác thực tùy chỉnh khi một lượt trò chuyện dừng lại để bảo đảm tuân thủ các tiêu chuẩn
  • Tùy chỉnh prompt khi ở trong một thư mục nhất định

Các hành vi trong thời gian chạy cần lưu ý:

  • Tất cả hook khớp từ nhiều tệp đều sẽ chạy.
  • Nhiều hook lệnh cùng khớp với một sự kiện được khởi chạy đồng thời, vì vậy một hook không thể ngăn hook khớp khác bắt đầu.
  • Hook lệnh không được quản lý phải được xem xét và tin cậy trước khi chạy.

Hook chạy tại những thời điểm khác nhau trong cuộc trò chuyện:

Thời điểm Hook
Trong một lượt PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop
Khi phiên hoặc tác nhân phụ bắt đầu SessionStart, SubagentStart
Khi luồng chính kết thúc SessionEnd (không chạy cho tác nhân phụ)

Nơi Codex tìm hook

Codex phát hiện hook bên cạnh các lớp cấu hình đang hoạt động ở một trong hai dạng sau:

  • hooks.json
  • các bảng [hooks] nội tuyến bên trong config.toml

Plugin đã cài đặt cũng có thể đóng gói cấu hình vòng đời thông qua tệp kê khai plugin hoặc một tệp hooks/hooks.json mặc định. Xem Xây dựng plugin để biết các quy tắc đóng gói plugin.

Trong thực tế, bốn vị trí hữu ích nhất là:

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

Nếu có nhiều nguồn hook, Codex sẽ tải tất cả hook khớp. Các lớp cấu hình có độ ưu tiên cao hơn không thay thế hook ở lớp có độ ưu tiên thấp hơn. Nếu một lớp chứa cả hooks.json[hooks] nội tuyến, Codex sẽ hợp nhất chúng và cảnh báo khi khởi động. Nên dùng một cách biểu diễn cho mỗi lớp.

Codex cũng có thể phát hiện hook được đóng gói cùng các plugin đang bật. Hook đi kèm plugin được tải cùng các nguồn hook khác và sử dụng cùng quy trình xem xét độ tin cậy như các hook không được quản lý khác.

Hook cục bộ của dự án chỉ được tải khi lớp .codex/ của dự án được tin cậy. Trong các dự án không đáng tin cậy, Codex vẫn tải hook người dùng và hệ thống từ các lớp cấu hình đang hoạt động tương ứng.

Xem xét và tin cậy hook

Codex liệt kê các hook đã cấu hình trước khi quyết định hook nào có thể chạy. Trước khi một hook lệnh không được quản lý có thể chạy, Codex yêu cầu bạn xem xét và tin cậy đúng định nghĩa hook đó. Codex ghi nhận trạng thái tin cậy dựa trên hàm băm hiện tại của hook, vì vậy hook mới hoặc đã thay đổi sẽ được đánh dấu để xem xét và bị bỏ qua cho đến khi được tin cậy.

Dùng /hooks trong CLI để kiểm tra nguồn hook, xem xét hook mới hoặc đã thay đổi, tin cậy hook hoặc vô hiệu hóa từng hook không được quản lý. Nếu cần xem xét hook khi khởi động, Codex sẽ in cảnh báo yêu cầu bạn mở /hooks.

Hook được quản lý từ nguồn hệ thống, MDM, đám mây hoặc requirements.toml được đánh dấu là được quản lý, được chính sách tin cậy và không thể bị vô hiệu hóa từ trình duyệt hook của người dùng.

Đối với tác vụ tự động hóa dùng một lần đã kiểm định nguồn hook bên ngoài Codex, hãy truyền --dangerously-bypass-hook-trust để chạy các hook đang bật mà không yêu cầu trạng thái tin cậy hook được lưu cho lần gọi đó.

Cấu trúc cấu hình

Hook được tổ chức thành ba cấp:

  • Một sự kiện hook như PreToolUse, PostToolUse, PreCompact, SubagentStart hoặc Stop
  • Một nhóm đối sánh quyết định thời điểm sự kiện đó khớp
  • Một hoặc nhiều trình xử lý hook chạy khi nhóm đối sánh khớp
{
  "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
          }
        ]
      }
    ]
  }
}

Lưu ý:

  • description là siêu dữ liệu cấp cao nhất không bắt buộc dành cho tệp hooks.json. Nó không thay đổi hook nào sẽ chạy.
  • timeout được tính bằng giây.
  • Nếu bỏ qua timeout, Codex sử dụng 600 giây cho hầu hết hook.
    • SessionEnd mặc định dùng 1 giây và hỗ trợ tối đa 3 giây.
  • statusMessage là tùy chọn.
  • additionalContextLimit đặt lượng additionalContext mà một hook lệnh có thể gửi đến mô hình trước khi Codex lưu toàn bộ văn bản vào ổ đĩa và thay vào đó gửi một bản xem trước ngắn hơn. Xem Đầu ra hook lớn.
  • commandWindows là phần ghi đè lệnh chỉ dành cho Windows và không bắt buộc. Trong TOML, hãy dùng command_windows hoặc commandWindows.
  • Tùy chọn async được phân tích cú pháp, nhưng hook lệnh bất đồng bộ chưa được hỗ trợ.
  • Hiện chỉ các trình xử lý type: "command" chạy. Các trình xử lý promptagent được phân tích cú pháp nhưng bị bỏ qua.
  • Lệnh chạy với cwd của phiên làm thư mục làm việc.
  • Đối với hook cục bộ của kho lưu trữ, nên phân giải từ thư mục gốc git thay vì dùng một đường dẫn tương đối như .codex/hooks/.... Codex có thể được khởi động từ một thư mục con, còn đường dẫn dựa trên thư mục gốc git sẽ giữ vị trí hook ổn định.

TOML nội tuyến tương đương trong config.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"

Tắt hook

Hook được bật theo mặc định. Để tắt hook trong config.toml, hãy đặt:

[features]
hooks = false

Dùng hooks làm khóa tính năng chuẩn. codex_hooks vẫn hoạt động dưới dạng bí danh không còn được khuyến nghị. Quản trị viên có thể buộc tắt hook theo cùng cách trong requirements.toml bằng [features].hooks = false.

Hook được quản lý từ requirements.toml

Các yêu cầu do doanh nghiệp quản lý cũng có thể định nghĩa hook nội tuyến trong [hooks]. Điều này hữu ích khi quản trị viên muốn bắt buộc cấu hình hook trong khi phân phối các tập lệnh thực tế qua MDM hoặc một hệ thống quản lý thiết bị khác. Để bắt buộc hook được quản lý ngay cả với người dùng đã tắt hook cục bộ, hãy ghim [features].hooks = true trong requirements.toml cùng với [hooks]. Để bỏ qua hook của người dùng, dự án, phiên và plugin nhưng vẫn cho phép hook do quản trị viên quản lý, hãy đặt 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"

Lưu ý về hook được quản lý:

  • managed_dir được dùng trên macOS và Linux.
  • windows_managed_dir được dùng trên Windows.
  • Codex không phân phối các tập lệnh trong managed_dir; công cụ doanh nghiệp của bạn phải cài đặt và cập nhật chúng riêng.
  • Lệnh hook được quản lý nên dùng đường dẫn tập lệnh tuyệt đối trong thư mục được quản lý đã cấu hình.
  • allow_managed_hooks_only = true bỏ qua hook từ nguồn người dùng, dự án, phiên và plugin, nhưng vẫn tải hook được quản lý từ requirements.toml và các lớp cấu hình được quản lý khác.

Hook đi kèm plugin

Khi một plugin được bật, Codex có thể tải hook vòng đời từ plugin đó cùng với hook người dùng, dự án và được quản lý.

Theo mặc định, Codex tìm hooks/hooks.json bên trong thư mục gốc plugin. Tệp kê khai plugin có thể ghi đè giá trị mặc định đó bằng một mục hooks trong .codex-plugin/plugin.json. Mục trong tệp kê khai có thể là một đường dẫn có tiền tố ./, một mảng đường dẫn có tiền tố ./, một đối tượng hook nội tuyến hoặc một mảng đối tượng hook nội tuyến.

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

Đường dẫn hook trong tệp kê khai được phân giải tương đối với thư mục gốc plugin và phải nằm trong thư mục gốc đó. Nếu tệp kê khai định nghĩa hooks, Codex sẽ dùng các mục trong tệp kê khai đó thay cho hooks/hooks.json mặc định.

Lệnh hook plugin nhận các biến môi trường sau:

  • PLUGIN_ROOT là phần mở rộng riêng của Codex trỏ đến thư mục gốc của plugin đã cài đặt.
  • PLUGIN_DATA là phần mở rộng riêng của Codex trỏ đến thư mục dữ liệu có thể ghi của plugin.
  • Codex cũng đặt CLAUDE_PLUGIN_ROOTCLAUDE_PLUGIN_DATA để tương thích với các hook plugin hiện có.

Hook plugin sử dụng cùng lược đồ sự kiện như các hook khác. Việc cài đặt hoặc bật một plugin không tự động khiến hook của plugin được tin cậy; Codex bỏ qua hook đi kèm plugin cho đến khi bạn xem xét và tin cậy định nghĩa hook hiện tại.

Mẫu đối sánh

Trường matcher là một chuỗi biểu thức chính quy lọc thời điểm hook kích hoạt. Dùng "*", "" hoặc bỏ hoàn toàn matcher để khớp mọi lần xuất hiện của một sự kiện được hỗ trợ.

Chỉ một số sự kiện Codex hiện tại tuân theo matcher:

Sự kiện Nội dung được matcher lọc Lưu ý
PermissionRequest tên công cụ Phạm vi hỗ trợ gồm Bash, apply_patch* và tên công cụ MCP
PostToolUse tên công cụ Xem Phạm vi công cụ
PostCompact tác nhân kích hoạt nén Các giá trị là manual hoặc auto
PreCompact tác nhân kích hoạt nén Các giá trị là manual hoặc auto
PreToolUse tên công cụ Xem Phạm vi công cụ
SessionEnd lý do kết thúc Hiện chỉ có other
SessionStart nguồn khởi động Các giá trị là startup, resume, clearcompact
SubagentStart loại tác nhân phụ Giá trị phụ thuộc vào tác nhân phụ khởi động
SubagentStop loại tác nhân phụ Giá trị phụ thuộc vào tác nhân phụ dừng
UserPromptSubmit không được hỗ trợ Mọi matcher đã cấu hình đều bị bỏ qua cho sự kiện này
Stop không được hỗ trợ Mọi matcher đã cấu hình đều bị bỏ qua cho sự kiện này

*Đối với apply_patch, các giá trị matcher cũng có thể dùng Edit hoặc Write.

Ví dụ:

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

Phạm vi công cụ

PreToolUsePostToolUse có thể quan sát nhiều loại lệnh gọi hơn lệnh shell và MCP. Hầu hết công cụ hàm cục bộ sử dụng cùng đường dẫn hook, vì vậy bạn có thể đối sánh tên công cụ, kiểm tra đối số JSON và, với PreToolUse, chặn hoặc viết lại lệnh gọi.

Đường dẫn công cụ PreToolUse PostToolUse Lưu ý
Lệnh shell Đối sánh dưới dạng Bash.
Thực thi hợp nhất (exec_command) Đối sánh dưới dạng Bash. Một lần thăm dò write_stdin sau đó có thể chuyển PostToolUse của lệnh ban đầu khi lệnh hoàn tất.
apply_patch Đối sánh dưới dạng apply_patch, Edit hoặc Write.
Công cụ MCP Đối sánh tên công cụ MCP, chẳng hạn như mcp__filesystem__read_file.
Công cụ hàm cục bộ khác Đối sánh tên công cụ hàm, chẳng hạn như update_plan. spawn_agent cũng khớp với Agent.
Công cụ được lưu trữ, như WebSearch Không Không Các công cụ này không sử dụng đường dẫn hook công cụ hàm cục bộ.

write_stdin là lớp truyền tải cho một phiên thực thi hợp nhất hiện có. Nó không chạy lại PreToolUse khi gửi dữ liệu đầu vào hoặc thăm dò một lệnh đã vượt qua PreToolUse.

Một số đường dẫn công cụ chuyên biệt có thể không dùng đường dẫn hook mặc định. Hãy xem hook công cụ như một lớp bảo vệ hữu ích, không phải ranh giới thực thi hoàn chỉnh.

Các trường đầu vào chung

Mỗi hook lệnh nhận một đối tượng JSON trên stdin.

Đây là các trường dùng chung mà bạn thường sử dụng:

Trường Kiểu Ý nghĩa
session_id string ID phiên Codex hiện tại. Hook tác nhân phụ dùng ID phiên cha.
transcript_path string | null Đường dẫn đến tệp bản ghi phiên, nếu có
cwd string Thư mục làm việc của phiên
hook_event_name string Tên sự kiện hook hiện tại
model string Phần mở rộng riêng của Codex. Slug mô hình đang hoạt động

Hook theo phạm vi lượt liệt kê turn_id dưới dạng phần mở rộng riêng của Codex trong các bảng dành riêng cho sự kiện tương ứng.

SessionStart, PreToolUse, PermissionRequest, PostToolUse, UserPromptSubmit, SubagentStart, SubagentStopStop cũng bao gồm permission_mode, mô tả chế độ quyền hiện tại là default, acceptEdits, plan, dontAsk hoặc bypassPermissions.

transcript_path trỏ đến bản ghi cuộc trò chuyện để tiện sử dụng, nhưng định dạng bản ghi không phải là giao diện ổn định cho hook và có thể thay đổi theo thời gian.

Nếu cần toàn bộ định dạng truyền, hãy xem Lược đồ.

Các trường đầu ra chung

SessionStart, PreCompact, PostCompact, UserPromptSubmit, SubagentStopStop hỗ trợ các trường JSON dùng chung sau. SubagentStart chấp nhận cùng cấu trúc cho systemMessage và ngữ cảnh dành riêng cho hook, nhưng continue: false không dừng tác nhân phụ:

{
  "continue": true,
  "stopReason": "optional",
  "systemMessage": "optional",
  "suppressOutput": false
}
Trường Tác dụng
continue Nếu là false, đánh dấu lần chạy hook đó là đã dừng
stopReason Được ghi lại làm lý do dừng
systemMessage Hiển thị dưới dạng cảnh báo trong UI hoặc luồng sự kiện
suppressOutput Hiện được phân tích cú pháp nhưng chưa triển khai

Thoát với 0 mà không có đầu ra được coi là thành công và Codex tiếp tục.

PreToolUsePermissionRequest hỗ trợ systemMessage, nhưng continue, stopReasonsuppressOutput hiện chưa được hỗ trợ cho các sự kiện đó. Nếu một hook PreToolUse trả về một trong các trường không được hỗ trợ này, Codex sẽ đánh dấu lần chạy hook đó là thất bại, báo lỗi và tiếp tục lệnh gọi công cụ.

PostToolUse hỗ trợ systemMessage, continue: falsestopReason. suppressOutput được phân tích cú pháp nhưng hiện chưa được hỗ trợ cho sự kiện đó.

Đầu ra hook lớn

Theo mặc định, Codex giới hạn mỗi thông báo đầu ra hook mà mô hình có thể nhìn thấy ở khoảng 2.500 token. Nếu hook trả về nhiều hơn, Codex sẽ lưu toàn bộ văn bản trong <temp_dir>/hook_outputs/<session_id>/<uuid>.txt và cung cấp cho mô hình một bản xem trước gồm phần đầu và phần cuối cùng với đường dẫn tệp đã lưu. Hành vi này được gọi là tràn ra đĩa: Codex lưu đầu ra quá lớn trên ổ đĩa và thay thế bằng một bản xem trước ngắn hơn mà mô hình có thể nhìn thấy. Nếu không thể ghi tệp, mô hình vẫn nhận được bản xem trước đã cắt ngắn.

Đối với bất kỳ hook lệnh nào trả về additionalContext, hãy đặt additionalContextLimit trên trình xử lý để tùy chỉnh ngưỡng token xấp xỉ:

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

Bỏ qua additionalContextLimit để dùng ngưỡng 2500 token mặc định. Dùng một số nguyên dương để chọn ngưỡng khác hoặc 0 để truyền toàn bộ ngữ cảnh bổ sung của trình xử lý trực tiếp đến mô hình. Codex đánh giá độc lập từng trình xử lý khớp. Đối với các sự kiện không thể tạo ngữ cảnh bổ sung, Codex bỏ qua additionalContextLimit và báo cảnh báo cấu hình.

Cài đặt này chỉ áp dụng cho additionalContext. Phản hồi công cụ và prompt tiếp tục giữ nguyên giới hạn mặc định.

Vì đầu ra quá lớn có thể được ghi vào ổ đĩa, hãy tránh trả về thông tin bí mật hoặc dữ liệu nhạy cảm khác trong đầu ra hook.

Hook

SessionStart

matcher được áp dụng cho source đối với sự kiện này.

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
source string Cách phiên bắt đầu: startup, resume, clear hoặc compact

Văn bản thuần trên stdout được thêm làm ngữ cảnh bổ sung dành cho nhà phát triển.

JSON trên stdout hỗ trợ Các trường đầu ra chung và cấu trúc dành riêng cho hook sau:

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

Văn bản additionalContext đó được thêm làm ngữ cảnh bổ sung dành cho nhà phát triển.

Sau khi Codex nén một phiên gốc, các hook SessionStart khớp với source: "compact" sẽ chạy trước yêu cầu mô hình tiếp theo. Điều này cũng áp dụng khi quá trình nén tự động xảy ra giữa một lượt: Codex chuyển ngữ cảnh bổ sung của hook đến ngay lượt tiếp tục thay vì chờ một lượt người dùng sau đó. Nếu hook trả về continue: false, Codex kết thúc lượt mà không gửi thêm yêu cầu mô hình.

SessionEnd

SessionEnd cho phép bạn chạy lệnh khi một phiên kết thúc, chẳng hạn như lưu ghi chú cuối cùng hoặc dọn dẹp tệp. Hook chạy cho luồng chính khi bạn lưu trữ hoặc xóa một cuộc trò chuyện vẫn đang mở, khi Codex đóng bình thường hoặc sau khi một cuộc trò chuyện không hoạt động và không mở trong bất kỳ máy khách kết nối nào trong 30 phút. Hook này không chạy cho tác nhân phụ.

Việc chuyển khỏi một cuộc trò chuyện hoặc gọi thread/unsubscribe không kết thúc phiên ngay lập tức, vì vậy thao tác đó sẽ không chạy SessionEnd ngay. Hook của bạn vẫn có thể đọc bản ghi phiên trong khi chạy.

matcher lọc reason cho sự kiện này. Hiện tại, reason luôn là other. Bạn có thể bỏ qua matcher hoặc dùng other để chạy với mọi sự kiện SessionEnd.

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
reason string Lý do phiên kết thúc: other

Ví dụ, một lệnh SessionEnd nhận:

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

Hook SessionEnd mang tính tư vấn. Đầu ra của hook không điều hướng Codex hoặc giữ luồng tiếp tục mở. Nếu lệnh hết thời gian chờ hoặc thoát với lỗi, Codex sẽ báo đó là lỗi hook.

SubagentStart

matcher được áp dụng cho agent_type đối với sự kiện này.

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
turn_id string Phần mở rộng riêng của Codex. ID lượt Codex đang hoạt động
agent_id string Mã định danh của tác nhân phụ
agent_type string Loại hoặc hồ sơ tác nhân phụ
permission_mode string Chế độ quyền hiện tại

Văn bản thuần trên stdout được thêm làm ngữ cảnh bổ sung dành cho nhà phát triển cho tác nhân phụ.

JSON trên stdout hỗ trợ systemMessage và cấu trúc dành riêng cho hook sau:

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

Văn bản additionalContext đó được thêm làm ngữ cảnh bổ sung dành cho nhà phát triển cho tác nhân phụ. continue: false được phân tích cú pháp để tương thích, nhưng không ngăn tác nhân phụ khởi động.

PreToolUse

PreToolUse có thể chặn Bash, thao tác chỉnh sửa tệp được thực hiện qua apply_patch, lệnh gọi công cụ MCP và các công cụ hàm cục bộ khác. Xem Phạm vi công cụ để biết các đường dẫn được hỗ trợ và ngoại lệ.

matcher được áp dụng cho tool_name và các bí danh đối sánh. Đối với chỉnh sửa tệp qua apply_patch, các giá trị matcher có thể dùng apply_patch, Edit hoặc Write; đầu vào hook vẫn báo cáo tool_name: "apply_patch".

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
turn_id string Phần mở rộng riêng của Codex. ID lượt Codex đang hoạt động
tool_name string Tên công cụ hook chuẩn, chẳng hạn như Bash, apply_patch hoặc tên MCP như mcp__fs__read
tool_use_id string ID lệnh gọi công cụ cho lần gọi này
tool_input JSON value Đầu vào dành riêng cho công cụ. Bashapply_patch dùng tool_input.command. MCP và các công cụ hàm cục bộ khác gửi đối số của chúng.

Văn bản thuần trên stdout bị bỏ qua.

JSON trên stdout có thể dùng systemMessage. Để từ chối một lệnh gọi công cụ được hỗ trợ, hãy trả về cấu trúc dành riêng cho hook sau:

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

Codex cũng chấp nhận cấu trúc khối cũ hơn sau:

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

Bạn cũng có thể dùng mã thoát 2 và ghi lý do chặn vào stderr.

Để thêm ngữ cảnh mà mô hình có thể nhìn thấy mà không chặn, hãy trả về hookSpecificOutput.additionalContext:

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

Để viết lại một lệnh gọi công cụ được hỗ trợ mà không chặn, hãy trả về permissionDecision: "allow" cùng updatedInput:

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

Đối với lệnh Bash và apply_patch, updatedInput phải bao gồm trường chuỗi command. Đối với MCP và các công cụ hàm cục bộ khác, updatedInput là đối tượng đối số thay thế. Chỉ trả về updatedInput cùng với permissionDecision: "allow"; các cấu trúc updatedInput khác được báo là lỗi.

permissionDecision: "ask", decision: "approve" cũ, continue: false, stopReasonsuppressOutput được phân tích cú pháp nhưng chưa được hỗ trợ. Codex đánh dấu lần chạy hook là thất bại, báo lỗi và tiếp tục lệnh gọi công cụ.

PermissionRequest

PermissionRequest chạy khi Codex sắp yêu cầu phê duyệt, chẳng hạn như nâng quyền shell hoặc phê duyệt mạng được quản lý. Hook có thể cho phép yêu cầu, từ chối yêu cầu hoặc không đưa ra quyết định để tiếp tục hiển thị prompt phê duyệt thông thường. Hook không chạy cho các lệnh không cần phê duyệt.

matcher được áp dụng cho tool_name và các bí danh đối sánh. Các giá trị chuẩn hiện tại bao gồm Bash, apply_patch và tên công cụ MCP như mcp__server__tool; apply_patch cũng khớp với EditWrite.

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
turn_id string Phần mở rộng riêng của Codex. ID lượt Codex đang hoạt động
tool_name string Tên công cụ hook chuẩn, chẳng hạn như Bash, apply_patch hoặc tên MCP như mcp__fs__read
tool_input JSON value Đầu vào dành riêng cho công cụ. Bashapply_patch dùng tool_input.command, còn công cụ MCP gửi tất cả đối số.
tool_input.description string | null Lý do phê duyệt dễ đọc, khi Codex có lý do đó

Văn bản thuần trên stdout bị bỏ qua.

Một số đầu vào công cụ có thể bao gồm mô tả dễ đọc, nhưng đừng dựa vào trường tool_input.description cho mọi công cụ.

Để phê duyệt yêu cầu, hãy trả về:

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

Để từ chối yêu cầu, hãy trả về:

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

Nếu nhiều hook khớp trả về quyết định, bất kỳ deny nào cũng được ưu tiên. Nếu không, một allow sẽ cho phép yêu cầu tiếp tục mà không hiển thị prompt phê duyệt. Nếu không có hook khớp nào đưa ra quyết định, Codex sử dụng quy trình phê duyệt thông thường.

Không trả về updatedInput, updatedPermissions hoặc interrupt cho PermissionRequest; các trường đó được dành riêng cho hành vi trong tương lai và hiện sẽ từ chối theo mặc định.

PostToolUse

PostToolUse chạy sau khi các công cụ được hỗ trợ tạo đầu ra, bao gồm Bash, apply_patch, lệnh gọi công cụ MCP và các công cụ hàm cục bộ khác. Với Bash, hook cũng chạy sau các lệnh thoát với trạng thái khác 0. Hook không thể hoàn tác tác dụng phụ của một công cụ đã chạy. Xem Phạm vi công cụ để biết các đường dẫn được hỗ trợ và ngoại lệ.

matcher được áp dụng cho tool_name và các bí danh đối sánh. Đối với chỉnh sửa tệp qua apply_patch, các giá trị matcher có thể dùng apply_patch, Edit hoặc Write; đầu vào hook vẫn báo cáo tool_name: "apply_patch".

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
turn_id string Phần mở rộng riêng của Codex. ID lượt Codex đang hoạt động
tool_name string Tên công cụ hook chuẩn, chẳng hạn như Bash, apply_patch hoặc tên MCP như mcp__fs__read
tool_use_id string ID lệnh gọi công cụ cho lần gọi này
tool_input JSON value Đầu vào dành riêng cho công cụ. Bashapply_patch dùng tool_input.command. MCP và các công cụ hàm cục bộ khác gửi đối số của chúng.
tool_response JSON value Đầu ra dành riêng cho công cụ. Công cụ MCP gửi kết quả lệnh gọi MCP. Các công cụ hàm cục bộ khác thường gửi đầu ra dành cho mô hình.

Văn bản thuần trên stdout bị bỏ qua.

JSON trên stdout có thể dùng systemMessage và cấu trúc dành riêng cho hook sau:

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

Văn bản additionalContext đó được thêm làm ngữ cảnh bổ sung dành cho nhà phát triển.

Đối với sự kiện này, decision: "block" không hoàn tác lệnh Bash đã hoàn thành. Thay vào đó, Codex ghi lại phản hồi, thay thế kết quả công cụ bằng phản hồi đó và để mô hình tiếp tục từ thông báo do hook cung cấp.

Bạn cũng có thể dùng mã thoát 2 và ghi lý do phản hồi vào stderr.

Để dừng quá trình xử lý thông thường của kết quả công cụ ban đầu sau khi lệnh đã chạy, hãy trả về continue: false. Codex sẽ thay thế kết quả công cụ bằng phản hồi hoặc văn bản dừng của bạn và tiếp tục từ đó.

updatedMCPToolOutputsuppressOutput được phân tích cú pháp nhưng chưa được hỗ trợ. Codex đánh dấu lần chạy hook là thất bại, báo lỗi và tiếp tục xử lý kết quả công cụ theo cách thông thường.

Lệnh gọi công cụ từ chế độ mã

Khi mô hình dùng chế độ mã để gọi công cụ từ JavaScript, quyết định của hook áp dụng cho lệnh gọi lồng nhau đó. PreToolUse có thể dừng công cụ trước khi chạy hoặc viết lại đầu vào của công cụ. PostToolUse chặn không thể hoàn tác tác dụng phụ của công cụ, nhưng có thể ngăn kết quả ban đầu đến được tập lệnh đang chạy.

Kết quả hook Nội dung chế độ mã nhận được
PreToolUse chặn Promise của công cụ bị từ chối trước khi công cụ chạy.
PreToolUse trả về updatedInput Công cụ chạy với đầu vào đã viết lại và promise được hoàn thành với kết quả đó.
PostToolUse trả về decision: "block" hoặc thoát với mã 2 Công cụ chạy, sau đó promise bị từ chối với lý do của hook.
PostToolUse trả về continue: false Codex dùng phản hồi hook cho kết quả mà mô hình nhìn thấy, nhưng không từ chối promise công cụ lồng nhau.

PreCompact

PreCompact chạy trước khi Codex nén cuộc trò chuyện. matcher được áp dụng cho trigger, có các giá trị là manualauto.

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
turn_id string Phần mở rộng riêng của Codex. ID lượt Codex đang hoạt động
trigger string Yếu tố kích hoạt quá trình nén: manual hoặc auto

Văn bản thuần trên stdout bị bỏ qua.

JSON trên stdout hỗ trợ Các trường đầu ra chung. Nếu một hook PreCompact khớp trả về continue: false, Codex sẽ dừng trước khi nén.

PostCompact

PostCompact chạy sau khi Codex nén cuộc trò chuyện. matcher được áp dụng cho trigger, có các giá trị là manualauto.

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
turn_id string Phần mở rộng riêng của Codex. ID lượt Codex đang hoạt động
trigger string Yếu tố kích hoạt quá trình nén: manual hoặc auto

Văn bản thuần trên stdout bị bỏ qua.

JSON trên stdout hỗ trợ Các trường đầu ra chung. Nếu một hook PostCompact khớp trả về continue: false, Codex sẽ dừng sau khi nén.

UserPromptSubmit

matcher hiện không được dùng cho sự kiện này.

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
turn_id string Phần mở rộng riêng của Codex. ID lượt Codex đang hoạt động
prompt string Prompt người dùng sắp được gửi

Văn bản thuần trên stdout được thêm làm ngữ cảnh bổ sung dành cho nhà phát triển.

JSON trên stdout hỗ trợ Các trường đầu ra chung và cấu trúc dành riêng cho hook sau:

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

Văn bản additionalContext đó được thêm làm ngữ cảnh bổ sung dành cho nhà phát triển.

Để chặn prompt, hãy trả về:

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

Bạn cũng có thể dùng mã thoát 2 và ghi lý do chặn vào stderr.

SubagentStop

matcher được áp dụng cho agent_type đối với sự kiện này.

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
turn_id string Phần mở rộng riêng của Codex. ID lượt Codex đang hoạt động
agent_id string Mã định danh của tác nhân phụ
agent_type string Loại hoặc hồ sơ tác nhân phụ
agent_transcript_path string | null Đường dẫn đến tệp bản ghi tác nhân phụ, nếu có
stop_hook_active boolean Tác nhân phụ này đã được tiếp tục hay chưa
last_assistant_message string | null Thông báo mới nhất của trợ lý tác nhân phụ, nếu có

SubagentStop yêu cầu JSON trên stdout khi thoát với 0. Đầu ra văn bản thuần không hợp lệ cho sự kiện này.

JSON trên stdout hỗ trợ Các trường đầu ra chung. Để yêu cầu Codex tiếp tục luồng tác nhân phụ, hãy trả về:

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

Bạn cũng có thể dùng mã thoát 2 và ghi lý do tiếp tục vào stderr.

Nếu bất kỳ hook SubagentStop khớp nào trả về continue: false, kết quả đó sẽ được ưu tiên hơn quyết định tiếp tục từ các hook SubagentStop khớp khác.

Stop

matcher hiện không được dùng cho sự kiện này.

Các trường ngoài Các trường đầu vào chung:

Trường Kiểu Ý nghĩa
turn_id string Phần mở rộng riêng của Codex. ID lượt Codex đang hoạt động
stop_hook_active boolean Lượt này đã được Stop tiếp tục hay chưa
last_assistant_message string | null Văn bản thông báo mới nhất của trợ lý, nếu có

Stop yêu cầu JSON trên stdout khi thoát với 0. Đầu ra văn bản thuần không hợp lệ cho sự kiện này.

JSON trên stdout hỗ trợ Các trường đầu ra chung. Để giữ Codex tiếp tục chạy, hãy trả về:

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

Bạn cũng có thể dùng mã thoát 2 và ghi lý do tiếp tục vào stderr.

Đối với sự kiện này, decision: "block" không từ chối lượt. Thay vào đó, nó yêu cầu Codex tiếp tục và tự động tạo một prompt tiếp tục mới hoạt động như prompt người dùng mới, sử dụng reason của bạn làm văn bản prompt đó.

Nếu bất kỳ hook Stop khớp nào trả về continue: false, kết quả đó được ưu tiên hơn quyết định tiếp tục từ các hook Stop khớp khác.

Lược đồ

Nếu cần định dạng truyền chính xác hiện tại, hãy xem các lược đồ được tạo trong kho lưu trữ Codex trên GitHub.

Bí danh văn bản thuần

  • string | null