Zum Hauptinhalt springen
Wenn eine Firewall-Regel das pending_approval-Verdikt zurückgibt, hält das Gateway den Tool-Call zurück und benachrichtigt Ihr eigenes Approval-System out-of-band. Diese Benachrichtigung ist ein signierter HTTP-POST — das Firewall-Webhook-Payload — und diese Seite dokumentiert seine exakte Form, sodass Sie die Signatur verifizieren, das Event routen und Ihre Entscheidung zurückposten können. Dies ist das asynchrone Geschwister des In-Konsolen-Approval-Flows, der auf der Firewall-Seite beschrieben ist. Der Konsolen-Pfad (ein Prüfer klickt approve/reject) benötigt überhaupt keinen Webhook. Der Webhook ist für den Fall, dass Sie eine Maschine — Ihren eigenen Ticketing-Bot, eine Slack-Action oder eine Agenten-Laufzeit — den Hold auflösen lassen möchten. Beide Pfade sind first-writer-wins, sodass Sie sie nebeneinander betreiben können.
Der Webhook ist ein Best-Effort-Routing-Signal, nicht der autoritative HITL-Kanal. Der eigene Long-Poll des Agenten auf GET /api/v1/firewall/approvals/:id ist das Backstop — wenn eine Benachrichtigung verloren geht oder Ihr Endpunkt kurz ausfällt, taucht der zurückgehaltene Aufruf trotzdem in der Konsole auf und wird normal aufgelöst. Der Webhook lässt nur eine Maschine schneller reagieren, als ein Mensch es täte.

1. Das Firewall-Webhook-Payload auf einen Blick

OrcaRouter POSTet ein JSON-Envelope an die URL, die Sie konfigurieren, signiert mit einem geteilten Secret. Hier ist eine vollständige Zustellung — Header und Body:
POST /your-approval-endpoint HTTP/1.1
Content-Type: application/json
X-Orca-Event: firewall.approval.pending
X-Orca-Signature: sha256=9f86d0818988...c2c9a3e1b4d7

{
  "event": "firewall.approval.pending",
  "workspace_id": 42,
  "occurred_at": "2026-06-09T12:00:00.123456789Z",
  "data": {
    "approval_id": "665f1a2b3c4d5e6f7a8b9c0d",
    "tool_name": "db.export",
    "request_id": "req_01J9X...",
    "conversation_id": "conv_8f2a...",
    "policy_id": 7,
    "rule_id": 31
  }
}
Das Envelope hat dieselbe Form, die OrcaRouter für jedes signierte Event verwendet, sodass ein Receiver viele Event-Typen über X-Orca-Event routen kann, ohne den Body zu parsen.

2. Envelope-Felder

Immer firewall.approval.pending für einen Approval-Hold. Gespiegelt im X-Orca-Event-Header, sodass Sie routen können, bevor Sie den Body parsen.
Die Integer-ID des Workspaces, dessen Policy den Aufruf zurückgehalten hat. Nützlich, wenn ein Endpunkt Webhooks von mehreren Workspaces empfängt.
RFC-3339-/UTC-Timestamp (Nanosekunden-Präzision) dafür, wann das Gateway die Freigabe eingereiht hat. Parsbar von jedem Standard-Event-Tooling.
Der Block, den Ihr Callback braucht, um das Gate aufzulösen. Felder in §3.

3. Das data-Payload

Der data-Block trägt alles, was zum Routen und Auflösen des Holds nötig ist — bewusst keine Tool-Argumente. Der Webhook ist ein Routing-Signal; der vollständige Aufruf-Kontext (Tool, Args, die Regel, die gefeuert hat) lebt im Konsolen-Approvals-Tab und im Audit-Log, wo er zugriffskontrolliert ist.
FeldTypBedeutung
approval_idstringDie ID, gegen die Sie Ihre Entscheidung posten.
tool_namestringDas zurückgehaltene Tool, z. B. db.export.
request_idstringDer Relay-Request, der den Hold ausgelöst hat.
conversation_idstringDie Agenten-Konversations- / Session-ID.
policy_idintDie Firewall-Policy, die gematcht hat.
rule_idintDie Regel, die pending_approval zurückgegeben hat.
Brauchen Sie die Argumente oder die gematchte Klausel, um die Entscheidung zu treffen? Lesen Sie sie aus dem Konsolen-Approvals-Tab (Developer+), oder lassen Sie Ihren Agenten GET /api/v1/firewall/approvals/:id mit seinem Gateway-Token pollen. Der Webhook trägt Args absichtlich nie über die Leitung.

4. Die Signatur verifizieren

Jede Zustellung ist signiert, sodass Sie Fälschungen ablehnen können. Der Signatur-Header ist:
X-Orca-Signature: sha256=<hex HMAC-SHA256(secret, raw_body)>
wobei secret das Approval-Webhook-Secret ist, das Sie auf dem Workspace setzen, und raw_body die exakten Bytes des Request-Bodys sind. Berechnen Sie den HMAC über die rohen Bytes — das geparste JSON neu zu serialisieren ändert Whitespace und bricht den Vergleich. Verifizieren Sie in konstanter Zeit:
import hmac, hashlib

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(
        secret.encode(), raw_body, hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(expected, header)
Die ausgehende Webhook-Signatur deckt nur den Body ab. Der eingehende Callback, den Sie zurückposten (§6), signiert approval_id + einen Zeilenumbruch + den Body — eine andere Konstruktion, absichtlich, sodass eine erfasste Signatur nicht über Freigaben hinweg wiederabgespielt werden kann. Verwenden Sie nicht eine Signaturroutine für beide Richtungen.

5. Den Webhook konfigurieren

Die Ziel-URL und das geteilte Secret sind Workspace-Einstellungen — setzen Sie sie einmal in der Konsole (oder über die Settings-API; Developer+). Es gibt keine Operator-Beteiligung und nichts zu deployen.
1

URL und Secret setzen

Setzen Sie in den Firewall-Einstellungen Ihren HTTPS-Endpunkt als Approval-Webhook-URL und ein starkes geteiltes Secret. Die URL muss https:// sein — Klartext-Ziele werden abgelehnt — und das Secret ist write-only (es wird beim Lesen nie zurückgegeben; die Settings-Antwort meldet nur, ob eines gesetzt ist).
2

Eine pending_approval-Regel verfassen

Fügen Sie eine Firewall-Regel hinzu, deren Verdikt pending_approval ist (oder verwenden Sie das HITL-Preset). Siehe Firewall-Regeln.
3

Empfangen und verifizieren

Ihr Endpunkt empfängt den signierten POST beim nächsten zurückgehaltenen Aufruf. Verifizieren Sie die Signatur (§4) und lösen Sie dann entweder über den Callback auf oder bringen Sie es einem Menschen zur Kenntnis.
Ein zurückgehaltener Aufruf funktioniert auch mit keinem konfigurierten Webhook — er taucht einfach in der Konsole auf, damit ein Mensch ihn auflöst. Und wenn Sie eine URL, aber kein Secret setzen, überspringt das Gateway den Dispatch vollständig, weil der Callback-Endpunkt nur signierte Requests akzeptiert: Eine Benachrichtigung, die Sie nicht zurück authentifizieren könnten, wäre nutzlos.

6. Der Callback: den Hold auflösen

Um per Maschine zu genehmigen oder abzulehnen, POSTen Sie zurück an:
POST /api/v1/firewall/approvals/:id/callback
mit derselben :id, die Sie als approval_id erhalten haben, signiert mit demselben geteilten Secret. Der Body ist eine Entscheidung:
BODY='{"decision":"approved","reason":"ticket OPS-4821 approved by on-call"}'
SIG="sha256=$(printf '%s\n%s' "$APPROVAL_ID" "$BODY" \
  | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')"

curl https://api.orcarouter.ai/api/v1/firewall/approvals/$APPROVAL_ID/callback \
  -H "Content-Type: application/json" \
  -H "X-Orca-Signature: $SIG" \
  -d "$BODY"
Body-FeldErforderlichWerte
decisionjaapproved oder rejected
reasonneinFreitext-Notiz, im Audit-Log aufgezeichnet.
Eine approved-Entscheidung lässt den nächsten Versuch des Agenten einmal durch — der Agent reicht den ursprünglichen Aufruf mit einem einmal nutzbaren X-OrcaRouter-Firewall-Approval-Header erneut ein. Eine rejected-Entscheidung hält den Aufruf blockiert.
Die Auflösung ist idempotent und first-writer-wins. Wenn ein Mensch den Hold bereits aus der Konsole aufgelöst hat — oder ein doppelter Callback eintrifft — gibt der Endpunkt 200 mit already_resolved: true zurück und die ursprüngliche Entscheidung bleibt bestehen. Retry-sicher.

7. Approval-Zustände

Ein zurückgehaltener Aufruf durchläuft diese Zustände; Ihr Callback treibt den Übergang aus pending heraus:
ZustandBedeutung
pendingWartet auf eine Entscheidung (der Zustand zur Webhook-Zeit).
approvedAufgelöst — der gegatete Aufruf darf einmal fortfahren.
rejectedAufgelöst — der gegatete Aufruf bleibt blockiert.
expiredDer Hold ist ohne Entscheidung gealtert.

8. Verwandte Referenzen

Firewall — HITL-Flow

Wie pending_approval einen Aufruf zurückhält und der Agent mit dem einmal nutzbaren Approval-Header erneut einreicht.

Fehlercodes

firewall_approval_pending und die anderen Firewall-HTTP-Antworten.

Verdikt-Glossar

Jedes Firewall-Verdikt, einschließlich pending_approval.

Firewall-API

Die vollständige Konsolen- + Gateway-Routenreferenz.
Wie Holds in das breitere Control-Modell passen, siehe Enforcement-Modes und Gefährliche Tool-Calls.