Hooks
Execute scripts determinísticos durante o ciclo de vida do Codex
Os hooks são uma infraestrutura de extensibilidade para o Codex. Permitem injetar os seus próprios scripts no ciclo do agente, possibilitando funcionalidades como:
- Enviar a conversa para um motor personalizado de registo/análise
- Analisar os prompts da sua equipa para impedir a colagem acidental de API keys
- Resumir conversas para criar automaticamente memórias persistentes
- Executar uma verificação de validação personalizada quando um turno da conversa termina, garantindo o cumprimento das normas
- Personalizar os prompts quando estiver num determinado diretório
Comportamento em tempo de execução a ter em conta:
- Todos os hooks correspondentes provenientes de vários ficheiros são executados.
- Vários hooks de comando correspondentes ao mesmo evento são iniciados em simultâneo, pelo que um hook não pode impedir o início de outro hook correspondente.
- Os hooks de comando não geridos têm de ser revistos e considerados fidedignos antes de serem executados.
Os hooks são executados em diferentes momentos de uma conversa:
| Quando | Hooks |
|---|---|
| Durante um turno | PreToolUse, PermissionRequest, PostToolUse, PreCompact, PostCompact, UserPromptSubmit, SubagentStop, Stop |
| Quando uma sessão ou subagente começa | SessionStart, SubagentStart |
| Quando o processo principal termina | SessionEnd (não é executado para subagentes) |
Onde o Codex procura hooks
O Codex deteta hooks junto das camadas de configuração ativas, numa destas formas:
hooks.json- tabelas
[hooks]inline dentro deconfig.toml
Os plugins instalados também podem incluir a configuração do ciclo de vida através do respetivo
manifesto ou de um ficheiro hooks/hooks.json predefinido. Consulte Criar
plugins para conhecer as
regras de empacotamento de plugins.
Na prática, as quatro localizações mais úteis são:
~/.codex/hooks.json~/.codex/config.toml<repo>/.codex/hooks.json<repo>/.codex/config.toml
Se existir mais do que uma origem de hooks, o Codex carrega todos os hooks correspondentes.
As camadas de configuração com maior precedência não substituem os hooks das camadas com menor precedência.
Se uma única camada contiver hooks.json e também [hooks] inline, o Codex
combina-os e apresenta um aviso durante o arranque. Dê preferência a uma representação por camada.
O Codex também pode detetar hooks incluídos em plugins ativados. Os hooks incluídos em plugins são carregados juntamente com outras origens de hooks e utilizam o mesmo processo de revisão de confiança que os restantes hooks não geridos.
Os hooks locais do projeto apenas são carregados quando a camada .codex/ do projeto é considerada fidedigna. Em
projetos não fidedignos, o Codex continua a carregar hooks do utilizador e do sistema a partir das respetivas
camadas de configuração ativas.
Rever e confiar nos hooks
O Codex apresenta os hooks configurados antes de decidir quais podem ser executados. Antes de um hook de comando não gerido poder ser executado, o Codex exige que reveja e considere fidedigna a definição exata do hook. O Codex regista a confiança relativamente ao hash atual do hook, pelo que os hooks novos ou alterados são marcados para revisão e ignorados até serem considerados fidedignos.
Utilize /hooks na CLI para inspecionar as origens dos hooks, rever hooks novos ou alterados,
considerar os hooks fidedignos ou desativar individualmente hooks não geridos. Se houver hooks que necessitem de revisão durante o
arranque, o Codex apresenta um aviso que lhe indica que deve abrir /hooks.
Os hooks geridos provenientes do sistema, de MDM, da cloud ou de origens requirements.toml são marcados
como geridos, considerados fidedignos por política e não podem ser desativados no navegador de hooks do utilizador.
Para uma automatização pontual que já valide as origens dos hooks fora do Codex, passe
--dangerously-bypass-hook-trust para executar os hooks ativados sem exigir
confiança persistente nos hooks para essa invocação.
Estrutura da configuração
Os hooks estão organizados em três níveis:
- Um evento de hook, como
PreToolUse,PostToolUse,PreCompact,SubagentStartouStop - Um grupo de correspondência que determina quando esse evento corresponde
- Um ou mais processadores de hooks executados quando o grupo de correspondência corresponde
{
"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:
descriptionsão metadados opcionais de nível superior para um ficheirohooks.json. Não alteram os hooks que são executados.timeouté expresso em segundos.- Se
timeoutfor omitido, o Codex utiliza600segundos para a maioria dos hooks.SessionEndutiliza1segundo por predefinição e suporta até3segundos.
statusMessageé opcional.additionalContextLimitdefine a quantidade deadditionalContextque um hook de comando pode enviar ao modelo antes de o Codex guardar o texto completo no disco e enviar, em alternativa, uma pré-visualização mais curta. Consulte Resultados extensos de hooks.commandWindowsé uma substituição de comando opcional exclusiva do Windows. Em TOML, utilizecommand_windowsoucommandWindows.- A opção
asyncé analisada, mas os hooks de comando assíncronos ainda não são suportados. - Atualmente, apenas são executados processadores
type: "command". Os processadoresprompteagentsão analisados, mas ignorados. - Os comandos são executados com o
cwdda sessão como diretório de trabalho. - Para hooks locais do repositório, prefira resolver o caminho a partir da raiz do git em vez de utilizar um
caminho relativo como
.codex/hooks/.... O Codex pode ser iniciado a partir de um subdiretório, e um caminho baseado na raiz do git mantém estável a localização do hook.
TOML inline equivalente em 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"Desativar hooks
Os hooks estão ativados por predefinição. Para os desativar em config.toml, defina:
[features]
hooks = falseUtilize hooks como chave de funcionalidade canónica. codex_hooks continua a funcionar como um
alias descontinuado. Os administradores podem forçar a desativação dos hooks da mesma forma em
requirements.toml com [features].hooks = false.
Hooks geridos provenientes de requirements.toml
Os requisitos geridos pela empresa também podem definir hooks inline sob [hooks].
Isto é útil quando os administradores pretendem impor a configuração dos hooks enquanto
distribuem os scripts efetivos através de MDM ou de outro sistema de gestão de dispositivos.
Para impor hooks geridos mesmo aos utilizadores que tenham desativado os hooks localmente, fixe
[features].hooks = true em requirements.toml juntamente com [hooks]. Para ignorar
hooks do utilizador, do projeto, da sessão e dos plugins, continuando a permitir hooks geridos pelos
administradores, defina 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 hooks geridos:
managed_diré utilizado no macOS e no Linux.windows_managed_diré utilizado no Windows.- O Codex não distribui os scripts em
managed_dir; as ferramentas da sua empresa têm de os instalar e atualizar separadamente. - Os comandos de hooks geridos devem utilizar caminhos absolutos de scripts no diretório gerido configurado.
allow_managed_hooks_only = trueignora hooks provenientes de origens do utilizador, do projeto, da sessão e de plugins, mas continua a carregar hooks geridos provenientes derequirements.tomle de outras camadas de configuração geridas.
Hooks incluídos em plugins
Quando um plugin está ativado, o Codex pode carregar hooks de ciclo de vida desse plugin juntamente com hooks do utilizador, do projeto e geridos.
Por predefinição, o Codex procura hooks/hooks.json na raiz do plugin. Um
manifesto de plugin pode substituir essa predefinição por uma entrada hooks em
.codex-plugin/plugin.json. A entrada do manifesto pode ser um caminho com o prefixo ./, uma
matriz de caminhos com o prefixo ./, um objeto de hooks inline ou uma matriz de objetos de
hooks inline.
{
"name": "repo-policy",
"hooks": "./hooks/hooks.json"
}Os caminhos dos hooks do manifesto são resolvidos relativamente à raiz do plugin e têm de permanecer
dentro dessa raiz. Se um manifesto definir hooks, o Codex utiliza essas entradas do manifesto
em vez do hooks/hooks.json predefinido.
Os comandos de hooks de plugins recebem estas variáveis de ambiente:
PLUGIN_ROOTé uma extensão específica do Codex que aponta para a raiz do plugin instalado.PLUGIN_DATAé uma extensão específica do Codex que aponta para o diretório de dados gravável do plugin.- O Codex também define
CLAUDE_PLUGIN_ROOTeCLAUDE_PLUGIN_DATApara garantir a compatibilidade com hooks de plugins existentes.
Os hooks de plugins utilizam o mesmo esquema de eventos que os restantes hooks. Instalar ou ativar um plugin não faz com que os seus hooks sejam automaticamente considerados fidedignos; o Codex ignora os hooks incluídos no plugin até que reveja e considere fidedigna a definição atual do hook.
Padrões de correspondência
O campo matcher é uma expressão regular que filtra quando os hooks são acionados. Utilize "*",
"" ou omita totalmente matcher para corresponder a todas as ocorrências de um evento
suportado.
Apenas alguns eventos atuais do Codex respeitam matcher:
| Evento | O que matcher filtra |
Notas |
|---|---|---|
PermissionRequest |
nome da ferramenta | O suporte inclui Bash, apply_patch* e nomes de ferramentas MCP |
PostToolUse |
nome da ferramenta | Consulte Cobertura de ferramentas |
PostCompact |
acionador de compactação | Os valores são manual ou auto |
PreCompact |
acionador de compactação | Os valores são manual ou auto |
PreToolUse |
nome da ferramenta | Consulte Cobertura de ferramentas |
SessionEnd |
motivo de término | Atualmente, apenas other |
SessionStart |
origem do início | Os valores são startup, resume, clear e compact |
SubagentStart |
tipo de subagente | Os valores dependem do subagente que é iniciado |
SubagentStop |
tipo de subagente | Os valores dependem do subagente que é interrompido |
UserPromptSubmit |
não suportado | Qualquer matcher configurado é ignorado para este evento |
Stop |
não suportado | Qualquer matcher configurado é ignorado para este evento |
*Para apply_patch, os valores de matcher também podem utilizar Edit ou Write.
Exemplos:
Bash^apply_patch$Edit|Writemcp__filesystem__read_filemcp__filesystem__.*startup|resume|clear|compactmanual|auto
Cobertura de ferramentas
PreToolUse e PostToolUse podem observar mais do que chamadas de shell e MCP. A maioria das
ferramentas de funções locais utiliza o mesmo percurso de hooks, pelo que pode fazer a correspondência pelo nome da ferramenta,
inspecionar os respetivos argumentos JSON e, no caso de PreToolUse, bloquear ou reescrever a chamada.
| Percurso da ferramenta | PreToolUse |
PostToolUse |
Notas |
|---|---|---|---|
| Comandos de shell | Sim | Sim | Faça a correspondência como Bash. |
Execução unificada (exec_command) |
Sim | Sim | Faça a correspondência como Bash. Uma consulta posterior de write_stdin pode fornecer o PostToolUse do comando original quando este terminar. |
apply_patch |
Sim | Sim | Faça a correspondência como apply_patch, Edit ou Write. |
| Ferramentas MCP | Sim | Sim | Faça a correspondência pelo nome da ferramenta MCP, como mcp__filesystem__read_file. |
| Outras ferramentas de funções locais | Sim | Sim | Faça a correspondência pelo nome da ferramenta de função, como update_plan. spawn_agent também corresponde a Agent. |
Ferramentas alojadas, como WebSearch |
Não | Não | Estas não utilizam o percurso de hooks das ferramentas de funções locais. |
write_stdin é o transporte para uma sessão de execução unificada existente. Não executa
PreToolUse novamente quando envia dados ou consulta um comando que já passou por
PreToolUse.
Alguns percursos de ferramentas especializadas podem optar por não utilizar o percurso de hooks predefinido. Considere os hooks de ferramentas uma proteção útil, não um limite de aplicação completo.
Campos de entrada comuns
Cada hook de comando recebe um objeto JSON em stdin.
Estes são os campos partilhados que utilizará normalmente:
| Campo | Tipo | Significado |
|---|---|---|
session_id |
string |
ID da sessão atual do Codex. Os hooks de subagentes utilizam o ID da sessão principal. |
transcript_path |
string | null |
Caminho para o ficheiro de transcrição da sessão, se existir |
cwd |
string |
Diretório de trabalho da sessão |
hook_event_name |
string |
Nome do evento de hook atual |
model |
string |
Extensão específica do Codex. Slug do modelo ativo |
Os hooks associados ao turno indicam turn_id como uma extensão específica do Codex nas respetivas
tabelas específicas do evento.
SessionStart, PreToolUse, PermissionRequest, PostToolUse,
UserPromptSubmit, SubagentStart, SubagentStop e Stop também incluem
permission_mode, que descreve o modo de permissões atual como default,
acceptEdits, plan, dontAsk ou bypassPermissions.
transcript_path aponta para uma transcrição da conversa por conveniência, mas o
formato da transcrição não é uma interface estável para hooks e pode mudar ao longo do tempo.
Se precisar do formato de transmissão completo, consulte Esquemas.
Campos de saída comuns
SessionStart, PreCompact, PostCompact, UserPromptSubmit,
SubagentStop e Stop suportam estes campos JSON partilhados. SubagentStart
aceita a mesma estrutura para systemMessage e para o contexto específico do hook, mas
continue: false não interrompe o subagente:
{
"continue": true,
"stopReason": "optional",
"systemMessage": "optional",
"suppressOutput": false
}| Campo | Efeito |
|---|---|
continue |
Se for false, assinala essa execução do hook como interrompida |
stopReason |
Registado como o motivo da interrupção |
systemMessage |
Apresentado como aviso na IU ou no fluxo de eventos |
suppressOutput |
Atualmente analisado, mas ainda não implementado |
A saída 0 sem conteúdo é tratada como sucesso e o Codex continua.
PreToolUse e PermissionRequest suportam systemMessage, mas continue,
stopReason e suppressOutput não são atualmente suportados para esses eventos.
Se um hook PreToolUse devolver um desses campos não suportados, o Codex assinala
essa execução do hook como falhada, comunica o erro e prossegue com a chamada da ferramenta.
PostToolUse suporta systemMessage, continue: false e stopReason.
suppressOutput é analisado, mas não é atualmente suportado para esse evento.
Saída extensa de hooks
Por predefinição, o Codex limita cada mensagem de saída de hook visível para o modelo a cerca de
2 500 tokens. Se um hook devolver mais, o Codex guarda o texto completo em
<temp_dir>/hook_outputs/<session_id>/<uuid>.txt e fornece ao modelo uma
pré-visualização do início e do fim, juntamente com o caminho do ficheiro guardado. Este comportamento denomina-se
spilling: o Codex armazena a saída de grandes dimensões no disco e substitui-a por uma
pré-visualização mais curta, visível para o modelo. Se não for possível escrever o ficheiro, o modelo continua a
receber uma pré-visualização truncada.
Para qualquer hook de comando que devolva additionalContext, defina
additionalContextLimit no processador para personalizar o limiar aproximado de
tokens:
{
"type": "command",
"command": "python3 ~/.codex/hooks/session_start.py",
"additionalContextLimit": 5000
}Omita additionalContextLimit para utilizar o limiar predefinido de 2500 tokens. Utilize um
número inteiro positivo para selecionar um limiar diferente, ou 0 para transmitir o contexto adicional
completo do processador diretamente ao modelo. O Codex avalia cada
processador correspondente de forma independente. Para eventos que não podem produzir contexto
adicional, o Codex ignora additionalContextLimit e comunica um aviso de
configuração.
A definição aplica-se apenas a additionalContext. O feedback das ferramentas e os pedidos de continuação
mantêm o limite predefinido.
Uma vez que a saída de grandes dimensões pode ser escrita no disco, evite devolver segredos ou outros dados confidenciais na saída dos hooks.
Hooks
SessionStart
matcher é aplicado a source para este evento.
Campos adicionais aos Campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
source |
string |
Como a sessão foi iniciada: startup, resume, clear ou compact |
O texto simples em stdout é adicionado como contexto adicional de programador.
O JSON em stdout suporta os Campos de saída comuns e esta
estrutura específica do hook:
{
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": "Load the workspace conventions before editing."
}
}Esse texto additionalContext é adicionado como contexto adicional de programador.
Depois de o Codex compactar uma sessão raiz, os hooks SessionStart que correspondam a
source: "compact" são executados antes do pedido seguinte ao modelo. Isto também se aplica quando a
compactação automática ocorre a meio de um turno: o Codex fornece o contexto adicional do hook
à continuação imediata, em vez de aguardar por um turno posterior do
utilizador. Se o hook devolver continue: false, o Codex termina o turno
sem enviar outro pedido ao modelo.
SessionEnd
SessionEnd permite executar um comando quando uma sessão termina, por exemplo, para guardar notas
finais ou limpar ficheiros. É executado para o thread principal quando arquiva ou
elimina uma conversa que ainda está aberta, quando o Codex fecha normalmente ou depois de uma
conversa estar inativa e não estar aberta em nenhum cliente ligado durante 30
minutos. Não é executado para subagentes.
Mudar para outra conversa ou chamar thread/unsubscribe não termina
a sessão de imediato, pelo que não executa imediatamente SessionEnd. O seu hook ainda pode
ler a transcrição da sessão durante a execução.
matcher filtra reason para este evento. Por enquanto, reason é sempre other.
Pode omitir matcher ou utilizar other para executar em todos os eventos SessionEnd.
Campos adicionais aos Campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
reason |
string |
Motivo pelo qual a sessão terminou: other |
Por exemplo, um comando SessionEnd recebe:
{
"session_id": "thr_123",
"transcript_path": "/workspace/.codex/rollout.jsonl",
"cwd": "/workspace",
"hook_event_name": "SessionEnd",
"reason": "other"
}Os hooks SessionEnd são consultivos. A respetiva saída não orienta o Codex nem mantém o
thread aberto. Se um comando exceder o tempo limite ou terminar com um erro, o Codex comunica-o como
uma falha do hook.
SubagentStart
matcher é aplicado a agent_type para este evento.
Campos adicionais aos Campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensão específica do Codex. ID do turno ativo do Codex |
agent_id |
string |
Identificador do subagente |
agent_type |
string |
Tipo ou perfil do subagente |
permission_mode |
string |
Modo de permissões atual |
O texto simples em stdout é adicionado como contexto adicional de programador para o subagente.
O JSON em stdout suporta systemMessage e esta estrutura específica do hook:
{
"hookSpecificOutput": {
"hookEventName": "SubagentStart",
"additionalContext": "Review the repository test conventions first."
}
}Esse texto additionalContext é adicionado como contexto de programador adicional para o
subagente. continue: false é analisado para efeitos de compatibilidade, mas não impede o
arranque do subagente.
PreToolUse
PreToolUse pode intercetar o Bash, as edições de ficheiros efetuadas através de apply_patch,
as chamadas de ferramentas MCP e outras ferramentas de funções locais. Consulte a cobertura das
ferramentas para conhecer os caminhos suportados e as exceções.
matcher é aplicado a tool_name e aos aliases do comparador. Para edições de ficheiros através de
apply_patch, os valores de matcher podem utilizar apply_patch, Edit ou Write; a entrada do hook
continua a indicar tool_name: "apply_patch".
Campos adicionais aos campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensão específica do Codex. ID do turno ativo do Codex |
tool_name |
string |
Nome canónico da ferramenta do hook, como Bash, apply_patch ou um nome MCP como mcp__fs__read |
tool_use_id |
string |
ID da chamada de ferramenta desta invocação |
tool_input |
JSON value |
Entrada específica da ferramenta. Bash e apply_patch utilizam tool_input.command. O MCP e outras ferramentas de funções locais enviam os respetivos argumentos. |
O texto simples em stdout é ignorado.
O JSON em stdout pode utilizar systemMessage. Para recusar uma chamada de ferramenta suportada, devolva
esta estrutura específica do hook:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "deny",
"permissionDecisionReason": "Destructive command blocked by hook."
}
}O Codex também aceita esta estrutura de bloco mais antiga:
{
"decision": "block",
"reason": "Destructive command blocked by hook."
}Também pode utilizar o código de saída 2 e escrever o motivo do bloqueio em stderr.
Para adicionar contexto visível ao modelo sem bloquear, devolva
hookSpecificOutput.additionalContext:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"additionalContext": "The pending command touches generated files."
}
}Para reescrever uma chamada de ferramenta suportada sem bloquear, devolva
permissionDecision: "allow" com updatedInput:
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"permissionDecision": "allow",
"updatedInput": {
"command": "echo rewritten"
}
}
}Para comandos Bash e apply_patch, updatedInput tem de incluir um campo de cadeia de carateres
command. Para o MCP e outras ferramentas de funções locais, updatedInput é o
objeto de argumentos de substituição. Devolva updatedInput apenas com
permissionDecision: "allow"; outras estruturas de updatedInput são comunicadas como
erros.
permissionDecision: "ask", o decision: "approve" legado, continue: false,
stopReason e suppressOutput são analisados, mas ainda não são suportados. O Codex marca
a execução do hook como falhada, comunica o erro e prossegue com a chamada da ferramenta.
PermissionRequest
PermissionRequest é executado quando o Codex está prestes a pedir aprovação, como para um
escalamento da shell ou uma aprovação de rede gerida. Pode permitir o pedido, recusar
o pedido ou optar por não decidir e deixar que o pedido de aprovação normal prossiga.
Não é executado para comandos que não necessitem de aprovação.
matcher é aplicado a tool_name e aos aliases do comparador. Os valores canónicos
atuais incluem Bash, apply_patch e nomes de ferramentas MCP como
mcp__server__tool; apply_patch também corresponde a Edit e Write.
Campos adicionais aos campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensão específica do Codex. ID do turno ativo do Codex |
tool_name |
string |
Nome canónico da ferramenta do hook, como Bash, apply_patch ou um nome MCP como mcp__fs__read |
tool_input |
JSON value |
Entrada específica da ferramenta. Bash e apply_patch utilizam tool_input.command, enquanto as ferramentas MCP enviam todos os argumentos. |
tool_input.description |
string | null |
Motivo da aprovação legível por humanos, quando o Codex dispõe de um |
O texto simples em stdout é ignorado.
Algumas entradas de ferramentas podem incluir uma descrição legível por humanos, mas não dependa de um
campo tool_input.description para todas as ferramentas.
Para aprovar o pedido, devolva:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "allow"
}
}
}Para recusar o pedido, devolva:
{
"hookSpecificOutput": {
"hookEventName": "PermissionRequest",
"decision": {
"behavior": "deny",
"message": "Blocked by repository policy."
}
}
}Se vários hooks correspondentes devolverem decisões, qualquer deny prevalece. Caso contrário, um
allow permite que o pedido prossiga sem apresentar o pedido de aprovação. Se nenhum
hook correspondente tomar uma decisão, o Codex utiliza o fluxo de aprovação normal.
Não devolva updatedInput, updatedPermissions ou interrupt para
PermissionRequest; esses campos estão reservados para comportamento futuro e, atualmente, provocam uma
falha segura.
PostToolUse
PostToolUse é executado depois de as ferramentas suportadas produzirem resultados, incluindo Bash,
apply_patch, chamadas de ferramentas MCP e outras ferramentas de funções locais. Para o Bash, também
é executado após comandos que terminem com um estado diferente de zero. Não pode anular os efeitos
secundários de uma ferramenta que já tenha sido executada. Consulte a cobertura das ferramentas para
conhecer os caminhos suportados e as exceções.
matcher é aplicado a tool_name e aos aliases do comparador. Para edições de ficheiros através de
apply_patch, os valores de matcher podem utilizar apply_patch, Edit ou Write; a entrada do hook
continua a indicar tool_name: "apply_patch".
Campos adicionais aos campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensão específica do Codex. ID do turno ativo do Codex |
tool_name |
string |
Nome canónico da ferramenta do hook, como Bash, apply_patch ou um nome MCP como mcp__fs__read |
tool_use_id |
string |
ID da chamada de ferramenta desta invocação |
tool_input |
JSON value |
Entrada específica da ferramenta. Bash e apply_patch utilizam tool_input.command. O MCP e outras ferramentas de funções locais enviam os respetivos argumentos. |
tool_response |
JSON value |
Saída específica da ferramenta. As ferramentas MCP enviam o resultado da chamada MCP. Outras ferramentas de funções locais enviam normalmente a respetiva saída destinada ao modelo. |
O texto simples em stdout é ignorado.
O JSON em stdout pode utilizar systemMessage e esta estrutura específica do hook:
{
"decision": "block",
"reason": "The Bash output needs review before continuing.",
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "The command updated generated files."
}
}Esse texto additionalContext é adicionado como contexto de programador adicional.
Para este evento, decision: "block" não anula o comando Bash concluído.
Em vez disso, o Codex regista os comentários, substitui o resultado da ferramenta por esses
comentários e permite que o modelo prossiga a partir da mensagem fornecida pelo hook.
Também pode utilizar o código de saída 2 e escrever o motivo dos comentários em stderr.
Para interromper o processamento normal do resultado original da ferramenta depois de o comando já ter
sido executado, devolva continue: false. O Codex substituirá o resultado da ferramenta pelos
seus comentários ou texto de interrupção e prosseguirá a partir daí.
updatedMCPToolOutput e suppressOutput são analisados, mas ainda não são suportados.
O Codex marca a execução do hook como falhada, comunica o erro e prossegue com o
processamento normal do resultado da ferramenta.
Chamadas de ferramentas no modo de código
Quando um modelo utiliza o modo de código para chamar uma ferramenta a partir de JavaScript, as decisões do hook aplicam-se
à chamada aninhada. PreToolUse pode parar a ferramenta antes da execução ou reescrever
a respetiva entrada. Um PostToolUse de bloqueio não pode anular os efeitos secundários da ferramenta, mas pode
impedir que o resultado original chegue ao script em execução.
| Resultado do hook | O que o modo de código vê |
|---|---|
PreToolUse bloqueia |
A promessa da ferramenta é rejeitada antes de a ferramenta ser executada. |
PreToolUse devolve updatedInput |
A ferramenta é executada com a entrada reescrita e a promessa é resolvida com esse resultado. |
PostToolUse devolve decision: "block" ou termina com o código 2 |
A ferramenta é executada e, em seguida, a promessa é rejeitada com o motivo do hook. |
PostToolUse devolve continue: false |
O Codex utiliza os comentários do hook para o resultado visível ao modelo, mas não rejeita a promessa da ferramenta aninhada. |
PreCompact
PreCompact é executado antes de o Codex compactar a conversa. matcher é aplicado
a trigger, cujos valores são manual e auto.
Campos adicionais aos campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensão específica do Codex. ID do turno ativo do Codex |
trigger |
string |
O que desencadeou a compactação: manual ou auto |
O texto simples em stdout é ignorado.
O JSON em stdout suporta os campos de saída comuns. Se um
hook PreCompact correspondente devolver continue: false, o Codex para antes de
compactar.
PostCompact
PostCompact é executado depois de o Codex compactar a conversa. matcher é aplicado
a trigger, cujos valores são manual e auto.
Campos adicionais aos campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensão específica do Codex. ID do turno ativo do Codex |
trigger |
string |
O que desencadeou a compactação: manual ou auto |
O texto simples em stdout é ignorado.
O JSON em stdout suporta os campos de saída comuns. Se um
hook PostCompact correspondente devolver continue: false, o Codex para depois de
compactar.
UserPromptSubmit
matcher não é utilizado atualmente para este evento.
Campos adicionais aos campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensão específica do Codex. ID do turno ativo do Codex |
prompt |
string |
Pedido do utilizador que está prestes a ser enviado |
O texto simples em stdout é adicionado como contexto de programador adicional.
O JSON em stdout suporta Campos de saída comuns e
esta estrutura específica do hook:
{
"hookSpecificOutput": {
"hookEventName": "UserPromptSubmit",
"additionalContext": "Ask for a clearer reproduction before editing files."
}
}Esse texto additionalContext é adicionado como contexto de programador adicional.
Para bloquear o pedido, devolva:
{
"decision": "block",
"reason": "Ask for confirmation before doing that."
}Também pode utilizar o código de saída 2 e escrever o motivo do bloqueio em stderr.
SubagentStop
matcher é aplicado a agent_type para este evento.
Campos adicionais aos Campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensão específica do Codex. ID do turno ativo do Codex |
agent_id |
string |
Identificador do subagente |
agent_type |
string |
Tipo ou perfil do subagente |
agent_transcript_path |
string | null |
Caminho para o ficheiro de transcrição do subagente, caso exista |
stop_hook_active |
boolean |
Se este subagente já teve continuação |
last_assistant_message |
string | null |
Mensagem mais recente do assistente do subagente, se disponível |
SubagentStop espera JSON em stdout quando termina com 0. Uma saída de texto simples é
inválida para este evento.
O JSON em stdout suporta Campos de saída comuns. Para pedir ao
Codex que prossiga com o fluxo do subagente, devolva:
{
"decision": "block",
"reason": "Run one more focused pass inside the subagent."
}Também pode utilizar o código de saída 2 e escrever o motivo da continuação em stderr.
Se algum hook SubagentStop correspondente devolver continue: false, essa decisão tem
precedência sobre as decisões de continuação de outros hooks SubagentStop
correspondentes.
Stop
matcher não é atualmente utilizado para este evento.
Campos adicionais aos Campos de entrada comuns:
| Campo | Tipo | Significado |
|---|---|---|
turn_id |
string |
Extensão específica do Codex. ID do turno ativo do Codex |
stop_hook_active |
boolean |
Se este turno já teve continuação por Stop |
last_assistant_message |
string | null |
Texto da mensagem mais recente do assistente, se disponível |
Stop espera JSON em stdout quando termina com 0. Uma saída de texto simples é inválida
para este evento.
O JSON em stdout suporta Campos de saída comuns. Para manter o
Codex em execução, devolva:
{
"decision": "block",
"reason": "Run one more pass over the failing tests."
}Também pode utilizar o código de saída 2 e escrever o motivo da continuação em stderr.
Para este evento, decision: "block" não rejeita o turno. Em vez disso, indica ao
Codex que deve continuar e cria automaticamente um novo pedido de continuação que funciona
como um novo pedido do utilizador, utilizando o seu reason como texto desse pedido.
Se algum hook Stop correspondente devolver continue: false, essa decisão tem precedência
sobre as decisões de continuação de outros hooks Stop correspondentes.
Esquemas
Se precisar do formato wire atual exato, consulte os esquemas gerados no repositório Codex no GitHub.
Aliases de texto simples
- string | null