Chuyển đến nội dung chính
Một số cuộc gọi tool quá hệ trọng để allow mù quáng và quá hữu ích để cấm dứt khoát — một lần ghi cơ sở dữ liệu production, một chuyển khoản, một *.delete trên dữ liệu thật. Với những cái đó bạn muốn một người trong vòng lặp: giữ cuộc gọi lại, để một con người xem, rồi chỉ tiến hành khi có một cái gật đầu. Đó chính xác là điều mà verdict pending_approval làm. Trang này đề cập luồng phê duyệt agent có con người trong vòng lặp từ đầu tới cuối: cách một cuộc gọi được giữ hiện ra, cách một người duyệt phân giải nó từ console hoặc một webhook, và cách agent gửi lại cuộc gọi đã duyệt. Để biết nơi verdict nằm trong ngữ pháp quy tắc, xem Quy tắc Firewall; để biết mô hình chính sách quanh nó, xem tổng quan Firewall.

1. Một cuộc gọi được giữ trông như thế nào

Khi một quy tắc phân giải về pending_approval, engine xếp hàng một bản ghi phê duyệt và cuộc gọi không đến được tool. Relay trả về HTTP 400 với error.code firewall_approval_pending; approval id mà agent sẽ poll được mang trong error.message có-thể-đọc-bởi-con-người:
{
  "error": {
    "code": "firewall_approval_pending",
    "message": "tool \"db.write\" held for approval (…) — resolve approval 507f1f77bcf86cd799439011 and retry with header X-OrcaRouter-Firewall-Approval"
  }
}
error.metadata có cấu trúc (khi có) mang chi tiết lý do của verdict — reason_code, factors, risk_score — không phải approval id. Parse id ra khỏi message, hoặc lấy nó từ helper SDK bên dưới. Lần giữ là tức thì — không có long-poll inline nào block request của bạn. Agent nhận id trở lại, cuộc gọi được đỗ ở phía server trong trạng thái pending, và việc phân giải xảy ra ngoài luồng.
Một cuộc gọi được giữ được ghi lại như một event firewall với verdict pending_approval, nên nó có thể lọc trong events log ngay bên cạnh các event deny — bạn luôn có thể thấy cái gì được giữ và, qua bản ghi phê duyệt, cái gì được phân giải.

2. Một ví dụ cụ thể

Soạn một quy tắc giữ bất kỳ lần ghi nào tới một kết nối production cho một con người:
{
  "label": "hold prod db writes",
  "tool_name_glob": "db.write",
  "verdict": "pending_approval",
  "args_match_json": "{\"clauses\":[{\"path\":\"$.connection\",\"op\":\"eq\",\"value\":\"prod\"}]}"
}
Giờ vòng đời:
1

Agent gọi tool

Agent phát ra db.write trên prod. Quy tắc khớp, engine giữ cuộc gọi, và relay trả về 400 firewall_approval_pending với một approval_id.
2

Một con người (hoặc hệ thống của bạn) xem xét

Một người duyệt phân giải phê duyệt — trong console hoặc qua một webhook callback có chữ ký (xem §3).
3

Agent poll cho đến khi được phân giải

Agent poll approval id cho đến khi trạng thái của nó không còn là pending (xem §4).
4

Agent gửi lại với approval header

Khi approved, agent phát lại đúng cùng cuộc gọi một lần, mang một header X-OrcaRouter-Firewall-Approval dùng-một-lần. Engine nhận phê duyệt và cho cuộc gọi đó đi qua.

3. Phân giải một phê duyệt

Có hai cách để biến một phê duyệt pending thành approved hoặc rejected. Cả hai chia sẻ một bảo đảm quyết-định-đầu-tiên-thắng — lần phân giải đầu tiên đáp xuống được áp dụng một cách atomic, và bất kỳ lần phân giải sau (hoặc một bản trùng) là một no-op idempotent trả về 200.
Tab Approvals liệt kê các lần giữ pending cũ-nhất-trước, mỗi cái với tên tool và một dòng “Held because…” nêu tên chính sách và mệnh đề quy tắc đã kích hoạt. (Đối số cuộc gọi thô không được lưu trên bản ghi phê duyệt — chỉ tên tool, xuất xứ, và một args hash — nên người duyệt quyết định từ tool cộng mệnh đề đã khớp.) Một người duyệt phân giải một cái với:
PATCH /api/workspace/firewall/approvals/:id
{ "decision": "approved", "reason": "verified change ticket #4821" }
decision phải là approved hoặc rejected. Route này là UserAuth (session console của người duyệt) và giới hạn ở Developer+ — danh tính của người duyệt chính là sự ủy quyền, nên không có shared secret nào liên quan. Các lần phân giải được ghi vào audit log của workspace.
Để nối phê duyệt vào một hệ thống bên ngoài (một phê duyệt Slack, một quy trình ticketing), cấu hình một approval webhook secret cho workspace, rồi POST quyết định trở lại:
POST /api/v1/firewall/approvals/:id/callback
{ "decision": "approved", "reason": "auto-approved by change-control bot" }
Callback được xác thực bằng HMAC-SHA256: đặt header X-Orca-Signature: sha256=<hex> thành HMAC của <approval_id>\n<raw_body> khóa bằng approval webhook secret của workspace bạn. Id là một phần của vật liệu được ký, nên một chữ ký bị bắt không thể được replay lên một phê duyệt khác. Không có một secret được cấu hình, việc phân giải qua-callback bị từ chối — phân giải qua PATCH của console thay vào.
Cấu hình một đường từ chối của approval-webhook là mặc định an toàn cho các lần chạy không-giám-sát: nếu không con người nào phân giải một lần giữ, cuộc gọi đơn giản ở lại đỗ và agent tiếp tục poll. Một cuộc gọi được giữ không bao giờ âm thầm trở thành một allow.

4. Poll, rồi gửi lại

Phía agent là một vòng lặp poll theo sau bởi một lần gửi lại. Poll trạng thái phê duyệt với một token phạm-vi-firewall-gateway:
GET /api/v1/firewall/approvals/:id
Route này yêu cầu một token với firewall-gateway scope (cùng gateway key chuyên biệt được dùng cho /evaluate và MCP gateway); một relay key thường nhận 403. Nó trả về doc phê duyệt — đợi cho đến khi stateapproved hoặc rejected thay vì pending. Một id cross-workspace hoặc chưa biết trả về 404, không bao giờ tiết lộ rằng nó tồn tại cho một tenant khác. Gửi lại một khi trạng thái là approved: phát lại cùng cuộc gọi tool, mang approval id trong một header dùng-một-lần:
X-OrcaRouter-Firewall-Approval: 507f1f77bcf86cd799439011
Engine nhận một cách atomic phê duyệt — dùng-một-lần. Lần gửi lại đầu tiên mang nó được cho qua đúng một lần đó; một replay của cùng header tìm thấy phê duyệt đã được tiêu thụ và bị giữ lại lần nữa, không được cho qua. Một phê duyệt rejected không bao giờ nhận được, nên agent nên xử lý từ chối như một deny cuối cùng và chọn một đường khác.
Helper HITL của OrcaRouter MCP SDK chạy vòng lặp poll-rồi-gửi-lại này cho bạn: khi evaluate trả về pending_approval, nó poll GET /api/v1/firewall/approvals/:id và gửi lại với approval header khi được phê duyệt — bạn chỉ soạn quy tắc và bố trí người duyệt.

5. Các trạng thái và vai trò trong nháy mắt

Trạng tháiÝ nghĩaHành động agent
pendingĐược giữ, chờ một quyết địnhTiếp tục poll
approvedNgười duyệt nói cóGửi lại một lần với header
rejectedNgười duyệt nói khôngXử lý như một deny
Hành độngRouteAuth · vai trò
Liệt kê hàng đợiGET /api/workspace/firewall/approvalsUserAuth · Developer+
Phân giảiPATCH /api/workspace/firewall/approvals/:idUserAuth · Developer+
Webhook callbackPOST /api/v1/firewall/approvals/:id/callbackKý HMAC
Poll trạng tháiGET /api/v1/firewall/approvals/:idGateway token

6. Phê duyệt khớp vào đâu

Một verdict pending_approval là một trong các verdict firewall — nó kết hợp với mọi thứ khác trong một chính sách. Hai tương tác đáng biết:
  • Cách ly skill leo thang thành một lần giữ. Nếu một cuộc gọi tool được giữ thuộc về một skill bị cách ly, bất cứ thứ gì chưa tới mức deny được leo thang thành pending_approval tự động — cách ly và phê duyệt là cùng một cổng xem xét từ hai hướng.
  • Shadow mode làm phẳng nó. Trong shadow mode một verdict pending_approval bị hạ cấp thành audit và ghi log như [shadow] would …, nên bạn có thể đo một lần giữ sẽ kích hoạt thường xuyên ra sao trước khi nó bắt đầu quản trị traffic thật.
Đây là kiểm soát đúng cho cuộc gọi tool nguy hiểmquyền tự quyết quá mức — các trường hợp mà một verdict “hỏi một con người” thắng cả allow lẫn deny.

Đi đâu tiếp theo

Verdict

Cả sáu verdict firewall và verdict mặc định.

Gateway key

Tạo token firewall-gateway dùng để poll phê duyệt.

Shadow mode

Đo một lần giữ trước khi nó quản trị traffic thật.

Tham chiếu quy tắc

Soạn quy tắc tạo ra một verdict pending_approval.