跳转到主要内容
一个请求返回了 HTTP 400,你的智能体停滞了。在你改动任何代码之前, 网关其实已经告诉了你发生了什么:错误码点明哪个控制触发了,而两个 信息流之一会点明确切的规则。本页就是这个查找并追踪的流程——读错误码、 打开正确的信息流、找到规则。 如果你只记住一件事:来自一个安全控制的 400 不是你提示词里的 bug。它是 一个策略在尽职。你的工作是找出哪个策略,然后决定是修复调用还是放宽规则。

1. 我的 llm 请求为什么被拦下了?—— 从错误码开始

托管网关上的每一次安全拦截都返回 HTTP 400,在 OpenAI 形态的错误体里 带一个机器可读的 code。那个错误码是这条路上的第一个岔口——它告诉你要 调试哪个控制平面、要打开哪个信息流。
{
  "error": {
    "message": "tool \"shell.exec\" blocked by firewall: destructive shell command",
    "code": "firewall_blocked",
    "type": "invalid_request_error"
  }
}

guardrail_blocked

一条 防护栏 内容规则在你的请求输入或 模型输出上触发了。在 Matches 信息流中追踪它。 参见 §2

firewall_blocked

一条 防火墙 规则拒绝了一次工具调用。 在 Events 信息流中追踪它。参见 §3

firewall_approval_pending

一次工具调用被挂起等待人工审批——而非被拒绝。去解决它, 别去调试它。参见 §4
三个错误码都是 skip-retry:重新运行那个完全相同的调用会路由到同一个 策略并再次被拦。重试是被浪费的延迟——改去修复输入或规则。完整的错误码 表在 错误码

2. guardrail_blocked —— 在 Matches 中找到规则

guardrail_blocked 意味着附加到你密钥(或你工作区默认值)的一个内容策略 对请求输入或模型输出运行了一次 block 动作。拦截消息点名防护栏和规则, 而该请求不消耗你任何配额——输入拦截在计量之前触发;输出拦截退回预先 扣除的配额。 追踪它:
1

打开 Matches 信息流

在控制台里,前往 Guardrails 页面上的 Matches 标签 (GET /api/guardrail/match,Member)。每一条触发的规则都落在这里—— 它的 RuleTypeActionStage,以及一个 Detail 字符串,例如 pii: email, phonematched 3 keyword(s)
2

过滤到那次拦截

action = block 和你请求的时间过滤。匹配的那一行告诉你规则类型 (piiregexkeywordmax_charsllm_judgegroundingexternal)以及它是在 input 还是 output 阶段触发的。
3

看它实际匹配到了什么

默认情况下,该信息流记录一条规则触发了以及它的 Detail 元字符串 ——而不是匹配的子串。在该防护栏上打开 Log raw content (它默认关闭,这是隐私保守的姿态)以捕获那段冒犯字符串用于分诊。 该开关不会追溯生效。
觉得某次拦截是错的?打开那条匹配并把它标记为误报POST /api/guardrail/match/:id/mark-fp,Admin)。要在发布修复之前 先证明它,编辑规则并在防护栏编辑器的 Test 标签里重新运行那个样本 ——不调用上游,不消耗配额。

一个具体例子

你发出一条包含某客户 SSN 的支持回复。你的 pii-shield 防护栏有一个 entity_actions 覆盖,对 ssn 执行拦截
{
  "type": "pii",
  "stage": "input",
  "action": "mask",
  "entities": ["email", "ssn"],
  "entity_actions": { "ssn": "block" }
}
网关返回 400 guardrail_blocked。Matches 信息流显示 RuleType: piiAction: blockStage: inputDetail: 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该运行累积的花费越过了某条规则的分(cents)上限;解析为一次拒绝。
1

把 Events 过滤到那次拒绝

verdict=deny 过滤,再按 toolrun_idsession_id 过滤 以隔离那次确切的调用。事件点名匹配到的规则以及执行面——inboundresponsemcpegress
2

在匹配到的规则上读原因

原因字符串(例如 destructive shell commandegress host not allowed)告诉你规则是匹配在工具名、一个 args_match 子句,还是一个 egress 目的地上。 判定词汇表glob 与 JSONPath 参考 解码 这种匹配。
3

用 Test 沙箱确认

在防火墙 Test 标签里重放同一个工具调用 (POST /api/workspace/firewall/test,Developer+)以看到判定、 匹配到的规则和原因——不派发任何东西,不记录任何东西。
一次 cap_cost 拒绝不是规则误触——你的智能体运行撞上了你设置的 消费上限。要么该运行正在循环(检查 Runs 汇总和 异常信息流 里的 retry_loop), 要么这个上限对于该任务确实太低。审慎地提高上限,而不是单纯重试。

4. firewall_approval_pending —— 它是被挂起,而非被拒绝

firewall_approval_pending 是唯一一个你应当当作拦截来对待的 400。 一个 pending_approval 判定为人工挂起了这次工具调用;错误体携带一个 审批 id。这次调用没有失败——它在等待。
  1. 一名审查者解决它——从控制台(Developer+)或经由你自己的 HMAC webhook 回调POST /api/v1/firewall/approvals/:id/callback)。
  2. 你的智能体用错误里的那个 id 轮询 GET /api/v1/firewall/approvals/:id(网关令牌)。
  3. 一旦获批,携带一次性的 X-OrcaRouter-Firewall-Approval 头重新提交 原始调用,网关便放行它那一次。
完整的 HITL 环路参见 防火墙 → 人工审批

5. 不是安全拦截?先排除密钥

并非每个 400 都是一次防护栏或防火墙判定。在你一头扎进信息流之前, 先排除密钥约束——这些在任何策略运行之前就拒绝,并且不携带上面 那些安全错误码:
密钥的 model_limits 允许列表不包含所请求的模型。对列表之外模型的 请求会被提前拒绝。把该模型加到密钥上,或调用一个被允许的模型。
密钥有一个 allow_ips 允许列表,而请求来自列表之外的地址。把调用方 的 IP / CIDR 加进去,或从一个被允许的网络发起调用。
密钥的 credit_limit_usd 上限已耗尽(0 表示无限制)。提高上限, 或轮换到一个还有余量的密钥。
网关 hook(evaluate、MCP 派发)需要一个带 is_firewall_gateway=true 的密钥。一个普通中继密钥会得到 403。 为那些路由铸造一个 firewall-gateway-scoped 密钥。

6. 两分钟分诊流程

拦在提示词或响应文本上

错误码是 guardrail_blocked → 打开 Matches,过滤 action=block,读 Stage + Detail。修复内容或规则;在防护栏 Test 标签里证明它。

拦在一次工具调用上

错误码是 firewall_blocked → 打开 Events,过滤 verdict=deny,读执行面 + 原因。修复调用或规则;在防火墙 Test 标签里证明它。

调用被挂起

错误码是 firewall_approval_pending → 轮询审批 id 并携带审批头 重新提交。没什么要调试的。

以上皆非

没有安全错误码 → 检查密钥:model_limitsallow_ipscredit_limit_usd,或缺失网关范围导致的 403

7. 相关参考

错误码

完整的错误码表——网关能返回的每一种拦截、挂起和拒绝。

判定词汇表

每个防火墙判定意味着什么,以及它何时解析为一次拒绝。

Glob 与 JSONPath

解码匹配到你这次调用的 tool_name_globargs_match

防护栏 vs 防火墙

哪个平面触发了——文本筛查还是动作治理。
关于这些控制本身,参见 防护栏防火墙;关于它们拦截的威胁,从 威胁模型 开始。