Ganchos

Este tópico descreve como usar ganchos para executar código personalizado em pontos-chave do ciclo de vida do agente. Os ganchos permitem interceptar chamadas de ferramentas, auditar o comportamento de agentes, aplicar políticas, injetar contexto e controlar o fluxo de execução.

Como funcionam os ganchos

Os ganchos seguem um processo de quatro etapas: um evento é acionado, o SDK verifica se há alguma correspondência, ele chama o retorno de chamada e esse retorno envia uma decisão que controla o que acontece depois.

  1. O agente aciona um evento (por exemplo, está prestes a chamar uma ferramenta).

  2. O SDK verifica cada correspondência de gancho registrada para aquele tipo de evento.

  3. Se houver uma correspondência (ou não houver um padrão de correspondência, o que significa que corresponde a tudo), o SDK chama as funções de retorno de chamada associadas.

  4. Cada retorno de chamada envia um objeto de saída que pode permitir, bloquear ou modificar a operação.

Eventos de gancho

Os seguintes eventos estão disponíveis:

Evento

Quando é acionado

PreToolUse

Antes da execução de uma ferramenta. Pode bloquear a ferramenta ou modificar a entrada.

PostToolUse

Depois que uma ferramenta é executada com sucesso. Pode incluir contexto adicional.

PostToolUseFailure

Após uma falha na execução de uma ferramenta.

UserPromptSubmit

Quando o usuário envia um prompt. Pode incluir contexto adicional.

Stop

Quando o agente está prestes a parar. Pode injetar contexto ou interromper a sessão.

SubagentStart

Quando um subagente é iniciado.

SubagentStop

Quando um subagente está prestes a parar.

PreCompact

Antes que a conversa seja compactada (resumida para se ajustar à janela de contexto).

Notification

Quando o agente emite uma notificação.

PermissionRequest

Quando ocorre uma verificação de permissão da ferramenta.

Configurando ganchos

Passe os ganchos pela opção hooks ao criar uma sessão. Cada evento de gancho é mapeado para uma lista de correspondências, e cada correspondência contém uma lista de funções de retorno de chamada.

import { createCortexCodeSession } from "cortex-code-agent-sdk";

const session = await createCortexCodeSession({
  cwd: process.cwd(),
  hooks: {
    PreToolUse: [
      {
        matcher: "Bash",
        hooks: [
          async (input, toolUseId, context) => {
            console.log("Bash command:", input.tool_input);
            return {};
          },
        ],
      },
    ],
  },
});

Correspondências

Cada correspondência de gancho tem três campos:

Campo

Tipo

Descrição

matcher

string (opcional)

Um padrão regex usado por eventos que oferecem suporte à correspondência. PreToolUse,``PostToolUse`` e PermissionRequest correspondem ao nome da ferramenta. Notification corresponde ao tipo de notificação. PreCompact corresponde ao valor do acionador ("auto" ou "manual"). Se omitido, o gancho é acionado para todos os valores daquele evento.

hooks

lista de retornos de chamada

Uma ou mais funções de retorno de chamada a serem executadas quando houver correspondência.

timeout

number (opcional)

Tempo máximo em segundos para todos os retornos de chamada da correspondência. O padrão é 60.

O campo matcher aceita qualquer padrão regex válido. Por exemplo:

  • "Bash" – corresponde apenas à ferramenta Bash

  • "Write|Edit" – corresponde a gravação ou edição

  • ".*" – corresponde a todas as ferramentas (o mesmo que omitir a correspondência)

Entradas de retorno de chamada

Cada retorno de chamada recebe três argumentos:

Argumento

Descrição

input

Um objeto com dados específicos do evento. Todos os eventos incluem session_id,``transcript_path``, cwd, permission_mode e hook_event_name. Os eventos de ferramentas também incluem tool_name, tool_input e tool_use_id.

toolUseId / tool_use_id

A ferramenta usa ID (para eventos relacionados a ferramentas) ou null.

context

Um objeto de contexto. Reservado para uso futuro (por exemplo, sinais de anulação).

Os campos de entrada variam de acordo com o evento:

Evento

Campos de entrada adicionais

PreToolUse

tool_name, tool_input, tool_use_id

PostToolUse

tool_name, tool_input, tool_response, tool_use_id

PostToolUseFailure

tool_name, tool_input, tool_use_id, error, is_interrupt opcional

UserPromptSubmit

prompt

Stop

stop_hook_active

SubagentStart

agent_id, agent_type

SubagentStop

stop_hook_active, agent_id, agent_transcript_path, agent_type

PreCompact

trigger ("manual" ou "auto"), custom_instructions

Notification

message, notification_type, title opcional

PermissionRequest

tool_name, tool_input, permission_suggestions opcional

Ganchos no ciclo de vida da ferramenta e PermissionRequest também podem incluir os campos opcionais agent_id e agent_type quando eles forem disparados de um subagente.

Saídas de retorno de chamada

Os retornos de chamada enviam um objeto de saída que controla a execução. Os seguintes campos estão disponíveis:

Campo

Tipo

Descrição

continue / continue_

boolean

Se o processamento deve prosseguir. Defina como false para interromper o processamento do site de gancho ou turno atual. Padrão: true.

stopReason

string

Mensagem exibida quando continue for false.

decision

"block"

Defina como "block" para bloquear a operação atual.

reason

string

Mensagem de feedback para o agente sobre a decisão.

systemMessage

string

A mensagem de aviso exibida ao usuário.

hookSpecificOutput

object

Controles específicos do evento (consulte abaixo).

Nota

O SDK Python usa continue_ (com um sublinhado no final) em vez de continue para evitar o conflito de palavras-chave do Python. O SDK converte automaticamente isso em continue ao se comunicar com a CLI.

Saídas específicas de gancho

O campo hookSpecificOutput aceita controles específicos do evento:

PreToolUse

Campo

Descrição

permissionDecision

"allow", "deny" ou "ask". Controla se a ferramenta pode ser executada.

permissionDecisionReason

Motivo da decisão sobre a permissão.

updatedInput

Entrada da ferramenta modificada para usar em vez da original.

PostToolUse

Campo

Descrição

additionalContext

Contexto extra injetado na conversa após a execução da ferramenta.

UserPromptSubmit

Campo

Descrição

additionalContext

Contexto extra injetado na conversa.

PermissionRequest

Campo

Descrição

decision.behavior

"allow" ou "deny". Controla o resultado da permissão.

decision.message

Mensagem exibida ao negar a solicitação da permissão.

Exemplos

Bloquear ferramentas perigosas

Impedir que o agente execute comandos bash específicos:

import { createCortexCodeSession } from "cortex-code-agent-sdk";

const session = await createCortexCodeSession({
  cwd: process.cwd(),
  hooks: {
    PreToolUse: [
      {
        matcher: "Bash",
        hooks: [
          async (input) => {
            const command = (input.tool_input as any)?.command ?? "";
            if (command.includes("rm -rf") || command.includes("DROP TABLE")) {
              return {
                decision: "block",
                reason: "Destructive commands are not allowed",
              };
            }
            return {};
          },
        ],
      },
    ],
  },
});

Permitir automaticamente solicitações de permissão somente leitura

Autorizar solicitações de permissão para ferramentas que leem apenas dados:

hooks: {
  PermissionRequest: [
    {
      matcher: "Read|Glob|Grep",
      hooks: [
        async (input) => {
          return {
            hookSpecificOutput: {
              hookEventName: "PermissionRequest",
              decision: { behavior: "allow" },
            },
          };
        },
      ],
    },
  ],
}

Modificar entrada da ferramenta

Adicionar um tempo limite para todos os comandos bash antes de serem executados:

hooks: {
  PreToolUse: [
    {
      matcher: "Bash",
      hooks: [
        async (input) => {
          const originalCommand = (input.tool_input as any)?.command ?? "";
          return {
            hookSpecificOutput: {
              hookEventName: "PreToolUse",
              updatedInput: { command: `timeout 30 ${originalCommand}` },
            },
          };
        },
      ],
    },
  ],
}

Registros de auditoria

Registrar todas as chamadas de ferramenta para fins de auditoria sem afetar a execução:

import { createCortexCodeSession } from "cortex-code-agent-sdk";
import { appendFileSync } from "node:fs";

const session = await createCortexCodeSession({
  cwd: process.cwd(),
  hooks: {
    PostToolUse: [
      {
        hooks: [
          async (input) => {
            const entry = {
              timestamp: new Date().toISOString(),
              tool: input.tool_name,
              input: input.tool_input,
              sessionId: input.session_id,
            };
            appendFileSync("audit.log", JSON.stringify(entry) + "\n");
            return {};
          },
        ],
      },
    ],
  },
});

Ganchos vs. canUseTool

Tanto os ganchos quanto o retorno de chamada canUseTool pode interceptar chamadas de ferramentas, mas têm finalidades diferentes:

Recurso

canUseTool

Ganchos

Escopo

Somente verificação de permissão pré-execução

Vários eventos do ciclo de vida (ciclo de vida da ferramenta, envio de prompts, interrupções, ciclo de vida do subagente, notificação e compactação)

Eventos

Um: solicitação de permissão

Dez: PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, UserPromptSubmit, Stop, SubagentStart, SubagentStop, Notification e PreCompact

Correspondência de padrões

Sem suporte para correspondência. Invocado para solicitações de permissão que ainda não foram resolvidas por listas de regras.

Sim (as correspondências regex filtram por nome de ferramenta, tipo de notificação ou acionador de compactação, dependendo do evento)

Modificar entrada

Limitado. updatedInput é atualmente usado para pseudoferramentas roteadas por SDK, como AskUserQuestion e ExitPlanMode.

Sim (hookSpecificOutput.updatedInput)

Melhor para

Decisões simples de permissão/negação

Registro de auditoria, injeção de contexto, políticas complexas, ações pós-execução

É possível usar as duas juntas. O retorno de chamada canUseTool é executado como parte do sistema de permissão da CLI, enquanto os ganchos PreToolUse são executados separadamente.