Português

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 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 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, SubagentStart ou Stop
  • 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:

  • description são metadados opcionais de nível superior para um ficheiro hooks.json. Não alteram 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 utiliza 1 segundo por predefinição e suporta 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 Resultados extensos de hooks.
  • commandWindows é uma substituição de comando opcional exclusiva do Windows. Em TOML, utilize command_windows ou commandWindows.
  • 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 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, 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 = false

Utilize 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 = true ignora hooks provenientes de origens do utilizador, do projeto, da sessão e de plugins, mas continua a carregar hooks geridos provenientes 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 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_ROOT e CLAUDE_PLUGIN_DATA para 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|Write
  • mcp__filesystem__read_file
  • mcp__filesystem__.*
  • startup|resume|clear|compact
  • manual|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