Saltar para o conteúdo principal
Quando uma regra de firewall retorna pending_approval, a chamada de ferramenta é retida e seu agente espera. Por padrão um revisor limpa essa retenção do console. O webhook de aprovação do firewall conecta o mesmo portão ao seu sistema: o gateway faz POST de uma notificação assinada ao seu endpoint no momento em que uma chamada é retida, e seu sistema faz POST de uma decisão assinada por HMAC de volta para liberá-la — sem assento de console, sem consultar um humano. Esta é a metade assíncrona (callback) do human-in-the-loop. A chamada retida, o veredito e o caminho de resolução do console são cobertos em Resolver aprovações e na referência do Firewall; esta página é apenas a fiação do webhook.
O webhook é um aviso de caminho rápido, não o sistema de registro. O long-poll do relay na chamada retida é o portão autoritativo — se uma notificação é perdida ou seu receptor está fora, a retenção ainda permanece e um revisor pode limpá-la do console. Configurar o webhook apenas adiciona uma forma programática de resolvê-la.

1. Quando usar um webhook de aprovação do firewall

Recorra a ele quando um portão de firewall human-in-the-loop tem de ser resolvido por algo diferente de uma pessoa clicando um botão:

Roteie para sua própria UI de aprovações

Empurre chamadas de ferramenta retidas para o Slack, PagerDuty ou uma fila de revisão interna e resolva-as onde sua equipe já trabalha.

Política programática

Auto-aprove um db.query retido contra uma réplica de leitura, auto-rejeite um contra prod — seu código decide, o gateway aplica.

2. Configure-o no console

Ambas as metades vivem em uma configuração de workspace. Abra Firewall → Settings e preencha dois campos (uma ação Developer+ — a escrita de configurações é restrita por papel):
O endpoint https:// para o qual fazemos POST quando uma chamada é retida. HTTP é recusado, e a URL passa por um preflight de SSRF ao salvar, então um destino de loopback, faixa privada ou cloud-metadata é rejeitado antes de poder ser armazenado. Deixe-o vazio para desabilitar o caminho assíncrono inteiramente.
Um segredo HMAC write-only (até 255 caracteres). Ele assina nossa notificação de saída e autentica seu callback de entrada. O console nunca o ecoa de volta — uma vez salvo você vê apenas que um segredo está definido; rotacione escrevendo um novo valor.
O endpoint de callback é apenas-HMAC. Até um segredo compartilhado ser definido, o gateway não entregará notificações e rejeita cada callback — o portão só pode ser limpo do console. Defina o segredo para ligar o caminho assíncrono.
Prefere a API REST? Os mesmos campos atualizam através da rota de configurações do console (UserAuth, Developer+):
curl -X PUT https://api.orcarouter.ai/api/workspace/firewall/settings \
  -H "Authorization: Bearer $ORCA_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "approval_webhook_url": "https://hooks.example.com/orca/firewall",
        "approval_webhook_secret": "whsec_your_shared_secret"
      }'

3. A notificação que enviamos a você

Quando uma chamada é retida, fazemos POST de um envelope JSON assinado à sua URL:
POST /orca/firewall HTTP/1.1
Content-Type: application/json
X-Orca-Event: firewall.approval.pending
X-Orca-Signature: sha256=<hex>
{
  "event": "firewall.approval.pending",
  "workspace_id": 42,
  "occurred_at": "2026-06-09T17:04:11.482Z",
  "data": {
    "approval_id": "665f1b...",
    "tool_name": "db.query",
    "request_id": "req_9f2c...",
    "conversation_id": "conv_77a1...",
    "policy_id": 7,
    "rule_id": 31
  }
}
O envelope é um sinal de roteamento, não o contexto completo — ele carrega o approval_id de que você precisa para resolver e identificadores para correlacionar, nunca os argumentos da ferramenta. O detalhe do argumento vive na fila de Approvals e no log de events do firewall.
Verifique a assinatura de saída antes de confiar no payload: X-Orca-Signature é sha256= + hex HMAC-SHA256(secret, raw_body) sobre os bytes exatos que você recebeu. Compare em tempo constante. A entrega é at-least-once e refeita em falhas transitórias, então torne seu handler idempotente em approval_id.

4. O callback que você faz POST de volta

Para liberar (ou rejeitar) a retenção, faça POST de sua decisão ao endpoint de callback com o approval_id da notificação:
POST /api/v1/firewall/approvals/665f1b.../callback
X-Orca-Signature: sha256=<hex>
Content-Type: application/json

{ "decision": "approved", "reason": "read-replica query, auto-approved" }
decision é approved ou rejected — nenhum outro valor é aceito. reason é opcional e aparece na trilha de auditoria da aprovação resolvida.
A assinatura de callback está vinculada ao id de aprovação, então uma assinatura capturada não pode ser reproduzida contra uma chamada retida diferente. Assine a string <approval_id> + uma quebra de linha literal (\n) + o corpo cru da requisição:
X-Orca-Signature = "sha256=" + HMAC_SHA256(secret, approval_id + "\n" + body)
Isso difere da notificação de saída, que assina o corpo sozinho. Um callback cuja assinatura não verifica recebe 401 — e um id de aprovação ausente, incompatível ou inexistente retorna o mesmo 401, então o endpoint nunca confirma se um id existe.
O callback é first-decision-wins e idempotente: quem resolve primeiro — seu webhook ou um revisor de console — define o resultado, e um callback repetido para uma aprovação já resolvida retorna 200 para que seu sistema pare de fazer retry.

5. Liberando a chamada retida

Resolver a aprovação não reproduz a chamada de ferramenta para você — ela levanta o portão para que seu agente possa reemiti-la. O runtime do agente:
  1. Consulta o estado da retenção em GET /api/v1/firewall/approvals/:id (uma chave com escopo de firewall-gateway, não sua chave de relay ou sessão de console) até ela sair de pending.
  2. No approved, reenvia a chamada de ferramenta original carregando um header X-OrcaRouter-Firewall-Approval de uso único — o gateway deixa aquela única chamada passar e o token é gasto.
Se a regra subjacente foi editada depois de a chamada ser retida, a fila de Approvals sinaliza que a regra mudou desde então e suprime a cláusula “held because…” agora obsoleta, para que um revisor de console não aja sobre proveniência que não corresponde mais ao que reteve a chamada.

6. Verifique a fiação

Uma verificação rápida de ponta a ponta antes de depender dela:
PassoO que fazerEsperado
Reter uma chamadaAcione uma regra com um veredito pending_approval400 firewall_approval_pending
NotificaçãoObserve seu endpointPOST firewall.approval.pending assinado chega
CallbackFaça POST de um { "decision": "approved" } assinado200 com o estado resolvido
Guarda de replayFaça POST do callback de novo200, já resolvido (sem dupla aplicação)
Se a notificação nunca chega, confirme que o segredo está definido (sem ele o gateway não entrega) e que a URL passou nas verificações de HTTPS + SSRF no momento de salvar.

7. Onde isso se encaixa

Resolver aprovações

O caminho do revisor de console e o ciclo de vida completo da chamada retida.

Vereditos

De onde pending_approval vem e como ele se compõe com outros vereditos.

Chaves de gateway

Cunhe a chave com escopo de firewall-gateway de que o fluxo de consulta + reenvio precisa.

Agência excessiva

A ameaça que os portões human-in-the-loop são construídos para conter.
Para o modelo de veredito, as superfícies de enforcement e o resto do firewall, veja a referência do Firewall.