Domínio 1 — Agentic Architecture & Orchestration · Lição 6 de 7

Hooks, enforcement programático e handoffs

Objetivos de aprendizagem

Prompt orienta; hook garante

Instruções no prompt são probabilísticas: mesmo bem escritas, têm taxa de falha diferente de zero — o modelo pode pular a verificação de identidade em 1 caso a cada 20, e em operação financeira isso é inaceitável. Hooks e gates programáticos são determinísticos: código que roda fora do modelo e não pode ser "convencido" a abrir exceção.

MecanismoNaturezaUse quando
Instrução no system prompt / few-shotProbabilísticaPreferências de estilo, priorização, heurísticas de decisão em que erro ocasional é tolerável.
Hook / gate programáticoDeterminísticaCompliance obrigatória: verificação de identidade antes de operação financeira, tetos de valor, políticas regulatórias.

Heurística de prova: se o enunciado fala em "garantir", "nunca permitir", "compliance", valor financeiro ou consequência regulatória — a resposta correta envolve enforcement programático (hook/gate). Alternativas que "reforçam o prompt" ou "adicionam few-shot" são distratores quando a exigência é determinística.

Os dois hooks que a prova cobra

flowchart LR
    M[Modelo pede tool_use
process_refund $750] --> H{Hook PreToolUse} H -- viola política --> B[Bloqueia + motivo:
reembolso acima de $500
exige aprovação humana] B --> E[Fluxo de escalação
handoff estruturado] H -- ok --> X[Executa a ferramenta] X --> P[Hook PostToolUse
normaliza timestamps/status] P --> M2[Resultado normalizado
volta ao modelo]

Hooks no Claude Agent SDK

No Agent SDK, hooks são callbacks Python registrados por evento, opcionalmente filtrados por ferramenta via HookMatcher. Um PreToolUse pode negar a chamada com permissionDecision: "deny" e um motivo — que o modelo lê e usa para se redirecionar (ex.: escalar):

import datetime
from claude_agent_sdk import ClaudeAgentOptions, HookMatcher

REFUND_LIMIT = 500

async def block_large_refunds(input_data, tool_use_id, context):
    """PreToolUse: garantia deterministica da politica de reembolso."""
    tool_name = input_data.get("tool_name", "")
    tool_input = input_data.get("tool_input", {})
    if tool_name.endswith("process_refund"):
        amount = float(tool_input.get("amount", 0))
        if amount > REFUND_LIMIT:
            return {
                "hookSpecificOutput": {
                    "hookEventName": "PreToolUse",
                    "permissionDecision": "deny",
                    "permissionDecisionReason": (
                        "Reembolsos acima de $%d exigem aprovacao humana. "
                        "Use escalate_to_human com o handoff estruturado."
                        % REFUND_LIMIT
                    ),
                }
            }
    return {}

async def normalize_timestamps(input_data, tool_use_id, context):
    """PostToolUse: normaliza formatos heterogeneos antes de o modelo ler."""
    response = input_data.get("tool_response", {})
    raw = response.get("created_at")
    if isinstance(raw, (int, float)):
        iso = datetime.datetime.fromtimestamp(
            raw, tz=datetime.timezone.utc
        ).isoformat()
        # Anexa contexto adicional normalizado para o modelo
        return {
            "hookSpecificOutput": {
                "hookEventName": "PostToolUse",
                "additionalContext": "created_at normalizado (ISO 8601): " + iso,
            }
        }
    return {}

options = ClaudeAgentOptions(
    allowed_tools=["mcp__support__get_customer",
                   "mcp__support__process_refund",
                   "mcp__support__escalate_to_human"],
    hooks={
        "PreToolUse": [
            HookMatcher(matcher="mcp__support__process_refund",
                        hooks=[block_large_refunds]),
        ],
        "PostToolUse": [
            HookMatcher(hooks=[normalize_timestamps]),  # todas as ferramentas
        ],
    },
)

O motivo da negação (permissionDecisionReason) não é burocracia: é o texto que o modelo recebe no lugar do resultado. Um motivo acionável ("use escalate_to_human") redireciona o agente para o fluxo alternativo correto; um "denied" seco deixa o agente sem saída.

Gate de pré-requisito

Variante do PreToolUse cobrada na sample question oficial: manter estado no harness (ex.: "customer verificado?") e bloquear ferramentas downstream até o pré-requisito completar. Um PostToolUse em get_customer marca verified = True; um PreToolUse em lookup_order/process_refund nega enquanto verified for False. Nenhum prompt, por melhor que seja, dá essa garantia — em produção o agente pulava get_customer em 12% dos casos mesmo com instrução "obrigatória" no prompt.

Handoff estruturado para escalação humana

Quando o agente escala no meio do processo, o humano que assume não tem acesso ao transcript da conversa. O task statement 1.4 exige um protocolo de handoff estruturado, tipicamente os campos:

Além do handoff, o task statement 1.4 cobra a decomposição de solicitações multi-questão: separar as questões distintas do cliente, investigar cada uma (em paralelo, compartilhando contexto) e sintetizar uma resolução unificada — em vez de responder só à primeira questão.

Pegadinhas da prova

Resumo em 5 linhas

  1. Prompt = orientação probabilística; hook/gate = garantia determinística. Compliance obrigatória (identidade antes de operação financeira, tetos de valor) exige hooks.
  2. PreToolUse intercepta antes de executar: bloqueia violações de política (reembolso > $500) com motivo acionável que redireciona o agente (ex.: escalação).
  3. PostToolUse intercepta o resultado: normaliza formatos heterogêneos (Unix vs. ISO 8601, códigos numéricos) antes de o modelo raciocinar sobre eles.
  4. Gate de pré-requisito: estado no harness + PreToolUse bloqueando ferramentas downstream até o pré-requisito (customer ID verificado) completar.
  5. Escalação a humano sem acesso ao transcript pede handoff estruturado: customer ID, causa raiz, valores e ação recomendada.

Documentação oficial

Questões de fixação

1. A política da empresa proíbe reembolsos acima de $500 sem aprovação humana — sem exceções. Como garantir isso no agente de suporte?

2. Três MCP tools retornam datas em formatos diferentes (Unix timestamp, ISO 8601 e string local), e o agente ocasionalmente compara datas de forma errada. Qual é a solução recomendada?

3. Ao escalar um caso no meio do atendimento para um humano que não tem acesso ao transcript, o que o agente deve enviar?

4. (escolha duas) Em quais situações o enforcement por prompt é insuficiente e um hook/gate programático é exigido?