400 不是
你提示詞中的 bug。那是政策在盡其職責。你的工作是找出
哪個政策,然後決定要修正呼叫還是放寬規則。
1. 我的 LLM 請求為何被攔下?——從錯誤代碼開始
託管閘道上的每次安全攔截都返回 HTTP 400,附帶 OpenAI 形狀錯誤主體中一個機器可讀的code。那個代碼是
路上的第一個分岔——它告訴你要除錯哪個控制平面,
以及打開哪個動態。
firewall_approval_pending
一個工具呼叫被保留供人工審批——而非拒絕。解析它,
別除錯它。參見 §4。
三個代碼都是 skip-retry:重新執行完全相同的呼叫會路由
到同一個政策並再次封鎖。重試是浪費的延遲——改為修正
輸入或規則。完整代碼表位於
錯誤代碼。
2. guardrail_blocked — 在 Matches 中找到規則
guardrail_blocked 意味著附加到你金鑰(或你
工作區預設值)的內容政策對請求輸入或
模型輸出執行了一次 block 動作。封鎖訊息會指名防護欄和規則,
而該請求不消耗你的配額——輸入封鎖在
計量之前觸發;輸出封鎖退還預先消耗的配額。
追溯它:
打開 Matches 動態
在控制台中,前往防護欄頁面上的 Matches 分頁
(
GET /api/guardrail/match,Member)。每條觸發的規則都會
出現在此——它的 RuleType、Action、Stage,以及一個 Detail 字串,例如
pii: email, phone 或 matched 3 keyword(s)。過濾到封鎖
按
action = block 和你請求的時間過濾。匹配的
列會告訴你規則類型(pii、regex、keyword、max_chars、
llm_judge、grounding、external),以及它是在
input 還是 output 階段觸發。一個具體範例
你發送一條包含客戶 SSN 的支援回覆。你的pii-shield
防護欄有一個 entity_actions 覆寫,在 ssn 上封鎖:
400 guardrail_blocked。Matches 動態顯示
RuleType: pii、Action: block、Stage: input、Detail: pii: ssn。
修正是一個產品決定,而非程式碼更改:將覆寫放寬為 mask
(模型從不看到 SSN,呼叫通過),或保留封鎖
並在上游剝除 SSN。完整的規則類型和 PII 實體參考參見
防護欄。
3. firewall_blocked — 在 Events 中找到裁決
firewall_blocked 意味著一條**防火牆政策
拒絕了一個工具呼叫。在 inbound 表面上它浮現為 400;透過
MCP 閘道它浮現為一個工具錯誤**(firewall deny: <reason>)
以便模型可以反應而非崩潰。錯誤 metadata 攜帶
原因代碼、風險因子和分數。
在 Events 動態中追溯它(GET /api/workspace/firewall/events,
Developer+)——每次評估背後的原始記錄。每個事件攜帶
一個裁決和它所見的表面:
| 裁決 | 它對你的封鎖意味著什麼 |
|---|---|
deny | 一條規則(或 default_verdict)封鎖了呼叫。這就是你的 firewall_blocked。 |
audit | 允許但記錄——包括政策處於影子模式時的 [shadow] 「would deny」。 |
cap_cost | 執行的累計支出越過了每規則的分數上限;解析為拒絕。 |
將 Events 過濾到拒絕
按
verdict=deny 過濾,再按 tool、run_id 或 session_id
過濾以隔離確切的呼叫。事件指名匹配的規則和
表面——inbound、response、mcp 或 egress。讀取匹配規則上的原因
原因字串(例如
destructive shell command、
egress host not allowed)告訴你規則是匹配到了
工具名稱、args_match 子句,還是外向目的地。
裁決詞彙表和
Glob 與 JSONPath 參考解碼
匹配。4. firewall_approval_pending — 它被保留,不是被拒絕
firewall_approval_pending 是唯一一個你不應該當成
封鎖處理的 400。一個 pending_approval 裁決將工具呼叫保留供人工審查;
錯誤主體攜帶一個審批 id。呼叫尚未失敗——它在
等待。
- 審查者解析它——從控制台(Developer+)或透過你自己的
HMAC webhook 回呼(
POST /api/v1/firewall/approvals/:id/callback)。 - 你的代理用錯誤中的 id 對
GET /api/v1/firewall/approvals/:id(閘道權杖)輪詢。 - 一旦核准,帶著單次使用的
X-OrcaRouter-Firewall-Approval標頭重新提交原始呼叫,閘道讓它 通過那一次。
5. 不是安全攔截?先排除金鑰
不是每個400 都是防護欄或防火牆裁決。在你深入
動態之前,先排除金鑰約束——這些在任何政策
執行之前就拒絕,且不攜帶上述安全代碼:
模型在上游呼叫前被拒絕
模型在上游呼叫前被拒絕
金鑰的
model_limits 允許清單不包含請求的
模型。對清單之外模型的請求會被當場拒絕。
將模型加入金鑰,或呼叫一個被允許的模型。在驗證時被 IP 拒絕
在驗證時被 IP 拒絕
金鑰有一個
allow_ips 允許清單,而請求來自
清單之外的地址。加入呼叫者的 IP / CIDR,或從
被允許的網路呼叫。達到支出上限
達到支出上限
金鑰的
credit_limit_usd 上限已耗盡(0 代表
無限)。提高上限或輪換到有餘量的金鑰。/api/v1/firewall/* 路由上的 403
/api/v1/firewall/* 路由上的 403
閘道鉤子(
evaluate、MCP 派發)需要一個帶有
is_firewall_gateway=true 的金鑰。普通中繼金鑰會得到 403。為那些路由
鑄造一個防火牆閘道範圍化的金鑰。6. 兩分鐘分類流程
提示詞或回應文字上的封鎖
代碼是
guardrail_blocked → 打開 Matches,過濾
action=block,讀取 Stage + Detail。修正內容或
規則;在防護欄 Test 分頁中證明它。工具呼叫上的封鎖
代碼是
firewall_blocked → 打開 Events,過濾
verdict=deny,讀取表面 + 原因。修正呼叫或規則;
在防火牆 Test 分頁中證明它。呼叫被保留
代碼是
firewall_approval_pending → 輪詢審批 id 並
帶著審批標頭重新提交。沒有東西要除錯。以上皆非
沒有安全代碼 → 檢查金鑰:
model_limits、allow_ips、
credit_limit_usd,或缺少閘道範圍的 403。7. 相關參考
錯誤代碼
完整代碼表——閘道可能返回的每次封鎖、保留和拒絕。
裁決詞彙表
每個防火牆裁決的含義,以及它何時解析為拒絕。
Glob 與 JSONPath
解碼匹配你呼叫的
tool_name_glob 和 args_match。防護欄與防火牆
哪個平面觸發了——文字篩查還是動作治理。
