跳转到主要内容
为一个工具做白名单回答的是一个智能体可以调用哪个工具。它无法回答 用什么参数shell.execls 没问题;对 rm -rf / 则是一场灾难。 db.query 对一个副本没问题;对 prod 则是一项负债。这个差别存在于 参数中,而一条工具名规则看不到它。 防火墙的参数子句args_match_json)弥合了那个缺口。它们检查模型为 一次工具调用选中的具体参数,并从它们的决定判定——所以你可以广泛地 允许一个工具,同时拒绝它能采取的那一种危险形态。本页是编写那些子句的 聚焦指南;关于完整的规则词汇表参见 防火墙规则, 围绕它们的策略模型参见 防火墙
参数值只在模型选中了如何调用一个工具之后才存在,所以参数子句属于 responsemcp 执行面。在 inbound 上——智能体只声明工具定义——没有调用时参数可检查。

1. 何时验证工具调用参数

每当一个工具总体上安全但在某种特定形态下危险时,就使用一个参数子句:

破坏性命令

允许 shell.exec,但在命令匹配 rm -rfmkfsdd if= 时拒绝。

生产杀伤半径

允许 db.query,但在连接目标是 prod 时拒绝(或挂起等待审批)。

内部目的地

允许一个 fetch 工具,但在它的 url/ip 参数落入一个 RFC-1918 范围 或云元数据 IP 时拒绝。

超大操作

允许一个批量工具,但在一个 limitcount 参数超过一个数值上限时 拒绝。
该规则仍然首先匹配工具名;子句把它从哪个工具收窄到哪次调用

2. 一个子句集的形态

args_match_json 是一个 JSON 编码的字符串,其解码后的值是一个持有 clauses 列表的对象。每个子句是一个 { path, op, value } 三元组,而 所有子句以 AND 组合——只有当每个子句都为真时该规则才触发。解码后, 该值看起来像:
{
  "clauses": [
    { "path": "$.command",    "op": "regex",      "value": "rm -rf|drop table" },
    { "path": "$.connection", "op": "in",         "value": ["prod", "replica"] },
    { "path": "$.ip",         "op": "cidr_match", "value": "10.0.0.0/8" }
  ]
}
在一个规则体中,该字段把那段 JSON 作为一个单一的转义字符串携带——例如 "args_match_json": "{\"clauses\":[{\"path\":\"$.command\",\"op\":\"regex\",\"value\":\"rm -rf\"}]}" 一个空的或缺失的 args_match_json空真(vacuously true)——该规则 仅靠它的工具名 glob 匹配,与一条仅名称规则的做法完全相同。

3. 运算符

七个运算符构成了这个封闭的词汇表。控制台在你保存时验证运算符及其值的 形态,所以一个格式不正确的子句绝不会被持久化。
运算符在以下情况匹配
eq标量相等(数字按数值比较;类型不匹配即为不匹配)。
contains子串——两个操作数都必须是字符串。
regex一个 Go RE2 模式匹配该字符串值(线性时间,无反向引用)。
in该值是给定 JSON 数组的一个元素。
cidr_match该字符串 IP 落入给定的 CIDR。
gt / lt数值大于 / 小于(字符串不被强制转换)。

4. 路径语法

一个子句的 path 是工具参数对象之上的一个小的 JSONPath 子集
按名称读取一个顶层或嵌套对象字段。
索引进一个数组,可选地继续进入该元素的字段。
对照整个参数 blob 匹配(与 containsregex 搭配做粗扫很有用)。
没有通配符、过滤器、切片或递归下降——该语法有意精简,所以匹配在热路径上 保持线性时间且可预测。

5. 一个完整示例

你让你的智能体自由运行 shell.exec,但一次递归强制删除永远不应该到达 shell。编写一条 response 执行面规则,在命令参数看起来具破坏性时 拒绝 shell.exec
1

打开规则编辑器

在控制台中,打开绑定到你智能体密钥的防火墙策略(或工作区默认)并 添加一条规则。编辑策略是一个 Developer+ 操作——Member 可以读取 策略但不能写入。
2

在 response 执行面上匹配该工具

把执行面设为 response,工具 glob 设为 shell.execresponse 执行面携带模型选中的参数,正是该子句所需要的。
3

添加参数子句

$.command 上添加一个 regex 子句,然后把判定设为 deny
{
  "stage": "response",
  "tool_name_glob": "shell.exec",
  "verdict": "deny",
  "args_match_json": "{\"clauses\":[{\"path\":\"$.command\",\"op\":\"regex\",\"value\":\"rm\\\\s+-rf|mkfs|dd\\\\s+if=\"}]}"
}
args_match_json 是一个 JSON 编码的字符串;其解码后的值就是 §2 中 展示的 { "clauses": [ … ] } 对象。
4

在依赖它之前 dry-run

使用 Test 标签 对一个样本 shell.exec 调用评估该规则。它返回判定、匹配到的规则和原因——不派发 任何内容,不持久化任何内容。
现在带有 "command": "ls -la"shell.exec 像以前一样通过,而 "command": "rm -rf /var" 被拒绝。response 上的一个拒绝让模型看到一个 工具错误并作出反应——换一个工具、询问用户,或者停止——而非崩溃。
想允许该调用但剥除一个泄露的值而非拦截?把判定换成 sanitize。Sanitize 不脱敏该子句所匹配的东西——它在参数字符串上运行一个独立的脱敏器(像 openai_keyanthropic_keyssn_us 这样的命名预设,外加你自己的自定义 正则),把每个命中替换为一个 [redacted:…] 令牌,并转发清理后的调用。 args_match_json 子句仍然决定该规则是否触发;脱敏器决定什么被擦除。 参见 脱敏参数。Sanitize 只脱敏 工具调用参数——绝不脱敏工具返回的内容。

6. 子句故障关闭——影响规则,而非请求

如果一个子句无法被评估——路径无法解析、参数格式不正确,或一个 regex / CIDR 无效——该子句评估为 false,该规则就不触发。该调用落到下一条 规则或策略的 default_verdict。一个损坏的子句绝不会自动拒绝,也绝不会 扰动中继。
因为一个无法评估的子句使它的规则匹配,所以永远不要依赖一个子句以某种 特定方式失败。把你的”捕获一切危险”规则编写为一个带有它自己工具 glob 的 明确 deny,并把参数子句用于收窄一个许可——而非作为你的最后一道防线。

7. 把子句与规则的其余部分组合

参数子句与一条规则表达的其他一切叠加——它们是几个 AND 条件中的一个:
与之组合效果
tool_name_glob子句只在工具名匹配后才运行——名称在先,参数在后。
skill_name_glob所属技能对同一个工具的参数设不同的门(例如对 community.* 更严格)。
verdict把子句与 denysanitizepending_approvalcap_cost 搭配,而不只是 deny
多个子句全部都必须成立——把一个 regex 命令检查与一个 in 环境检查组合以紧密限定一个拒绝。
关于每种搭配产生的精确判定语义,参见 判定;关于一个被挂起的调用如何解决,参见 审批

8. 这部分的位置

防火墙规则

完整的规则参考——glob、子句、sanitizer、egress 和序列。

参数 cookbook

针对常见危险形态的可复制粘贴 args_match_json 配方。

防火墙执行面

为什么参数子句存在于 responsemcp 上,而非 inbound

拦截工具

当没有任何参数安全时,直接拒绝一个工具。
关于更广的图景,参见 危险工具调用OrcaRouter 如何检查