Хуки
Запускайте детерминированные скрипты в течение жизненного цикла Codex
Хуки — это механизм расширения Codex. Они позволяют встраивать собственные скрипты в агентный цикл и реализовывать такие возможности, как:
- Отправка чата в собственную систему журналирования или аналитики
- Проверка промптов вашей команды, чтобы предотвратить случайную вставку API keys
- Автоматическое создание постоянной памяти на основе кратких сводок чатов
- Запуск собственной проверки при завершении хода чата для обеспечения соблюдения стандартов
- Настройка промптов при работе в определённом каталоге
Особенности поведения во время выполнения:
- Запускаются все соответствующие хуки из нескольких файлов.
- Несколько соответствующих командных хуков для одного события запускаются параллельно, поэтому один хук не может помешать запуску другого соответствующего хука.
- Перед запуском неуправляемые командные хуки необходимо проверить и признать доверенными.
Хуки запускаются на разных этапах диалога:
| Когда | Хуки |
|---|---|
| Во время хода | PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop |
| При запуске сеанса или субагента | SessionStart, SubagentStart |
| При завершении основной ветки | SessionEnd (не запускается для субагентов) |
Где Codex ищет хуки
Codex обнаруживает хуки рядом с активными слоями конфигурации в одной из следующих форм:
hooks.json- встроенные таблицы
[hooks]внутриconfig.toml
Установленные плагины также могут включать конфигурацию жизненного цикла через свой
манифест или файл 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 связывает доверие с текущим хешем хука, поэтому новые или изменённые хуки помечаются как требующие проверки и пропускаются до предоставления доверия.
Используйте /hooks в CLI, чтобы просматривать источники хуков, проверять новые или изменённые хуки,
предоставлять хукам доверие либо отключать отдельные неуправляемые хуки. Если при
запуске хуки требуют проверки, 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по умолчанию используется1секунда; поддерживается значение до3секунд.
- Для
statusMessageуказывать необязательно.additionalContextLimitопределяет объёмadditionalContext, который командный хук может отправить модели, прежде чем Codex сохранит полный текст на диск и вместо него отправит сокращённый предварительный просмотр. См. раздел Большой объём вывода хука.commandWindows— необязательное переопределение команды только для Windows. В TOML используйтеcommand_windowsилиcommandWindows.- Параметр
asyncразбирается, но асинхронные командные хуки пока не поддерживаются. - В настоящее время запускаются только обработчики
type: "command". Обработчикиpromptиagentразбираются, но пропускаются. - Команды запускаются с каталогом сеанса
cwdв качестве рабочего каталога. - Для хуков внутри репозитория предпочтительно определять путь от корня git, а не использовать
относительный путь, например
.codex/hooks/.... Codex может быть запущен из подкаталога, а путь от корня git обеспечивает постоянное расположение хука.
Эквивалентная встроенная конфигурация TOML в 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"Отключение хуков
Хуки включены по умолчанию. Чтобы отключить их в config.toml, задайте:
[features]
hooks = falseИспользуйте hooks как канонический ключ функции. codex_hooks по-прежнему работает как
устаревший псевдоним. Администраторы могут аналогичным образом принудительно отключить хуки в
requirements.toml с помощью [features].hooks = false.
Управляемые хуки из requirements.toml
Управляемые корпоративные требования также могут определять хуки непосредственно в [hooks].
Это удобно, когда администраторам необходимо обеспечить применение конфигурации хуков, а
сами скрипты распространяются через MDM или другую систему управления устройствами.
Чтобы принудительно применять управляемые хуки даже для пользователей, отключивших хуки локально, закрепите
[features].hooks = true в requirements.toml вместе с [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пропускает хуки из пользовательских, проектных, сеансовых и плагинных источников, но продолжает загружать управляемые хуки изrequirements.tomlи других управляемых слоёв конфигурации.
Хуки, входящие в плагины
Когда плагин включён, Codex может загружать из него хуки жизненного цикла вместе с пользовательскими, проектными и управляемыми хуками.
По умолчанию Codex ищет hooks/hooks.json в корне плагина. Манифест
плагина может переопределить это значение по умолчанию с помощью записи hooks в
.codex-plugin/plugin.json. Запись манифеста может быть путём с префиксом ./,
массивом путей с префиксом ./, встроенным объектом хуков или массивом встроенных
объектов хуков.
{
"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 |
SubagentStart |
тип субагента | Значения зависят от запускаемого субагента |
SubagentStop |
тип субагента | Значения зависят от останавливаемого субагента |
UserPromptSubmit |
не поддерживается | Любой настроенный matcher игнорируется для этого события |
Stop |
не поддерживается | Любой настроенный matcher игнорируется для этого события |
*Для apply_patch в значениях matcher также можно использовать Edit или Write.
Примеры:
Bash^apply_patch$Edit|Writemcp__filesystem__read_filemcp__filesystem__.*startup|resume|clear|compactmanual|auto
Охват инструментов
PreToolUse и PostToolUse могут отслеживать не только вызовы оболочки и MCP. Большинство
локальных функциональных инструментов используют тот же путь хуков, поэтому вы можете сопоставить имя инструмента,
проверить его аргументы JSON, а для PreToolUse — заблокировать или изменить вызов.
| Путь инструмента | PreToolUse |
PostToolUse |
Примечания |
|---|---|---|---|
| Команды оболочки | Да | Да | Сопоставляются как 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.
Некоторые специализированные пути инструментов могут не использовать стандартный путь хуков. Считайте хуки инструментов полезным защитным механизмом, а не всеобъемлющей границей контроля.
Общие входные поля
Каждый хук команды получает один объект JSON через stdin.
Ниже перечислены общие поля, которые обычно используются:
| Поле | Тип | Значение |
|---|---|---|
session_id |
string |
Идентификатор текущего сеанса Codex. Хуки субагентов используют идентификатор родительского сеанса. |
transcript_path |
string | null |
Путь к файлу расшифровки сеанса, если он существует |
cwd |
string |
Рабочий каталог сеанса |
hook_event_name |
string |
Имя текущего события хука |
model |
string |
Расширение Codex. Слаг активной модели |
В таблицах полей для событий хуков с областью действия в пределах хода turn_id указан как расширение Codex.
SessionStart, PreToolUse, PermissionRequest, PostToolUse,
UserPromptSubmit, SubagentStart, SubagentStop и Stop также включают
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 |
Отображается как предупреждение в интерфейсе или потоке событий |
suppressOutput |
В настоящее время разбирается, но ещё не реализовано |
Выход с кодом 0 без вывода считается успешным, и Codex продолжает работу.
PreToolUse и PermissionRequest поддерживают systemMessage, но continue,
stopReason и suppressOutput сейчас не поддерживаются для этих событий.
Если хук PreToolUse возвращает одно из этих неподдерживаемых полей, Codex помечает
выполнение хука как неудачное, сообщает об ошибке и продолжает вызов инструмента.
PostToolUse поддерживает systemMessage, continue: false и stopReason.
suppressOutput разбирается, но сейчас не поддерживается для этого события.
Большой объём вывода хука
По умолчанию Codex ограничивает каждое видимое модели сообщение с выводом хука примерно
2 500 токенами. Если хук возвращает больше, Codex сохраняет полный текст в
<temp_dir>/hook_outputs/<session_id>/<uuid>.txt и предоставляет модели предварительный просмотр начала и конца
с путём к сохранённому файлу. Это поведение называется
выгрузкой: Codex сохраняет слишком большой вывод на диске и заменяет его
более коротким предварительным просмотром, видимым модели. Если записать файл не удаётся, модель всё равно
получает усечённый предварительный просмотр.
Для любого хука команды, возвращающего additionalContext, задайте
additionalContextLimit в обработчике, чтобы настроить приблизительный порог
числа токенов:
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_start.py",
"additionalContextLimit": 5000
}Не указывайте additionalContextLimit, чтобы использовать стандартный порог в 2500 токенов. Укажите
положительное целое число, чтобы выбрать другой порог, или 0, чтобы передать полный
дополнительный контекст обработчика непосредственно модели. Codex оценивает каждый
подходящий обработчик независимо. Для событий, которые не могут создавать дополнительный
контекст, Codex игнорирует additionalContextLimit и сообщает предупреждение
о конфигурации.
Эта настройка применяется только к additionalContext. Отзывы инструментов и запросы
на продолжение используют стандартный предел.
Поскольку слишком большой вывод может записываться на диск, не возвращайте в выводе хука секреты или другие конфиденциальные данные.
Хуки
SessionStart
Для этого события matcher применяется к source.
Поля в дополнение к общим входным полям:
| Поле | Тип | Значение |
|---|---|---|
source |
string |
Способ запуска сеанса: startup, resume, clear или compact |
Обычный текст в stdout добавляется как дополнительный контекст разработчика.
JSON в stdout поддерживает общие выходные поля и следующую
структуру, специфичную для хука:
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "Load the workspace conventions before editing."
}
}Этот текст additionalContext добавляется как дополнительный контекст разработчика.
После сжатия корневого сеанса Codex хуки SessionStart, соответствующие
source: "compact", выполняются перед следующим запросом к модели. Это также применимо, когда
автоматическое сжатие происходит в середине хода: 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 носят рекомендательный характер. Их вывод не будет направлять работу Codex или оставлять
поток открытым. Если время выполнения команды истекает или она завершается с ошибкой, Codex сообщает об этом как
о сбое хука.
SubagentStart
Для этого события matcher применяется к agent_type.
Поля в дополнение к общим входным полям:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Расширение Codex. Идентификатор активного хода Codex |
agent_id |
string |
Идентификатор субагента |
agent_type |
string |
Тип или профиль субагента |
permission_mode |
string |
Текущий режим разрешений |
Обычный текст в stdout добавляется как дополнительный контекст разработчика для субагента.
JSON в stdout поддерживает 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 |
tool_name |
string |
Каноническое имя инструмента хука, например Bash, apply_patch или имя MCP, такое как mcp__fs__read |
tool_use_id |
string |
Идентификатор вызова инструмента для этого обращения |
tool_input |
JSON value |
Входные данные конкретного инструмента. Bash и apply_patch используют tool_input.command. MCP и другие локальные функциональные инструменты передают свои аргументы. |
Обычный текст в stdout игнорируется.
JSON в stdout может использовать 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."
}
}Чтобы перезаписать поддерживаемый вызов инструмента без блокировки, верните
permissionDecision: "allow" с updatedInput:
{
"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
PermissionRequest запускается, когда Codex собирается запросить одобрение, например для
повышения привилегий оболочки или доступа к управляемой сети. Он может разрешить запрос, отклонить
его либо отказаться принимать решение и продолжить обычный запрос одобрения.
Он не запускается для команд, которым одобрение не требуется.
matcher применяется к tool_name и псевдонимам сопоставления. Текущие канонические
значения включают Bash, apply_patch и имена инструментов MCP, такие как
mcp__server__tool; apply_patch также соответствует Edit и Write.
Поля в дополнение к общим входным полям:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Расширение, специфичное для Codex. Идентификатор активного хода Codex |
tool_name |
string |
Каноническое имя инструмента хука, например Bash, apply_patch или имя MCP, такое как mcp__fs__read |
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 использует обычный процесс одобрения.
Не возвращайте updatedInput, updatedPermissions или interrupt для
PermissionRequest; эти поля зарезервированы для будущего поведения и в настоящее время
приводят к отклонению запроса.
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 |
tool_name |
string |
Каноническое имя инструмента хука, например Bash, apply_patch или имя MCP, такое как mcp__fs__read |
tool_use_id |
string |
Идентификатор вызова инструмента для этого обращения |
tool_input |
JSON value |
Входные данные конкретного инструмента. Bash и apply_patch используют tool_input.command. MCP и другие локальные функциональные инструменты передают свои аргументы. |
tool_response |
JSON value |
Результат конкретного инструмента. Инструменты MCP передают результат вызова MCP. Другие локальные функциональные инструменты обычно передают результат, предназначенный для модели. |
Обычный текст в stdout игнорируется.
JSON в stdout может использовать 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 блокирует |
Промис инструмента отклоняется до запуска инструмента. |
PreToolUse возвращает updatedInput |
Инструмент запускается с перезаписанными входными данными, а промис разрешается с полученным результатом. |
PostToolUse возвращает decision: "block" или завершается с кодом 2 |
Инструмент запускается, после чего промис отклоняется с причиной, указанной хуком. |
PostToolUse возвращает continue: false |
Codex использует обратную связь хука как видимый модели результат, но не отклоняет промис вложенного инструмента. |
PreCompact
PreCompact запускается перед сжатием чата в Codex. matcher применяется
к trigger, значениями которого являются manual и auto.
Поля в дополнение к общим входным полям:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Расширение, специфичное для Codex. Идентификатор активного хода Codex |
trigger |
string |
Что вызвало сжатие: manual или auto |
Обычный текст в stdout игнорируется.
JSON в stdout поддерживает общие выходные поля. Если
соответствующий хук PreCompact возвращает continue: false, Codex останавливается до
сжатия.
PostCompact
PostCompact запускается после сжатия чата в Codex. matcher применяется
к trigger, значениями которого являются manual и auto.
Поля в дополнение к общим входным полям:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Расширение, специфичное для Codex. Идентификатор активного хода Codex |
trigger |
string |
Что вызвало сжатие: manual или auto |
Обычный текст в stdout игнорируется.
JSON в stdout поддерживает общие выходные поля. Если
соответствующий хук PostCompact возвращает continue: false, Codex останавливается после
сжатия.
UserPromptSubmit
matcher в настоящее время не используется для этого события.
Поля в дополнение к общим входным полям:
| Поле | Тип | Значение |
|---|---|---|
turn_id |
string |
Расширение, специфичное для Codex. Идентификатор активного хода Codex |
prompt |
string |
Пользовательский запрос, который будет отправлен |
Обычный текст в stdout добавляется как дополнительный контекст разработчика.
JSON в stdout поддерживает общие поля вывода и
следующую структуру, специфичную для этого хука:
{
"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 |
agent_id |
string |
Идентификатор субагента |
agent_type |
string |
Тип или профиль субагента |
agent_transcript_path |
string | null |
Путь к файлу расшифровки субагента, если он существует |
stop_hook_active |
boolean |
Было ли выполнение этого субагента уже продолжено |
last_assistant_message |
string | null |
Последнее сообщение ассистента-субагента, если оно доступно |
SubagentStop ожидает JSON в stdout при завершении с кодом 0. Вывод в виде обычного текста
недопустим для этого события.
JSON в stdout поддерживает общие поля вывода. Чтобы попросить
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 |
stop_hook_active |
boolean |
Было ли выполнение этого хода уже продолжено с помощью Stop |
last_assistant_message |
string | null |
Текст последнего сообщения ассистента, если он доступен |
Stop ожидает JSON в stdout при завершении с кодом 0. Вывод в виде обычного текста недопустим
для этого события.
JSON в stdout поддерживает общие поля вывода. Чтобы
Codex продолжил работу, верните:
{
"decision": "block",
"reason": "Run one more pass over the failing tests."
}Также можно использовать код завершения 2 и записать причину продолжения в stderr.
Для этого события decision: "block" не отклоняет ход. Вместо этого он указывает
Codex продолжить работу и автоматически создаёт новый запрос на продолжение, который действует
как новый пользовательский запрос и использует значение reason в качестве его текста.
Если какой-либо соответствующий хук Stop возвращает continue: false, это решение имеет приоритет
над решениями о продолжении от других соответствующих хуков Stop.
Схемы
Если вам нужен точный текущий формат передачи данных, ознакомьтесь со сгенерированными схемами в репозитории Codex на GitHub.
Псевдонимы обычного текста
- string | null