Saltar para o conteúdo principal
Algumas chamadas de ferramenta são consequentes demais para permitir cegamente e úteis demais para banir totalmente — uma escrita em banco de dados de produção, uma transferência bancária, um *.delete em dados reais. Para essas você quer uma pessoa no loop: retenha a chamada, deixe um humano olhar, depois prossiga apenas num sim. É exatamente isso que o veredito pending_approval faz. Esta página cobre o fluxo de aprovação de agente com human in the loop de ponta a ponta: como uma chamada retida aparece, como um revisor a resolve do console ou de um webhook, e como o agente reenvia a chamada aprovada. Para onde o veredito fica na gramática de regras, veja Regras do Firewall; para o modelo de política em torno dele, veja a Visão geral do Firewall.

1. Como é uma chamada retida

Quando uma regra resolve para pending_approval, o motor enfileira um registro de aprovação e a chamada não chega à ferramenta. O relay retorna HTTP 400 com error.code firewall_approval_pending; o id de aprovação no qual o agente vai consultar é carregado na error.message legível por humanos:
{
  "error": {
    "code": "firewall_approval_pending",
    "message": "tool \"db.write\" held for approval (…) — resolve approval 507f1f77bcf86cd799439011 and retry with header X-OrcaRouter-Firewall-Approval"
  }
}
O error.metadata estruturado (quando presente) carrega o detalhe do motivo do veredito — reason_code, factors, risk_score — não o id de aprovação. Parseie o id da mensagem, ou obtenha-o do helper do SDK abaixo. A retenção é imediata — não há um long-poll inline bloqueando sua requisição. O agente recebe o id de volta, a chamada é estacionada no lado do servidor no estado pending, e a resolução acontece fora de banda.
Uma chamada retida é registrada como um evento de firewall com veredito pending_approval, então é filtrável no log de events bem ao lado dos eventos deny — você sempre pode ver o que foi retido e, via o registro de aprovação, o que foi resolvido.

2. Um exemplo concreto

Crie uma regra que retém qualquer escrita a uma conexão de produção para um humano:
{
  "label": "hold prod db writes",
  "tool_name_glob": "db.write",
  "verdict": "pending_approval",
  "args_match_json": "{\"clauses\":[{\"path\":\"$.connection\",\"op\":\"eq\",\"value\":\"prod\"}]}"
}
Agora o ciclo de vida:
1

O agente chama a ferramenta

O agente emite db.write contra prod. A regra corresponde, o motor retém a chamada, e o relay retorna 400 firewall_approval_pending com um approval_id.
2

Um humano (ou seu sistema) revisa

Um revisor resolve a aprovação — no console ou via um callback de webhook assinado (veja §3).
3

O agente consulta até resolver

O agente consulta o id de aprovação até seu estado não ser mais pending (veja §4).
4

O agente reenvia com o header de aprovação

No approved, o agente reemite exatamente a mesma chamada uma vez, carregando um header X-OrcaRouter-Firewall-Approval de uso único. O motor reivindica a aprovação e deixa aquela única chamada passar.

3. Resolvendo uma aprovação

Há duas maneiras de transformar uma aprovação pending em approved ou rejected. Ambas compartilham uma garantia de primeira-decisão-vence — a primeira resolução a aterrissar é aplicada atomicamente, e qualquer resolução posterior (ou uma duplicata) é um no-op idempotente retornando 200.
A aba Approvals lista as retenções pendentes mais-antigas-primeiro, cada uma com o nome da ferramenta e uma linha “Held because…” nomeando a política e a cláusula de regra que disparou. (Os argumentos crus da chamada não são armazenados no registro de aprovação — apenas o nome da ferramenta, a proveniência e um hash de args — então o revisor decide a partir da ferramenta mais a cláusula correspondida.) Um revisor resolve uma com:
PATCH /api/workspace/firewall/approvals/:id
{ "decision": "approved", "reason": "verified change ticket #4821" }
decision deve ser approved ou rejected. Esta rota é UserAuth (a sessão de console do revisor) e restrita a Developer+ — a identidade do seu revisor é a autorização, então nenhum segredo compartilhado está envolvido. As resoluções são escritas no log de auditoria do workspace.
Para conectar aprovações a um sistema externo (uma aprovação no Slack, um fluxo de ticketing), configure um segredo de webhook de aprovação para o workspace, depois faça POST da decisão de volta:
POST /api/v1/firewall/approvals/:id/callback
{ "decision": "approved", "reason": "auto-approved by change-control bot" }
O callback é autenticado por HMAC-SHA256: defina o header X-Orca-Signature: sha256=<hex> para o HMAC de <approval_id>\n<raw_body> chaveado com o segredo de webhook de aprovação do seu workspace. O id é parte do material assinado, então uma assinatura capturada não pode ser reproduzida contra uma aprovação diferente. Sem um segredo configurado, a resolução conduzida por callback é rejeitada — resolva via o PATCH do console em vez disso.
Configurar um caminho de rejeição de webhook de aprovação é o padrão seguro para runs não supervisionadas: se nenhum humano resolver uma retenção, a chamada simplesmente permanece estacionada e o agente continua consultando. Uma chamada retida nunca se torna silenciosamente um allow.

4. Consulte, depois reenvie

O lado do agente é um loop de consulta seguido de um reenvio. Consulte o estado de aprovação com um token com escopo de firewall-gateway:
GET /api/v1/firewall/approvals/:id
Esta rota exige um token com o escopo de firewall-gateway (a mesma chave de gateway dedicada usada para /evaluate e o gateway MCP); uma chave de relay normal recebe 403. Ela retorna o documento de aprovação — espere até state ser approved ou rejected em vez de pending. Um id de outro workspace ou desconhecido retorna 404, nunca revelando que ele existe para outro tenant. Reenvie uma vez que o estado for approved: reemita a mesma chamada de ferramenta, carregando o id de aprovação num header de uso único:
X-OrcaRouter-Firewall-Approval: 507f1f77bcf86cd799439011
O motor reivindica atomicamente a aprovação — uso único. O primeiro reenvio que a carrega é permitido aquela única vez; uma reprodução do mesmo header encontra a aprovação já consumida e é retida de novo, não permitida. Uma aprovação rejected nunca é reivindicável, então o agente deve tratar a rejeição como um deny terminal e escolher outro caminho.
O helper de HITL do SDK MCP do OrcaRouter roda esse loop de consultar-depois-reenviar para você: quando evaluate retorna pending_approval, ele consulta GET /api/v1/firewall/approvals/:id e reenvia com o header de aprovação na aprovação — você só cria a regra e provê o revisor.

5. Estados e papéis em resumo

EstadoSignificadoAção do agente
pendingRetido, aguardando uma decisãoContinue consultando
approvedRevisor disse simReenvie uma vez com o header
rejectedRevisor disse nãoTrate como um deny
AçãoRotaAuth · papel
Listar a filaGET /api/workspace/firewall/approvalsUserAuth · Developer+
ResolverPATCH /api/workspace/firewall/approvals/:idUserAuth · Developer+
Callback de webhookPOST /api/v1/firewall/approvals/:id/callbackAssinado por HMAC
Consultar estadoGET /api/v1/firewall/approvals/:idToken de gateway

6. Onde as aprovações se encaixam

Um veredito pending_approval é um dos vereditos de firewall — ele se compõe com tudo o mais numa política. Duas interações que vale conhecer:
  • A quarentena de skill escala para uma retenção. Se uma chamada de ferramenta retida é de propriedade de uma skill em quarentena, qualquer coisa aquém de um deny é escalada para pending_approval automaticamente — quarentena e aprovações são o mesmo portão de revisão de duas direções.
  • O shadow mode o achata. No shadow mode um veredito pending_approval é rebaixado para audit e registrado como [shadow] would …, então você pode medir com que frequência uma retenção dispararia antes de ela começar a controlar o tráfego real.
Este é o controle certo para chamadas de ferramenta perigosas e agência excessiva — os casos onde um veredito de “perguntar a um humano” supera tanto allow quanto deny.

Para onde ir a seguir

Vereditos

Todos os seis vereditos de firewall e o veredito padrão.

Chaves de gateway

Cunhe o token de firewall-gateway usado para consultar aprovações.

Shadow mode

Meça uma retenção antes de ela controlar o tráfego real.

Referência de regras

Crie a regra que produz um veredito pending_approval.