Vai al contenuto principale
Quando una regola del firewall restituisce pending_approval, la chiamata a tool viene messa in attesa e il tuo agent aspetta. Per default un revisore libera quell’ hold dalla console. Il webhook di approvazione del firewall cabla lo stesso cancello nel tuo sistema: il gateway fa POST di una notifica firmata al tuo endpoint nel momento in cui una chiamata viene messa in attesa, e il tuo sistema fa POST di una decisione firmata con HMAC indietro per rilasciarla — nessun posto in console, nessun polling di un umano. Questa è la metà async (callback) dell’human-in-the-loop. La chiamata in attesa, il verdetto e il percorso di risoluzione da console sono trattati in Risolvi le approvazioni e nel riferimento del Firewall; questa pagina è solo il cablaggio del webhook.
Il webhook è un preavviso sul percorso rapido, non il sistema di registrazione. Il long-poll del relay sulla chiamata in attesa è il cancello autoritativo — se una notifica viene persa o il tuo ricevitore è giù, l’hold regge comunque e un revisore può liberarlo dalla console. Configurare il webhook aggiunge solo un modo programmatico per risolverlo.

1. Quando usare un webhook di approvazione del firewall

Ricorrivi quando un cancello del firewall human-in-the-loop deve essere risolto da qualcosa di diverso da una persona che clicca un pulsante:

Instrada verso la tua UI di approvazioni

Spingi le chiamate a tool in attesa in Slack, PagerDuty o una coda di revisione interna e risolvile dove il tuo team già lavora.

Policy programmatica

Auto-approva un db.query in attesa contro una replica di lettura, auto-rifiuta uno contro prod — decide il tuo codice, il gateway applica.

2. Configuralo nella console

Entrambe le metà vivono su un’impostazione del workspace. Apri Firewall → Settings e riempi due campi (un’azione Developer+ — la scrittura delle impostazioni è role-gated):
L’endpoint https:// su cui facciamo POST quando una chiamata viene messa in attesa. HTTP è rifiutato, e l’URL viene fatto passare attraverso un preflight SSRF al salvataggio, così una destinazione loopback, su range privato o cloud-metadata viene rifiutata prima di poter essere memorizzata. Lascialo vuoto per disabilitare interamente il percorso async.
Un segreto HMAC write-only (fino a 255 caratteri). Firma la nostra notifica in uscita e autentica il tuo callback in entrata. La console non lo restituisce mai — una volta salvato vedi solo che un segreto è impostato; ruotalo scrivendo un nuovo valore.
L’endpoint di callback è solo HMAC. Finché un segreto condiviso non è impostato, il gateway non consegnerà notifiche e rifiuta ogni callback — il cancello può essere liberato solo dalla console. Imposta il segreto per attivare il percorso async.
Preferisci l’API REST? Gli stessi campi si aggiornano attraverso la rotta delle impostazioni di 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. La notifica che ti inviamo

Quando una chiamata viene messa in attesa, facciamo POST di un envelope JSON firmato al tuo 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
  }
}
L’envelope è un segnale di routing, non il contesto completo — porta l’approval_id che ti serve per risolvere e gli identificatori per correlare, mai gli argomenti del tool. Il dettaglio degli argomenti vive nella coda di Approvals e nel log degli eventi del firewall.
Verifica la firma in uscita prima di fidarti del payload: X-Orca-Signature è sha256= + hex HMAC-SHA256(secret, raw_body) sui byte esatti che hai ricevuto. Confronta a tempo costante. La consegna è at-least-once e ritentata su fallimenti transitori, quindi rendi il tuo handler idempotente su approval_id.

4. Il callback che fai POST indietro

Per rilasciare (o rifiutare) l’hold, fai POST della tua decisione all’endpoint di callback con l’approval_id dalla notifica:
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 o rejected — nessun altro valore è accettato. reason è opzionale e compare nella traccia di audit dell’approvazione risolta.
La firma del callback è legata all’id di approvazione, così una firma catturata non può essere riprodotta contro una chiamata in attesa diversa. Firma la stringa <approval_id> + un newline letterale (\n) + il corpo grezzo della richiesta:
X-Orca-Signature = "sha256=" + HMAC_SHA256(secret, approval_id + "\n" + body)
Questo differisce dalla notifica in uscita, che firma il solo corpo. Un callback la cui firma non verifica ottiene 401 — e un id di approvazione mancante, discordante o inesistente restituisce lo stesso 401, così l’endpoint non conferma mai se un id esiste.
Il callback è vince-la-prima-decisione e idempotente: chiunque risolva per primo — il tuo webhook o un revisore di console — imposta l’esito, e un callback ripetuto per un’approvazione già risolta restituisce 200 così il tuo sistema smette di ritentare.

5. Rilasciare la chiamata in attesa

Risolvere l’approvazione non riproduce la chiamata a tool per te — solleva il cancello così il tuo agent può ri-emetterla. Il runtime dell’agent:
  1. Fa polling sullo stato dell’hold a GET /api/v1/firewall/approvals/:id (una chiave con scope firewall-gateway, non la tua chiave di relay o sessione di console) finché non lascia pending.
  2. Su approved, ri-invia la chiamata a tool originale portando un header monouso X-OrcaRouter-Firewall-Approval — il gateway lascia passare quell’unica chiamata e il token viene speso.
Se la regola sottostante è stata modificata dopo che la chiamata è stata messa in attesa, la coda di Approvals segnala che la regola è da allora cambiata e sopprime la clausola “held because…” ormai stantia, così un revisore di console non agisce su una provenienza che non corrisponde più a ciò che ha messo in attesa la chiamata.

6. Verifica il cablaggio

Un rapido controllo end-to-end prima di farci affidamento:
StepCosa fareAtteso
Metti in attesa una chiamataFai scattare una regola con un verdetto pending_approval400 firewall_approval_pending
NotificaOsserva il tuo endpointArriva un POST firewall.approval.pending firmato
CallbackFai POST di un { "decision": "approved" } firmato200 con lo stato risolto
Guardia di replayFai di nuovo POST del callback200, già risolta (nessuna doppia applicazione)
Se la notifica non arriva mai, conferma che il segreto sia impostato (senza di esso il gateway non consegnerà) e che l’URL abbia passato i controlli HTTPS + SSRF al momento del salvataggio.

7. Dove si inserisce

Risolvi le approvazioni

Il percorso del revisore di console e il ciclo di vita completo di una chiamata in attesa.

Verdetti

Da dove arriva pending_approval e come si compone con altri verdetti.

Chiavi del gateway

Conia la chiave con scope firewall-gateway di cui il flusso di polling + ri-invio ha bisogno.

Agenzia eccessiva

La minaccia che i cancelli human-in-the-loop sono costruiti per contenere.
Per il modello dei verdetti, le superfici di applicazione e il resto del firewall, vedi il riferimento del Firewall.