Saltar al contenido principal
Cuando una regla de firewall devuelve pending_approval, la llamada a herramienta se retiene y tu agente espera. Por defecto un revisor limpia esa retención desde la consola. El webhook de aprobación del firewall conecta la misma compuerta a tu sistema: el gateway hace POST de una notificación firmada a tu endpoint en el momento en que una llamada se retiene, y tu sistema hace POST de una decisión firmada con HMAC de vuelta para liberarla — sin asiento de consola, sin hacer polling a un humano. Esta es la mitad asíncrona (de callback) del humano en el ciclo. La llamada retenida, el veredicto y la ruta de resolución de consola se cubren en Resolver aprobaciones y la referencia del Firewall; esta página es solo el cableado del webhook.
El webhook es un aviso de ruta rápida, no el sistema de registro. El long-poll del relay sobre la llamada retenida es la compuerta autoritativa — si una notificación se pierde o tu receptor está caído, la retención sigue en pie y un revisor puede limpiarla desde la consola. Configurar el webhook solo añade una forma programática de resolverla.

1. Cuándo usar un webhook de aprobación del firewall

Recurre a él cuando una compuerta de humano en el ciclo del firewall tiene que ser resuelta por algo distinto a una persona haciendo clic en un botón:

Enruta a tu propia UI de aprobaciones

Empuja las llamadas a herramienta retenidas a Slack, PagerDuty o una cola de revisión interna y resuélvelas donde tu equipo ya trabaja.

Política programática

Auto-aprueba un db.query retenido contra una réplica de lectura, auto-rechaza uno contra prod — tu código decide, el gateway aplica.

2. Configúralo en la consola

Ambas mitades viven en un ajuste del espacio de trabajo. Abre Firewall → Settings y rellena dos campos (una acción Developer+ — la escritura de configuración está gobernada por rol):
El endpoint https:// al que hacemos POST cuando una llamada se retiene. HTTP se rechaza, y la URL se pasa por un preflight SSRF al guardar, así que un destino loopback, de rango privado o de metadatos de nube se rechaza antes de que pueda almacenarse. Déjala vacía para deshabilitar la ruta asíncrona por completo.
Un secreto HMAC de solo escritura (hasta 255 caracteres). Firma nuestra notificación de salida y autentica tu callback de entrada. La consola nunca lo refleja de vuelta — una vez guardado solo ves que un secreto está establecido; rota escribiendo un valor nuevo.
El endpoint de callback es solo HMAC. Hasta que se establece un secreto compartido, el gateway no entregará notificaciones y rechaza cada callback — la compuerta solo se puede limpiar desde la consola. Establece el secreto para activar la ruta asíncrona.
¿Prefieres la API REST? Los mismos campos se actualizan a través de la ruta de configuración de consola (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. La notificación que te enviamos

Cuando una llamada se retiene, hacemos POST de un sobre JSON firmado a tu 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
  }
}
El sobre es una señal de enrutamiento, no el contexto completo — lleva el approval_id que necesitas para resolver e identificadores para correlacionar, nunca los argumentos de la herramienta. El detalle de argumentos vive en la cola de Approvals y el registro de eventos del firewall.
Verifica la firma de salida antes de confiar en el payload: X-Orca-Signature es sha256= + hex HMAC-SHA256(secret, raw_body) sobre los bytes exactos que recibiste. Compara en tiempo constante. La entrega es al-menos-una-vez y se reintenta en fallos transitorios, así que haz tu manejador idempotente sobre approval_id.

4. El callback que haces POST de vuelta

Para liberar (o rechazar) la retención, haz POST de tu decisión al endpoint de callback con el approval_id de la notificación:
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 es approved o rejected — no se acepta ningún otro valor. reason es opcional y aparece en el rastro de auditoría de la aprobación resuelta.
La firma del callback está vinculada al id de aprobación, así que una firma capturada no se puede reproducir contra una llamada retenida diferente. Firma el string <approval_id> + un salto de línea literal (\n) + el cuerpo de solicitud en bruto:
X-Orca-Signature = "sha256=" + HMAC_SHA256(secret, approval_id + "\n" + body)
Esto difiere de la notificación de salida, que firma el cuerpo solo. Un callback cuya firma no verifica obtiene 401 — y un id de aprobación ausente, no coincidente o inexistente devuelve el mismo 401, así que el endpoint nunca confirma si un id existe.
El callback es gana-la-primera-decisión e idempotente: quien resuelve primero — tu webhook o un revisor de consola — establece el resultado, y un callback repetido para una aprobación ya resuelta devuelve 200 para que tu sistema deje de reintentar.

5. Liberar la llamada retenida

Resolver la aprobación no reproduce la llamada a herramienta por ti — levanta la compuerta para que tu agente pueda reemitirla. El runtime del agente:
  1. Hace polling del estado de la retención en GET /api/v1/firewall/approvals/:id (una clave con alcance de gateway de firewall, no tu clave de relay o sesión de consola) hasta que sale de pending.
  2. En approved, reenvía la llamada a herramienta original llevando una cabecera X-OrcaRouter-Firewall-Approval de un solo uso — el gateway deja pasar esa única llamada y el token se gasta.
Si la regla subyacente fue editada después de que la llamada se retuvo, la cola de Approvals marca que la regla ha cambiado desde entonces y suprime la cláusula “held because…” ahora obsoleta, para que un revisor de consola no actúe sobre procedencia que ya no coincide con lo que retuvo la llamada.

6. Verifica el cableado

Una verificación de extremo a extremo rápida antes de depender de ello:
PasoQué hacerEsperado
Retener una llamadaDispara una regla con un veredicto pending_approval400 firewall_approval_pending
NotificaciónObserva tu endpointLlega un POST firmado firewall.approval.pending
CallbackHaz POST de un { "decision": "approved" } firmado200 con el estado resuelto
Guardia de reproducciónHaz POST del callback de nuevo200, ya resuelta (sin doble aplicación)
Si la notificación nunca llega, confirma que el secreto está establecido (sin él el gateway no entregará) y que la URL pasó las verificaciones de HTTPS + SSRF en tiempo de guardado.

7. Dónde encaja esto

Resolver aprobaciones

La ruta del revisor de consola y el ciclo de vida completo de la llamada retenida.

Veredictos

De dónde viene pending_approval y cómo se compone con otros veredictos.

Claves de gateway

Acuña la clave con alcance de gateway de firewall que el flujo de polling + reenvío necesita.

Agencia excesiva

La amenaza que las compuertas de humano en el ciclo están construidas para contener.
Para el modelo de veredictos, las superficies de aplicación y el resto del firewall, ver la referencia del Firewall.