The matching language behind a firewall policy. Match tool calls by name, skill, arguments, and destination — then allow, audit, deny, sanitize, hold for approval, or cap cost. Deterministic, fail-closed, and safe on the hot path.
A firewall policy is an ordered list of rules.
This page is the complete reference for what a rule can express — the
matching language, the verdicts, and how the engine evaluates them.Rules are authored in the console rule editor, which writes structured
JSON match objects. Everything below describes that vocabulary so you can
read, reason about, and verify a rule precisely — whether you build it in
the UI or post it through the API.
Redaction config, used when verdict = sanitize. See §5.
egress
object
Host/CIDR allow/deny list, used when stage = egress. See §6.
cap_cost_cents
int
Run-cost ceiling, used when verdict = cap_cost.
sequence
object
Ordered multi-step match, enforced reactively. See §8.
notes
string
Author rationale; ignored by the engine.
A rule matches a tool call when all of its declared conditions hold:
the stage matches (or is empty), the tool glob matches, the skill glob
matches (or is empty), the argument clauses match (or are absent), and the
egress scope matches (egress rules only). The engine walks rules in
priority order and the first match wins.
matches http.fetchonly when it’s owned by a community.* skill —
trust the same tool from a built-in skill, gate it from a community one.
An empty skill glob matches any owner. How a tool call is attributed to a
skill is covered in Skills.
Tool-name matching answers which tool; argument clauses answer with
what arguments — the difference between “block shell.exec” and “block
shell.exec only when the command is rm -rf.”args_match is a set of clauses, all AND-ed together:
A small JSONPath subset over the tool’s argument object:
$.foo, $.foo.bar — field access
$.foo[0], $.arr[1].k — array indexing
$ — the whole arguments object
No wildcards, filters, slices, or recursive descent.
Argument clauses fail closed — the rule, not the request. If a path
doesn’t resolve, the arguments are malformed, or a regex/CIDR is invalid,
the clause evaluates false and the rule simply doesn’t fire — the call
falls through to the next rule or the default verdict. A broken clause
never auto-denies and never crashes the relay. Write your “catch
everything dangerous” rule as an explicit deny with its own glob rather
than relying on a clause to fail a particular way.
The console validates clauses strictly on save (unknown operators, bad
paths, non-array in values, uncompilable regexes, and invalid CIDRs are
all rejected) so a malformed clause can’t be persisted in the first place.
A sanitize verdict redacts matched substrings from the tool arguments
and forwards the cleaned call — useful for stripping secrets or PII an
agent put in a tool argument without blocking the whole action.
Preset matches are replaced with [redacted:<preset>]; custom-regex
matches with [redacted:custom]. The built-in preset library:aws_access_key, aws_secret_key, openai_key, anthropic_key,
bearer_token, email, ssn_us, credit_card (with a Luhn check).A sanitize rule must declare at least one preset or custom pattern — an
empty sanitizer is rejected on save. On the inbound surface there are no
call-time arguments to redact, so a sanitize verdict there escalates to a
block.
Entries match as a CIDR, an IP literal, or a case-insensitive hostname;
hostnames are best-effort resolved and re-checked against IP/CIDR entries.
The polarity follows the verdict: with an allow verdict the allow list
defines what’s in scope and deny carves exceptions out of it; with an
enforcing verdict (deny) the deny list defines what’s blocked and
allow carves exceptions out.169.254.169.254 (the cloud metadata endpoint) and RFC-1918 ranges are
the canonical things to deny — the block_ssrf_egress preset and the
tightautonomy level
ship exactly that.
Some risks are only visible across several calls — read 50 CRM records,
then export, then hit an external host. A sequence rule matches an
ordered chain rather than a single call:
Each step is a tool glob with an optional min_count (default 1) and an
optional egress: true (the step must be an egress call). Steps must
occur in order — interleaving with other calls is fine — and the whole
chain must complete within window_seconds (0 = no bound).
Sequences are enforced reactively by an asynchronous matcher, not
inline on each call — a sequence with a * step would otherwise match
every single tool call. They light up the events feed and can trigger
follow-on action, but they don’t block the individual call that completes
the chain in real time.
First match wins. Rules run in priority ASC, id ASC order; the
first rule whose conditions all hold decides the verdict. No rule
matches → the policy default_verdict.
Deterministic and dependency-free. Glob and clause matching are pure
string/JSON operations with no network call, safe to run on every tool
call. Regexes are RE2 — linear time, no catastrophic backtracking.
Fail-closed clauses. A clause that can’t be evaluated makes its rule
not fire rather than auto-denying (§4).
Strict save-time validation. Verdict/stage pairings, sanitizer
non-emptiness, cap_cost_cents presence, clause shape, and ref
resolution are all checked when you save — invalid rules can’t be
persisted.
Audited. Every rule create/update/delete writes an audit row after
the change commits; rule blobs and secrets are never written to the
audit log.