Hooks
Ejecuta scripts deterministas durante el ciclo de vida de Codex
Los hooks son un marco de extensibilidad para Codex. Permiten inyectar tus propios scripts en el bucle de agentes, lo que habilita funciones como:
- Enviar el chat a un motor personalizado de registro o análisis
- Analizar los prompts de tu equipo para impedir que se peguen accidentalmente API keys
- Resumir chats para crear memorias persistentes automáticamente
- Ejecutar una comprobación de validación personalizada cuando se detiene un turno del chat, para hacer cumplir los estándares
- Personalizar los prompts cuando se trabaja en un directorio determinado
Comportamiento en tiempo de ejecución que debes tener en cuenta:
- Se ejecutan todos los hooks coincidentes de varios archivos.
- Varios hooks de comando coincidentes para el mismo evento se inician simultáneamente, por lo que un hook no puede impedir que se inicie otro hook coincidente.
- Los hooks de comando no administrados deben revisarse y considerarse de confianza antes de ejecutarse.
Los hooks se ejecutan en distintos momentos de una conversación:
| Cuándo | Hooks |
|---|---|
| Durante un turno | PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop |
| Cuando se inicia una sesión o un subagente | SessionStart, SubagentStart |
| Cuando termina el hilo principal | SessionEnd (no se ejecuta para subagentes) |
Dónde busca Codex los hooks
Codex detecta hooks junto a las capas de configuración activas en cualquiera de estas formas:
hooks.json- tablas
[hooks]en línea dentro deconfig.toml
Los plugins instalados también pueden incluir la configuración del ciclo de vida mediante su
manifiesto de plugin o un archivo hooks/hooks.json predeterminado. Consulta Crear
plugins para conocer las
reglas de empaquetado de plugins.
En la práctica, las cuatro ubicaciones más útiles son:
~/.codex/hooks.json~/.codex/config.toml<repo>/.codex/hooks.json<repo>/.codex/config.toml
Si existe más de un origen de hooks, Codex carga todos los hooks coincidentes.
Las capas de configuración con mayor precedencia no reemplazan los hooks de menor precedencia.
Si una sola capa contiene tanto hooks.json como [hooks] en línea, Codex
los combina y muestra una advertencia al iniciarse. Usa preferentemente una sola representación por capa.
Codex también puede detectar hooks incluidos en plugins habilitados. Los hooks incluidos en plugins se cargan junto con otros orígenes de hooks y utilizan el mismo flujo de revisión de confianza que los demás hooks no administrados.
Los hooks locales del proyecto solo se cargan cuando la capa .codex/ del proyecto es de confianza. En
proyectos que no son de confianza, Codex sigue cargando los hooks de usuario y del sistema desde sus propias
capas de configuración activas.
Revisar los hooks y confiar en ellos
Codex enumera los hooks configurados antes de decidir cuáles pueden ejecutarse. Antes de que pueda ejecutarse un hook de comando no administrado, Codex exige que revises y marques como de confianza la definición exacta del hook. Codex registra la confianza en función del hash actual del hook, por lo que los hooks nuevos o modificados se marcan para su revisión y se omiten hasta que se consideren de confianza.
Usa /hooks en la CLI para inspeccionar los orígenes de los hooks, revisar hooks nuevos o modificados,
marcarlos como de confianza o deshabilitar hooks no administrados individuales. Si hay hooks que requieren revisión al
iniciarse, Codex muestra una advertencia que te indica que abras /hooks.
Los hooks administrados procedentes de orígenes del sistema, MDM, la nube o requirements.toml se marcan
como administrados, se consideran de confianza por política y no pueden deshabilitarse desde el explorador de hooks del usuario.
Para una automatización puntual que ya comprueba los orígenes de los hooks fuera de Codex, pasa
--dangerously-bypass-hook-trust para ejecutar los hooks habilitados sin requerir
que la confianza en los hooks se conserve para esa invocación.
Estructura de configuración
Los hooks se organizan en tres niveles:
- Un evento de hook como
PreToolUse,PostToolUse,PreCompact,SubagentStartoStop - Un grupo de coincidencia que determina cuándo coincide ese evento
- Uno o más controladores de hooks que se ejecutan cuando coincide el grupo de coincidencia
{
"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
}
]
}
]
}
}Notas:
descriptionson metadatos opcionales de nivel superior para un archivohooks.json. No cambian qué hooks se ejecutan.timeoutse expresa en segundos.- Si se omite
timeout, Codex usa600segundos para la mayoría de los hooks.SessionEndusa1segundo de forma predeterminada y admite hasta3segundos.
statusMessagees opcional.additionalContextLimitestablece cuántoadditionalContextpuede enviar un hook de comando al modelo antes de que Codex guarde el texto completo en el disco y envíe en su lugar una vista previa más corta. Consulta Salida extensa de hooks.commandWindowses una sustitución opcional del comando exclusiva de Windows. En TOML, usacommand_windowsocommandWindows.- La opción
asyncse analiza, pero los hooks de comando asíncronos todavía no son compatibles. - Actualmente, solo se ejecutan los controladores
type: "command". Los controladorespromptyagentse analizan, pero se omiten. - Los comandos se ejecutan con el
cwdde la sesión como directorio de trabajo. - Para los hooks locales del repositorio, es preferible resolver la ruta desde la raíz de git en lugar de usar una
ruta relativa como
.codex/hooks/.... Codex puede iniciarse desde un subdirectorio, y una ruta basada en la raíz de git mantiene estable la ubicación del hook.
TOML en línea equivalente en 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"Desactivar los hooks
Los hooks están habilitados de forma predeterminada. Para desactivarlos en config.toml, configura:
[features]
hooks = falseUsa hooks como clave de función canónica. codex_hooks sigue funcionando como
alias obsoleto. Los administradores pueden forzar la desactivación de los hooks de la misma forma en
requirements.toml con [features].hooks = false.
Hooks administrados desde requirements.toml
Los requisitos administrados por la empresa también pueden definir hooks en línea bajo [hooks].
Esto resulta útil cuando los administradores quieren imponer la configuración de hooks mientras
distribuyen los scripts reales mediante MDM u otro sistema de administración de dispositivos.
Para imponer hooks administrados incluso a los usuarios que hayan deshabilitado los hooks localmente, fija
[features].hooks = true en requirements.toml junto con [hooks]. Para ignorar
los hooks de usuario, proyecto, sesión y plugin sin dejar de permitir los hooks administrados por el
administrador, establece 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"Notas sobre los hooks administrados:
managed_dirse usa en macOS y Linux.windows_managed_dirse usa en Windows.- Codex no distribuye los scripts de
managed_dir; las herramientas de tu empresa deben instalarlos y actualizarlos por separado. - Los comandos de hooks administrados deben usar rutas absolutas de scripts dentro del directorio administrado configurado.
allow_managed_hooks_only = trueomite los hooks de orígenes de usuario, proyecto, sesión y plugin, pero sigue cargando los hooks administrados derequirements.tomly otras capas de configuración administradas.
Hooks incluidos en plugins
Cuando se habilita un plugin, Codex puede cargar hooks del ciclo de vida desde ese plugin junto con los hooks de usuario, proyecto y administrados.
De forma predeterminada, Codex busca hooks/hooks.json dentro de la raíz del plugin. Un
manifiesto de plugin puede sustituir ese valor predeterminado mediante una entrada hooks en
.codex-plugin/plugin.json. La entrada del manifiesto puede ser una ruta con el prefijo ./, un
array de rutas con el prefijo ./, un objeto de hooks en línea o un array de objetos de
hooks en línea.
{
"name": "repo-policy",
"hooks": "./hooks/hooks.json"
}Las rutas de hooks del manifiesto se resuelven con respecto a la raíz del plugin y deben permanecer
dentro de ella. Si un manifiesto define hooks, Codex usa esas entradas del manifiesto
en lugar del hooks/hooks.json predeterminado.
Los comandos de hooks de plugins reciben estas variables de entorno:
PLUGIN_ROOTes una extensión específica de Codex que apunta a la raíz del plugin instalado.PLUGIN_DATAes una extensión específica de Codex que apunta al directorio de datos del plugin con permisos de escritura.- Codex también establece
CLAUDE_PLUGIN_ROOTyCLAUDE_PLUGIN_DATApara mantener la compatibilidad con los hooks de plugins existentes.
Los hooks de plugins usan el mismo esquema de eventos que los demás hooks. Instalar o habilitar un plugin no hace que sus hooks se consideren de confianza automáticamente; Codex omite los hooks incluidos en plugins hasta que revises y marques como de confianza la definición actual del hook.
Patrones de coincidencia
El campo matcher es una cadena de expresión regular que filtra cuándo se activan los hooks. Usa "*",
"" u omite por completo matcher para hacer coincidir cada aparición de un evento
compatible.
Solo algunos eventos actuales de Codex respetan matcher:
| Evento | Qué filtra matcher |
Notas |
|---|---|---|
PermissionRequest |
nombre de la herramienta | La compatibilidad incluye Bash, apply_patch* y nombres de herramientas MCP |
PostToolUse |
nombre de la herramienta | Consulte Cobertura de herramientas |
PostCompact |
desencadenador de compactación | Los valores son manual o auto |
PreCompact |
desencadenador de compactación | Los valores son manual o auto |
PreToolUse |
nombre de la herramienta | Consulte Cobertura de herramientas |
SessionEnd |
motivo de finalización | Actualmente, solo other |
SessionStart |
origen de inicio | Los valores son startup, resume, clear y compact |
SubagentStart |
tipo de subagente | Los valores dependen del subagente que se inicia |
SubagentStop |
tipo de subagente | Los valores dependen del subagente que se detiene |
UserPromptSubmit |
no compatible | Cualquier matcher configurado se ignora para este evento |
Stop |
no compatible | Cualquier matcher configurado se ignora para este evento |
*Para apply_patch, los valores de matcher también pueden usar Edit o Write.
Ejemplos:
Bash^apply_patch$Edit|Writemcp__filesystem__read_filemcp__filesystem__.*startup|resume|clear|compactmanual|auto
Cobertura de herramientas
PreToolUse y PostToolUse pueden observar más que llamadas de shell y MCP. La mayoría de las
herramientas de funciones locales usan la misma ruta de hooks, por lo que puede buscar coincidencias con el nombre de la herramienta,
inspeccionar sus argumentos JSON y, para PreToolUse, bloquear o reescribir la llamada.
| Ruta de la herramienta | PreToolUse |
PostToolUse |
Notas |
|---|---|---|---|
| Comandos de shell | Sí | Sí | Busque coincidencias como Bash. |
Ejecución unificada (exec_command) |
Sí | Sí | Busque coincidencias como Bash. Una consulta posterior de write_stdin puede entregar el PostToolUse del comando original cuando este finalice. |
apply_patch |
Sí | Sí | Busque coincidencias como apply_patch, Edit o Write. |
| Herramientas MCP | Sí | Sí | Busque coincidencias con el nombre de la herramienta MCP, como mcp__filesystem__read_file. |
| Otras herramientas de funciones locales | Sí | Sí | Busque coincidencias con el nombre de la herramienta de función, como update_plan. spawn_agent también coincide con Agent. |
Herramientas alojadas, como WebSearch |
No | No | Estas no usan la ruta de hooks de herramientas de funciones locales. |
write_stdin es el transporte de una sesión de ejecución unificada existente. No ejecuta
PreToolUse de nuevo cuando envía entradas o consulta un comando que ya pasó por
PreToolUse.
Algunas rutas de herramientas especializadas pueden excluirse de la ruta de hooks predeterminada. Considere los hooks de herramientas como una medida de protección útil, no como un límite de aplicación completo.
Campos de entrada comunes
Cada hook de comando recibe un objeto JSON en stdin.
Estos son los campos compartidos que usará habitualmente:
| Campo | Tipo | Significado |
|---|---|---|
session_id |
string |
ID de la sesión actual de Codex. Los hooks de subagentes usan el ID de la sesión principal. |
transcript_path |
string | null |
Ruta al archivo de transcripción de la sesión, si existe |
cwd |
string |
Directorio de trabajo de la sesión |
hook_event_name |
string |
Nombre del evento de hook actual |
model |
string |
Extensión específica de Codex. Slug del modelo activo |
Los hooks cuyo ámbito es el turno incluyen turn_id como una extensión específica de Codex en sus
tablas específicas del evento.
SessionStart, PreToolUse, PermissionRequest, PostToolUse,
UserPromptSubmit, SubagentStart, SubagentStop y Stop también incluyen
permission_mode, que describe el modo de permisos actual como default,
acceptEdits, plan, dontAsk o bypassPermissions.
transcript_path apunta a una transcripción del chat para facilitar el acceso, pero el
formato de la transcripción no es una interfaz estable para los hooks y puede cambiar con el tiempo.
Si necesita el formato de transmisión completo, consulte Esquemas.
Campos de salida comunes
SessionStart, PreCompact, PostCompact, UserPromptSubmit,
SubagentStop y Stop admiten estos campos JSON compartidos. SubagentStart
acepta la misma estructura para systemMessage y el contexto específico del hook, pero
continue: false no detiene al subagente:
{
"continue": true,
"stopReason": "optional",
"systemMessage": "optional",
"suppressOutput": false
}| Campo | Efecto |
|---|---|
continue |
Si es false, marca esa ejecución del hook como detenida |
stopReason |
Se registra como motivo de la detención |
systemMessage |
Se muestra como advertencia en la interfaz de usuario o el flujo de eventos |
suppressOutput |
Actualmente se analiza, pero aún no está implementado |
Salir con 0 sin generar salida se considera un éxito y Codex continúa.
PreToolUse y PermissionRequest admiten systemMessage, pero continue,
stopReason y suppressOutput no son compatibles actualmente con esos eventos.
Si un hook PreToolUse devuelve uno de esos campos no compatibles, Codex marca
esa ejecución del hook como fallida, informa del error y continúa con la llamada a la herramienta.
PostToolUse admite systemMessage, continue: false y stopReason.
suppressOutput se analiza, pero actualmente no es compatible con ese evento.
Salida de hook grande
De forma predeterminada, Codex limita cada mensaje de salida de hook visible para el modelo a aproximadamente
2500 tokens. Si un hook devuelve más, Codex guarda el texto completo en
<temp_dir>/hook_outputs/<session_id>/<uuid>.txt y proporciona al modelo una
vista previa del principio y el final con la ruta del archivo guardado. Este comportamiento se denomina
desbordamiento: Codex almacena en disco la salida que supera el tamaño permitido y la sustituye por una
vista previa más breve visible para el modelo. Si no se puede escribir el archivo, el modelo sigue
recibiendo una vista previa truncada.
Para cualquier hook de comando que devuelva additionalContext, establezca
additionalContextLimit en el controlador para personalizar el umbral aproximado de
tokens:
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_start.py",
"additionalContextLimit": 5000
}Omita additionalContextLimit para usar el umbral predeterminado de 2500 tokens. Use un
entero positivo para seleccionar un umbral diferente, o 0 para pasar el contexto
adicional completo del controlador directamente al modelo. Codex evalúa cada
controlador coincidente de forma independiente. Para los eventos que no pueden producir contexto
adicional, Codex ignora additionalContextLimit e informa de una advertencia de
configuración.
La configuración se aplica únicamente a additionalContext. Los comentarios de las herramientas y las solicitudes de continuación
mantienen el límite predeterminado.
Dado que la salida que supera el tamaño permitido puede escribirse en el disco, evite devolver secretos u otros datos confidenciales en la salida de los hooks.
Hooks
SessionStart
matcher se aplica a source para este evento.
Campos adicionales a los Campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
source |
string |
Cómo se inició la sesión: startup, resume, clear o compact |
El texto sin formato en stdout se añade como contexto adicional del desarrollador.
El JSON en stdout admite los Campos de salida comunes y esta
estructura específica del hook:
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "Load the workspace conventions before editing."
}
}Ese texto de additionalContext se añade como contexto adicional del desarrollador.
Después de que Codex compacte una sesión raíz, los hooks SessionStart que coincidan con
source: "compact" se ejecutan antes de la siguiente solicitud al modelo. Esto también se aplica cuando
la compactación automática ocurre en medio de un turno: Codex entrega el contexto
adicional del hook a la continuación inmediata, en lugar de esperar a un
turno posterior del usuario. Si el hook devuelve continue: false, Codex finaliza el turno
sin enviar otra solicitud al modelo.
SessionEnd
SessionEnd permite ejecutar un comando cuando finaliza una sesión, por ejemplo, para guardar las
notas finales o limpiar archivos. Se ejecuta para el hilo principal cuando archiva o
elimina una conversación que sigue abierta, cuando Codex se cierra normalmente o después de que una
conversación permanezca inactiva y no esté abierta en ningún cliente conectado durante 30
minutos. No se ejecuta para los subagentes.
Cambiar de conversación o llamar a thread/unsubscribe no finaliza
la sesión inmediatamente, por lo que SessionEnd no se ejecutará de inmediato. Su hook aún puede
leer la transcripción de la sesión mientras se ejecuta.
matcher filtra reason para este evento. Por ahora, reason siempre es other.
Puede omitir matcher o usar other para ejecutarlo en cada evento SessionEnd.
Campos adicionales a los Campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
reason |
string |
Por qué finalizó la sesión: other |
Por ejemplo, un comando SessionEnd recibe:
{
"session_id": "thr_123",
"transcript_path": "/workspace/.codex/rollout.jsonl",
"cwd": "/workspace",
"hook_event_name": "SessionEnd",
"reason": "other"
}Los hooks SessionEnd son informativos. Su salida no orientará a Codex ni mantendrá el
hilo abierto. Si un comando agota el tiempo de espera o finaliza con un error, Codex lo informa como
un fallo del hook.
SubagentStart
matcher se aplica a agent_type para este evento.
Campos adicionales a los Campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensión específica de Codex. ID del turno activo de Codex |
agent_id |
string |
Identificador del subagente |
agent_type |
string |
Tipo o perfil del subagente |
permission_mode |
string |
Modo de permisos actual |
El texto sin formato en stdout se añade como contexto adicional del desarrollador para el subagente.
El JSON en stdout admite systemMessage y esta estructura específica del hook:
{
"hookSpecificOutput": {
"hookEventName": "SubagentStart",
"additionalContext": "Review the repository test conventions first."
}
}Ese texto additionalContext se añade como contexto adicional del desarrollador para el
subagente. continue: false se analiza por motivos de compatibilidad, pero no impide que el
subagente se inicie.
PreToolUse
PreToolUse puede interceptar Bash, las ediciones de archivos realizadas mediante apply_patch,
las llamadas a herramientas MCP y otras herramientas de funciones locales. Consulta la cobertura de
herramientas para conocer las rutas compatibles y las excepciones.
matcher se aplica a tool_name y a los alias de coincidencia. Para las ediciones de archivos mediante
apply_patch, los valores de matcher pueden usar apply_patch, Edit o Write; la entrada del hook
sigue indicando tool_name: "apply_patch".
Campos adicionales a los campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensión específica de Codex. Id. del turno activo de Codex |
tool_name |
string |
Nombre canónico de la herramienta del hook, como Bash, apply_patch o un nombre de MCP como mcp__fs__read |
tool_use_id |
string |
Id. de la llamada a la herramienta para esta invocación |
tool_input |
JSON value |
Entrada específica de la herramienta. Bash y apply_patch usan tool_input.command. MCP y otras herramientas de funciones locales envían sus argumentos. |
El texto sin formato en stdout se ignora.
El JSON en stdout puede usar systemMessage. Para denegar una llamada a una herramienta compatible, devuelve
esta estructura específica del hook:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Destructive command blocked by hook."
}
}Codex también acepta esta estructura de bloque anterior:
{
"decision": "block",
"reason": "Destructive command blocked by hook."
}También puedes usar el código de salida 2 y escribir el motivo del bloqueo en stderr.
Para añadir contexto visible para el modelo sin bloquear, devuelve
hookSpecificOutput.additionalContext:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "The pending command touches generated files."
}
}Para reescribir una llamada a una herramienta compatible sin bloquearla, devuelve
permissionDecision: "allow" con updatedInput:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"command": "echo rewritten"
}
}
}Para los comandos de Bash y apply_patch, updatedInput debe incluir un campo de cadena
command. Para MCP y otras herramientas de funciones locales, updatedInput es el
objeto de argumentos de reemplazo. Devuelve updatedInput únicamente con
permissionDecision: "allow"; las demás estructuras de updatedInput se notifican como
errores.
permissionDecision: "ask", el formato heredado decision: "approve", continue: false,
stopReason y suppressOutput se analizan, pero aún no son compatibles. Codex marca
la ejecución del hook como fallida, informa del error y continúa con la llamada a la herramienta.
PermissionRequest
PermissionRequest se ejecuta cuando Codex está a punto de solicitar aprobación, por ejemplo para una
escalación del shell o una aprobación de red administrada. Puede permitir la solicitud, denegar
la solicitud o abstenerse de decidir y dejar que continúe la solicitud de aprobación normal.
No se ejecuta para comandos que no necesitan aprobación.
matcher se aplica a tool_name y a los alias de coincidencia. Los valores canónicos
actuales incluyen Bash, apply_patch y nombres de herramientas MCP como
mcp__server__tool; apply_patch también coincide con Edit y Write.
Campos adicionales a los campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensión específica de Codex. Id. del turno activo de Codex |
tool_name |
string |
Nombre canónico de la herramienta del hook, como Bash, apply_patch o un nombre de MCP como mcp__fs__read |
tool_input |
JSON value |
Entrada específica de la herramienta. Bash y apply_patch usan tool_input.command, mientras que las herramientas MCP envían todos los argumentos. |
tool_input.description |
string | null |
Motivo de aprobación legible para las personas, cuando Codex dispone de uno |
El texto sin formato en stdout se ignora.
Algunas entradas de herramientas pueden incluir una descripción legible para las personas, pero no dependas de un
campo tool_input.description para todas las herramientas.
Para aprobar la solicitud, devuelve:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "allow"
}
}
}Para denegar la solicitud, devuelve:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "deny",
"message": "Blocked by repository policy."
}
}
}Si varios hooks coincidentes devuelven decisiones, prevalece cualquier deny. De lo contrario, un
allow permite que la solicitud continúe sin mostrar la solicitud de aprobación. Si ningún
hook coincidente toma una decisión, Codex usa el flujo de aprobación normal.
No devuelvas updatedInput, updatedPermissions ni interrupt para
PermissionRequest; esos campos están reservados para funciones futuras y actualmente
provocan un cierre seguro.
PostToolUse
PostToolUse se ejecuta después de que las herramientas compatibles generen una salida, incluidas Bash,
apply_patch, las llamadas a herramientas MCP y otras herramientas de funciones locales. En el caso de Bash, también
se ejecuta después de comandos que finalizan con un estado distinto de cero. No puede deshacer los efectos
secundarios de una herramienta que ya se ha ejecutado. Consulta la cobertura de herramientas para
conocer las rutas compatibles y las excepciones.
matcher se aplica a tool_name y a los alias de coincidencia. Para las ediciones de archivos mediante
apply_patch, los valores de matcher pueden usar apply_patch, Edit o Write; la entrada del hook
sigue indicando tool_name: "apply_patch".
Campos adicionales a los campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensión específica de Codex. Id. del turno activo de Codex |
tool_name |
string |
Nombre canónico de la herramienta del hook, como Bash, apply_patch o un nombre de MCP como mcp__fs__read |
tool_use_id |
string |
Id. de la llamada a la herramienta para esta invocación |
tool_input |
JSON value |
Entrada específica de la herramienta. Bash y apply_patch usan tool_input.command. MCP y otras herramientas de funciones locales envían sus argumentos. |
tool_response |
JSON value |
Salida específica de la herramienta. Las herramientas MCP envían el resultado de la llamada MCP. Otras herramientas de funciones locales suelen enviar su salida destinada al modelo. |
El texto sin formato en stdout se ignora.
El JSON en stdout puede usar systemMessage y esta estructura específica del hook:
{
"decision": "block",
"reason": "The Bash output needs review before continuing.",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "The command updated generated files."
}
}Ese texto additionalContext se añade como contexto adicional del desarrollador.
Para este evento, decision: "block" no deshace el comando de Bash completado.
En su lugar, Codex registra los comentarios, reemplaza el resultado de la herramienta por esos
comentarios y continúa el modelo desde el mensaje proporcionado por el hook.
También puedes usar el código de salida 2 y escribir el motivo de los comentarios en stderr.
Para detener el procesamiento normal del resultado original de la herramienta después de que el comando ya se haya
ejecutado, devuelve continue: false. Codex reemplazará el resultado de la herramienta por
tus comentarios o texto de detención y continuará desde allí.
updatedMCPToolOutput y suppressOutput se analizan, pero aún no son compatibles.
Codex marca la ejecución del hook como fallida, informa del error y continúa con el
procesamiento normal del resultado de la herramienta.
Llamadas a herramientas desde el modo de código
Cuando un modelo usa el modo de código para llamar a una herramienta desde JavaScript, las decisiones del hook se aplican
a esa llamada anidada. PreToolUse puede detener la herramienta antes de que se ejecute o reescribir
su entrada. Un PostToolUse de bloqueo no puede deshacer los efectos secundarios de la herramienta, pero puede
impedir que el resultado original llegue al script en ejecución.
| Resultado del hook | Lo que ve el modo de código |
|---|---|
PreToolUse bloquea |
La promesa de la herramienta se rechaza antes de que esta se ejecute. |
PreToolUse devuelve updatedInput |
La herramienta se ejecuta con la entrada reescrita y la promesa se resuelve con ese resultado. |
PostToolUse devuelve decision: "block" o finaliza con el código 2 |
La herramienta se ejecuta y, después, la promesa se rechaza con el motivo del hook. |
PostToolUse devuelve continue: false |
Codex usa los comentarios del hook como resultado visible para el modelo, pero no rechaza la promesa de la herramienta anidada. |
PreCompact
PreCompact se ejecuta antes de que Codex compacte el chat. matcher se aplica
a trigger, cuyos valores son manual y auto.
Campos adicionales a los campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensión específica de Codex. Id. del turno activo de Codex |
trigger |
string |
Qué activó la compactación: manual o auto |
El texto sin formato en stdout se ignora.
El JSON en stdout admite los campos de salida comunes. Si un
hook PreCompact coincidente devuelve continue: false, Codex se detiene antes de
compactar.
PostCompact
PostCompact se ejecuta después de que Codex compacte el chat. matcher se aplica
a trigger, cuyos valores son manual y auto.
Campos adicionales a los campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensión específica de Codex. Id. del turno activo de Codex |
trigger |
string |
Qué activó la compactación: manual o auto |
El texto sin formato en stdout se ignora.
El JSON en stdout admite los campos de salida comunes. Si un
hook PostCompact coincidente devuelve continue: false, Codex se detiene después de
compactar.
UserPromptSubmit
matcher no se usa actualmente para este evento.
Campos adicionales a los campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensión específica de Codex. Id. del turno activo de Codex |
prompt |
string |
Prompt del usuario que está a punto de enviarse |
El texto sin formato en stdout se añade como contexto adicional del desarrollador.
El JSON en stdout admite Campos de salida comunes y
esta estructura específica del hook:
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "Ask for a clearer reproduction before editing files."
}
}Ese texto additionalContext se añade como contexto adicional para el desarrollador.
Para bloquear el prompt, devuelve:
{
"decision": "block",
"reason": "Ask for confirmation before doing that."
}También puedes usar el código de salida 2 y escribir el motivo del bloqueo en stderr.
SubagentStop
matcher se aplica a agent_type para este evento.
Campos adicionales a los Campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensión específica de Codex. Id. del turno activo de Codex |
agent_id |
string |
Identificador del subagente |
agent_type |
string |
Tipo o perfil del subagente |
agent_transcript_path |
string | null |
Ruta al archivo de transcripción del subagente, si existe |
stop_hook_active |
boolean |
Indica si este subagente ya continuó |
last_assistant_message |
string | null |
Último mensaje del asistente del subagente, si está disponible |
SubagentStop espera JSON en stdout cuando termina con 0. La salida de texto sin formato no es
válida para este evento.
El JSON en stdout admite Campos de salida comunes. Para pedir a
Codex que continúe el flujo del subagente, devuelve:
{
"decision": "block",
"reason": "Run one more focused pass inside the subagent."
}También puedes usar el código de salida 2 y escribir el motivo de la continuación en stderr.
Si algún hook SubagentStop coincidente devuelve continue: false, esto tiene
prioridad sobre las decisiones de continuación de otros hooks SubagentStop
coincidentes.
Stop
matcher no se utiliza actualmente para este evento.
Campos adicionales a los Campos de entrada comunes:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensión específica de Codex. Id. del turno activo de Codex |
stop_hook_active |
boolean |
Indica si Stop ya continuó este turno |
last_assistant_message |
string | null |
Texto del último mensaje del asistente, si está disponible |
Stop espera JSON en stdout cuando termina con 0. La salida de texto sin formato no es válida
para este evento.
El JSON en stdout admite Campos de salida comunes. Para que
Codex siga ejecutándose, devuelve:
{
"decision": "block",
"reason": "Run one more pass over the failing tests."
}También puedes usar el código de salida 2 y escribir el motivo de la continuación en stderr.
Para este evento, decision: "block" no rechaza el turno. En su lugar, indica a
Codex que continúe y crea automáticamente un nuevo prompt de continuación que actúa
como un nuevo prompt del usuario, usando tu reason como texto del prompt.
Si algún hook Stop coincidente devuelve continue: false, esto tiene prioridad
sobre las decisiones de continuación de otros hooks Stop coincidentes.
Esquemas
Si necesitas el formato de transmisión actual exacto, consulta los esquemas generados en el repositorio de Codex en GitHub.
Alias de texto sin formato
- string | null