Português

Hooks

Hooks

Execute scripts determinísticos durante o ciclo de vida do Codex

Os hooks são uma estrutura de extensibilidade para o Codex. Permitem executar scripts ou ferramentas MCP durante o ciclo de agentes, 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 de conversa termina, impondo normas
  • Personalizar os prompts quando estiver num determinado diretório

Comportamento em tempo de execução a ter em conta:

  • Todos os hooks correspondentes 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 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 interrompe um turno ativo Interrupt (não é executado para subagentes)
Quando uma sessão ou subagente inicia SessionStart, SubagentStart
Quando a thread principal termina SessionEnd (não é executado para subagentes)

Onde o Codex procura hooks

O Codex descobre hooks junto das camadas de configuração ativas, numa destas formas:

  • hooks.json
  • tabelas [hooks] inline dentro de config.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 de menor precedência. Se uma única camada contiver hooks.json e [hooks] inline, o Codex combina-os e apresenta um aviso no arranque. Prefira uma representação por camada.

O Codex também pode descobrir 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 fluxo de revisão de confiança que os restantes hooks não geridos.

Os hooks locais do projeto só 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 considerar hooks fidedignos

O Codex apresenta uma lista dos hooks configurados antes de decidir quais podem ser executados. Antes de um hook 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 assinalados 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 hooks fidedignos ou desativar hooks não geridos individuais. Se existirem hooks que necessitem de revisão no arranque, o Codex apresenta um aviso que lhe indica que deve abrir /hooks.

Os hooks geridos provenientes de origens do sistema, MDM, cloud ou requirements.toml são assinalados como geridos, considerados fidedignos por política e não podem ser desativados no navegador de hooks do utilizador.

Para automatizações pontuais que já validem as origens dos hooks fora do Codex, transmita --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, SubagentStart ou Stop
  • Um grupo de correspondência que decide quando esse evento corresponde
  • Um ou mais processadores de hooks que são 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:

  • description consiste em metadados opcionais de nível superior para um ficheiro hooks.json. Não altera os hooks que são executados.
  • timeout é expresso em segundos.
  • Se timeout for omitido, o Codex utiliza 600 segundos para a maioria dos hooks.
    • SessionEnd e Interrupt utilizam 1 segundo por predefinição e suportam até 3 segundos.
  • statusMessage é opcional.
  • additionalContextLimit define a quantidade de additionalContext que 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 Saída extensa de hooks.
  • commandWindows é uma substituição opcional do comando, exclusiva do Windows. Em TOML, utilize command_windows ou commandWindows.
  • Defina async como true para executar um hook de comando em segundo plano.
  • São suportados processadores command e mcp_tool. Os processadores prompt e agent são analisados, mas ignorados.
  • Os comandos são executados com o cwd da sessão como diretório de trabalho.
  • Para hooks locais do repositório, dê preferência à resolução 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"

Hooks de ferramentas MCP

Um hook de ferramenta MCP permite que um evento do ciclo de vida invoque uma ferramenta num servidor MCP já ligado. Envia argumentos estruturados diretamente para a ferramenta e utiliza a mesma revisão de confiança e o mesmo contrato de resultados que um hook de comando.

Configurar um hook de ferramenta MCP

Este hook solicita ao servidor MCP scanner que analise cada patch depois de o Codex escrever ou editar ficheiros:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "mcp_tool",
            "server": "scanner",
            "tool": "scan_patch",
            "input": { "patch": "${tool_input.command}" },
            "timeout": 30,
            "statusMessage": "Scanning edited files"
          }
        ]
      }
    ]
  }
}
Campo Significado
type Tem de ser mcp_tool.
server Nome obrigatório de um servidor MCP já ligado.
tool Nome obrigatório de uma ferramenta exposta por esse servidor.
input Objeto JSON opcional de modelos de argumentos. A predefinição é {}.
timeout Limite de tempo opcional da execução ativa, em segundos. A predefinição é 600.
statusMessage Mensagem opcional apresentada durante a execução do hook.

Expandir argumentos a partir do evento do hook

Utilize ${field.nested} para ler um campo com notação de pontos a partir do evento do hook. Um marcador de posição que preencha um valor inteiro mantém o respetivo tipo JSON. Um marcador de posição dentro de uma string maior é apresentado como texto. O Codex expande objetos e matrizes recursivamente.

Para um evento que contenha {"tool_input":{"file_path":"src/main.rs","count":3}}, este modelo de argumentos:

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

transforma-se em:

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

Execução e ciclo de vida

  • Os hooks utilizam uma ligação MCP existente. Não iniciam nem voltam a ligar servidores.
  • Um hook pode bloquear uma operação quando a ferramenta devolve uma decisão de bloqueio. Os erros, servidores em falta e ferramentas indisponíveis não bloqueiam a operação.
  • Os hooks de ferramentas MCP são executados de forma síncrona. Não solicitam aprovação da ferramenta nem acionam outros hooks.
  • Aplica-se o limite de tempo mais curto do hook ou do servidor. O tempo de espera por uma resposta de elicitação MCP não é contabilizado no limite de tempo.
  • Os hooks SessionStart podem ser executados antes de um servidor MCP estar pronto. Se isso acontecer, não bloqueiam a sessão.
  • SessionEnd não suporta hooks de ferramentas MCP.

Desativar os hooks

Os hooks estão ativados por predefinição. Para os desativar em config.toml, defina:

[features]
hooks = false

Utilize hooks como chave canónica da funcionalidade. codex_hooks continua a funcionar como alias preterido. Os administradores podem forçar a desativação dos hooks da mesma forma em requirements.toml com [features].hooks = false.

Hooks geridos a partir de requirements.toml

Os requisitos geridos pela empresa também podem definir hooks inline em [hooks]. Isto é útil quando os administradores pretendem impor a configuração dos hooks, enquanto fornecem os próprios scripts através de MDM ou de outro sistema de gestão de dispositivos. Para impor hooks geridos mesmo aos utilizadores que desativaram os hooks localmente, fixe [features].hooks = true em requirements.toml juntamente com [hooks]. Para ignorar hooks do utilizador, do projeto, da sessão e de plugins, permitindo ainda assim hooks geridos pelo administrador, 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 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 = true ignora hooks provenientes de origens do utilizador, do projeto, da sessão e de plugins, mas continua a carregar hooks geridos a partir de requirements.toml e de outras camadas de configuração geridas.

Hooks incluídos em plugins

Quando um plugin está ativado, o Codex pode carregar hooks do ciclo de vida desse plugin juntamente com hooks do utilizador, do projeto e geridos.

Por predefinição, o Codex procura hooks/hooks.json dentro da raiz do plugin. Um manifesto de plugin pode substituir essa predefinição com 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 de 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_ROOT e CLAUDE_PLUGIN_DATA para 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 torna automaticamente fidedignos os respetivos hooks; 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 string de 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 do fim 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 inicia
SubagentStop tipo de subagente Os valores dependem do subagente que termina
UserPromptSubmit não suportado Qualquer matcher configurado é ignorado para este evento
Stop não suportado Qualquer matcher configurado é ignorado para este evento
Interrupt 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|Write
  • mcp__filesystem__read_file
  • mcp__filesystem__.*
  • startup|resume|clear|compact
  • manual|auto

Cobertura das ferramentas

PreToolUse e PostToolUse podem observar mais do que chamadas de shell e MCP. A maioria das ferramentas de função locais utiliza o mesmo caminho de hooks, pelo que pode estabelecer correspondência com o nome da ferramenta, inspecionar os respetivos argumentos JSON e, no caso de PreToolUse, bloquear ou reescrever a chamada.

Caminho da ferramenta PreToolUse PostToolUse Notas
Comandos de shell Sim Sim Corresponde como Bash.
Execução unificada (exec_command) Sim Sim Corresponde como Bash. Uma consulta write_stdin posterior pode fornecer o PostToolUse do comando original quando esse comando terminar.
apply_patch Sim Sim Corresponde como apply_patch, Edit ou Write.
Ferramentas MCP Sim Sim Corresponde ao nome da ferramenta MCP, como mcp__filesystem__read_file.
Outras ferramentas de função locais Sim Sim Corresponde ao 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 caminho de hooks de ferramentas de função 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 caminhos de ferramentas especializados podem optar por não utilizar o caminho de hooks predefinido. Considere os hooks de ferramentas uma proteção útil, não um limite de imposição completo.

Campos de entrada comuns

Cada hook de comando recebe um objeto JSON em stdin.

Estes são os campos partilhados que utilizará habitualmente:

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 com âmbito de turno apresentam turn_id como uma extensão específica do Codex nas respetivas tabelas específicas do evento.

SessionStart, PreToolUse, PermissionRequest, PostToolUse, UserPromptSubmit, SubagentStart, SubagentStop, Stop e Interrupt 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 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 com 0 sem resultados é considerada um êxito 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 continua a chamada da ferramenta.

PostToolUse suporta systemMessage, continue: false e stopReason. suppressOutput é analisado, mas não é atualmente suportado para esse evento.

Resultados extensos de hooks

Por predefinição, o Codex limita cada mensagem de resultados de hooks 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 com o caminho do ficheiro guardado. Este comportamento chama-se spilling: o Codex armazena no disco os resultados de tamanho excessivo e substitui-os 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 prompts de continuação mantêm o limite predefinido.

Uma vez que os resultados de tamanho excessivo podem ser escritos no disco, evite devolver segredos ou outros dados sensíveis nos resultados dos hooks.

Executar hooks em segundo plano

Por predefinição, o Codex aguarda que um hook de comando termine antes de prosseguir com a operação que o acionou. Defina async como true para executar um hook de comando em segundo plano enquanto o Codex continua.

Configurar um hook em segundo plano

Adicione "async": true a um processador de comandos em hooks.json:

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

Para um hook inline em config.toml, defina async = true:

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

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

Os hooks em segundo plano utilizam a mesma entrada, correspondência, análise de confiança, tempo limite e processamento de saídas extensas que os hooks de comando síncronos. Tal como noutros hooks de comando, timeout é medido em segundos e a predefinição é 600. Os hooks Interrupt utilizam uma predefinição de um segundo e um máximo de três segundos, inclusive quando são executados em segundo plano.

Como são executados os hooks em segundo plano

Quando um hook em segundo plano termina, o Codex fornece os resultados informativos suportados no ponto seguro seguinte da conversa:

  • Se estiver ativo um turno, o Codex aguarda que o pedido atual ao modelo e as chamadas de ferramentas terminem e, em seguida, disponibiliza os resultados ao pedido seguinte ao modelo nesse turno.
  • Se não estiver ativo nenhum turno, o Codex aguarda até ao turno seguinte do utilizador. A conclusão de um hook em segundo plano não inicia um novo turno.

Utilize a mesma saída JSON específica do evento que utilizaria num hook síncrono. O Codex adiciona additionalContext ao contexto do modelo e apresenta systemMessage como aviso.

Limitações

  • O Codex executa até oito hooks em segundo plano em simultâneo por sessão. Os hooks adicionais aguardam até que um hook em execução termine.
  • Cada invocação correspondente é executada de forma independente e os hooks em segundo plano podem terminar numa ordem diferente daquela em que começaram.
  • Quando a sessão termina, o Codex cancela os hooks em segundo plano não concluídos e elimina os resultados que não tenham sido fornecidos.
  • Os hooks SessionEnd são sempre executados de forma síncrona.

Hooks

SessionStart

matcher é aplicado a source neste evento.

Campos além dos Campos de entrada comuns:

Campo Tipo Significado
source string Como a sessão começou: startup, resume, clear ou compact

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": "SessionStart",
    "additionalContext": "Load the workspace conventions before editing."
  }
}

Esse texto additionalContext é adicionado como contexto de programador adicional.

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 no 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 invocar thread/unsubscribe não termina a sessão de imediato, pelo que não executará imediatamente SessionEnd. O hook ainda pode ler a transcrição da sessão durante a execução.

matcher filtra reason neste evento. Por enquanto, reason é sempre other. Pode omitir matcher ou utilizar other para executar em todos os eventos SessionEnd.

Campos além dos 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 sempre executados de forma síncrona, mesmo quando async é true. São consultivos, pelo que os respetivos resultados não orientarão o Codex nem manterão o thread aberto. Se um comando exceder o limite de tempo ou terminar com um erro, o Codex comunica-o como uma falha do hook.

SubagentStart

matcher é aplicado a agent_type neste evento.

Campos além dos 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ão atual

O texto simples em stdout é adicionado como contexto de programador adicional 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 fins de compatibilidade, mas não impede o início do subagente.

PreToolUse

PreToolUse pode intercetar Bash, edições de ficheiros efetuadas através de apply_patch, chamadas de ferramentas MCP e outras ferramentas de função locais. Consulte Cobertura das ferramentas para conhecer os caminhos suportados e as exceções.

matcher é aplicado a tool_name e aos aliases de correspondência. 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 comunicar tool_name: "apply_patch".

Campos além dos 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 da ferramenta para esta invocação
tool_input JSON value Entrada específica da ferramenta. Bash e apply_patch utilizam tool_input.command. As ferramentas MCP e outras ferramentas de função 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 bloqueio 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 para o modelo sem bloquear, devolva hookSpecificOutput.additionalContext:

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

Para reescrever uma chamada de ferramenta suportada sem a 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 string command. Para MCP e outras ferramentas de função locais, updatedInput é o objeto de argumentos substituto. 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 assinala a execução do hook como falhada, comunica o erro e continua a chamada da ferramenta.

PermissionRequest

PermissionRequest é executado quando o Codex está prestes a pedir aprovação, por exemplo, para uma escalada do shell ou aprovação da rede gerida. Pode permitir o pedido, recusar o pedido ou não tomar uma decisão e deixar que o pedido de aprovação normal continue. Não é executado para comandos que não necessitem de aprovação.

matcher é aplicado a tool_name e aos aliases de correspondência. 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 além dos 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 nem interrupt para PermissionRequest; esses campos estão reservados para comportamento futuro e atualmente provocam uma falha fechada.

PostToolUse

PostToolUse é executado depois de as ferramentas suportadas produzirem resultados, incluindo Bash, apply_patch, chamadas de ferramentas MCP e outras ferramentas de função locais. Para Bash, também é executado após comandos que terminem com um estado diferente de zero. Não pode desfazer efeitos secundários de uma ferramenta que já tenha sido executada. Consulte Cobertura das ferramentas para conhecer os caminhos suportados e as exceções.

matcher é aplicado a tool_name e aos aliases de correspondência. 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 comunicar tool_name: "apply_patch".

Campos além dos 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 da ferramenta para esta invocação
tool_input JSON value Entrada específica da ferramenta. Bash e apply_patch utilizam tool_input.command. As ferramentas MCP e outras ferramentas de função 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ção locais enviam normalmente os respetivos resultados dirigidos 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.

Neste evento, decision: "block" não desfaz o comando Bash concluído. Em vez disso, o Codex regista o feedback, substitui o resultado da ferramenta por esse feedback e faz o modelo continuar a partir da mensagem fornecida pelo hook.

Também pode utilizar o código de saída 2 e escrever o motivo do feedback 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 pelo seu feedback ou texto de interrupção e continuará a partir daí.

updatedMCPToolOutput e suppressOutput são analisados, mas ainda não são suportados. O Codex assinala a execução do hook como falhada, comunica o erro e continua 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 invocar uma ferramenta a partir de JavaScript, as decisões dos hooks aplicam-se a essa chamada aninhada. PreToolUse pode interromper a ferramenta antes de esta ser executada ou reescrever a respetiva entrada. Um PostToolUse de bloqueio não pode desfazer 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 o feedback do hook para o resultado visível para o 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 além dos 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 acionou a compactação: manual ou auto

O texto simples em stdout é ignorado.

O JSON em stdout suporta 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 além dos 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 acionou a compactação: manual ou auto

O texto simples em stdout é ignorado.

O JSON em stdout suporta Campos de saída comuns. Se um hook PostCompact correspondente devolver continue: false, o Codex para depois de compactar.

UserPromptSubmit

matcher não é atualmente utilizado neste evento.

Campos além dos Campos de entrada comuns:

Campo Tipo Significado
turn_id string Extensão específica do Codex. ID do turno ativo do Codex
prompt string Prompt 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 prompt, 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 neste evento.

Campos além dos 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, se existir
stop_hook_active boolean Se este subagente já foi continuado
last_assistant_message string | null Mensagem mais recente do assistente do subagente, se disponível

SubagentStop espera JSON em stdout quando termina com 0. A saída em texto simples é inválida para este evento.

O JSON em stdout suporta Campos de saída comuns. Para pedir ao Codex que continue 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 qualquer hook SubagentStop correspondente devolver continue: false, isso tem precedência sobre as decisões de continuação de outros hooks SubagentStop correspondentes.

Stop

matcher não é atualmente utilizado neste evento.

Campos além dos 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á foi continuado 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. A saída em 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.

Neste evento, decision: "block" não rejeita o turno. Em vez disso, indica ao Codex que continue e cria automaticamente um novo prompt de continuação que funciona como um novo prompt do utilizador, utilizando o seu reason como texto desse prompt.

Se qualquer hook Stop correspondente devolver continue: false, isso tem precedência sobre as decisões de continuação de outros hooks Stop correspondentes.

Interrupt

Interrupt é executado quando interrompe um turno ativo na thread principal. Utilize-o para registar a interrupção ou limpar o trabalho iniciado por um hook. Não é executado para threads inativas nem para subagentes, e qualquer matcher configurado é ignorado.

Além dos campos de entrada comuns, o evento inclui turn_id, o ID do turno interrompido, e permission_mode.

Os hooks de comando têm, por predefinição, um tempo limite de um segundo. Os tempos limite configurados estão limitados a um a três segundos. A saída do hook não pode impedir a interrupção nem reiniciar o turno. Termine com 0 sem saída ou devolva JSON com um systemMessage opcional para apresentar um aviso. A saída de texto simples é inválida para este evento.

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

Esquemas

Se precisar do formato de transmissão atual exato, consulte os esquemas gerados no repositório GitHub do Codex.

Aliases de texto simples

  • string | null