Skip to main content
Reference

Rule file reference

A rule file is a YAML document that declares a scope and its rules. The engine loads all .yaml and .yml files from a rules directory and indexes them by scope name.

Top-level fields

FieldTypeRequiredDefaultDescription
scopestringYesUnique name for this rule set. Must match [a-z][a-z0-9-]*, max 64 characters.
profilestringNoName of a profile to load. Maps short aliases to field paths in CEL expressions.
modestringNoaudit_onlyenforce — rules are enforced (deny blocks, redact mutates). audit_only — rules are evaluated and logged but never enforced.
on_errorstringNoclosedclosed — deny the call when a CEL expression errors. open — allow the call and skip the rule on error. In audit_only mode, errors are always treated as not matched.
defsmap(string, string)NoNamed constants substituted into CEL when expressions before compilation.
packs[]PackRefNoStarter packs to import. Pack rules are evaluated before inline rules.
case_sensitiveboolNofalseWhen false (default), all string values in params and context are lowered before CEL evaluation. Set to true for exact-case matching.
rules[]RuleYesList of rules. Max 500 per scope. Evaluated in order; deny short-circuits.

Rule fields

FieldTypeRequiredDefaultDescription
namestringYesUnique within scope. Must match [a-z][a-z0-9-]*, max 64 characters. Used in audit logs and denial responses.
descriptionstringNoHuman-readable explanation.
matchMatchNoWhen this rule applies. If omitted, the rule matches all calls in the scope.
actionstringYesdeny — block the call. log — allow and record. redact — allow and mutate fields.
messagestringNoReturned to the caller on deny. Recommended for deny rules.
redactRedactSpecConditionalRequired when action is redact. Defines what to redact and how.

Match block

FieldTypeRequiredDefaultDescription
operationstringNoGlob pattern matched against the call’s operation name.
whenstringNoCEL expression evaluated against the call. Must return bool. Max 2048 characters.

If both fields are present, both must match. If neither is present, the rule always matches.

Operation glob syntax

PatternMatches
create_issueExact match
create_*Any operation starting with create_
llm.tool_*llm.tool_result, llm.tool_use, etc.
*All operations (same as omitting operation)

Wildcards: * matches any sequence of characters. ? matches any single character. Regex is not supported in operation — use when for complex matching.

Redact block

Required when action is redact. Must have secrets: true, non-empty patterns, or both.

FieldTypeRequiredDefaultDescription
targetstringYesDot-path to the string field to scan. Must be a params.* path.
secretsboolNofalseEnable automatic secret detection (~160 built-in patterns via gitleaks). Detected secrets are replaced with [REDACTED:<rule-id>]. Runs before custom patterns.
patterns[]PatternNoList of regex patterns to match and replace. Max 50 patterns per redact block.

Pattern fields

FieldTypeRequiredDescription
matchstringYesRE2 regex pattern. Must not be empty.
replacestringYesReplacement string. Supports RE2 capture group references ($1, ${name}, etc.). The entire match is replaced with the expanded value.

Defs

Named string constants substituted into CEL when expressions before compilation. Each value must be a valid CEL sub-expression (list literal, string literal, integer, etc.).

Def name constraints

ConstraintValue
Pattern[a-z][a-z0-9_]*
Max length64 characters
Value max length2048 characters
ValueMust not be empty

Def names must not shadow reserved names. See Reserved names.

Pack references

FieldTypeRequiredDescription
namestringYesMatches the starter pack’s name field.
overridesmap(string, any)NoPer-rule overrides. Key is the rule name in the pack.

Override values

ValueEffect
disabledRemove the rule entirely.
Map with when, message, or actionShallow merge — specified fields replace the pack rule’s fields, unspecified fields are inherited.

You cannot override name or operation. Use a new inline rule instead.

Constraints summary

ConstraintLimit
Scope name pattern[a-z][a-z0-9-]*
Scope name max length64 characters
Rule name pattern[a-z][a-z0-9-]*
Rule name max length64 characters
Def name pattern[a-z][a-z0-9_]*
Def name max length64 characters
Max rules per scope500
Max patterns per redact block50
Max when expression length2048 characters
Max def value length2048 characters
Regex syntaxRE2 (linear-time, no backtracking)
Rule namesUnique within scope
Scope namesUnique across all loaded rule files

Reserved names

Def names and profile alias names must not use any of the following identifiers:

CategoryNames
Top-level variablesparams, context, now
CEL standard functionssize, has, matches, startsWith, endsWith, contains, exists, all, filter, exists_one
Keep custom functionscontainsAny, estimateTokens, inTimeWindow, rateCount, lower, upper, matchesDomain, dayOfWeek, hasSecrets
CEL type identifiersint, uint, double, bool, string, bytes, list, map, type, null_type
Literal keywordstrue, false, null

Evaluation order

  1. Pack rules are evaluated before inline rules.
  2. Rules are evaluated in file order.
  3. First deny match short-circuits — the call is blocked immediately.
  4. All matching redact rules are applied in order (mutations accumulate).
  5. All matching log rules are recorded.
  6. If no rule denies, the call is allowed.

Field paths

Field paths use dot notation to navigate the call object. Used in redact.target and CEL when expressions.

PathDescription
params.titleTop-level parameter field
params.input.commandNested parameter field
params.toArray field (use collection functions in CEL)
context.agent_idAgent identity
context.direction"request", "response", or ""
context.labels.sandbox_idLabel value

Redact targets must start with params..

Complete example

scope: linear-tools
profile: linear
mode: enforce
on_error: closed

defs:
  allowed_teams: '["team-eng", "team-infra"]'
  max_issues_per_hour: "20"

packs:
  - name: linear-safe-defaults
    overrides:
      no-auto-p0: disabled

rules:
  - name: team-allowlist
    description: "Restrict issue creation to approved teams"
    match:
      operation: "create_issue"
      when: "!(team in allowed_teams)"
    action: deny
    message: "This agent may only create issues in Engineering and Infrastructure."

  - name: issue-creation-rate
    description: "Prevent runaway issue creation"
    match:
      operation: "create_issue"
      when: "rateCount('linear:create:' + context.agent_id, '1h') > max_issues_per_hour"
    action: deny
    message: "Rate limit exceeded. Maximum 20 issues per hour."

  - name: strip-secrets
    description: "Redact secrets from tool results"
    match:
      operation: "*"
    action: redact
    redact:
      target: "params.content"
      secrets: true
      patterns:
        - match: "(?i)ssn:\\s*\\d{3}-\\d{2}-\\d{4}"
          replace: "[REDACTED:SSN]"

  - name: audit-all-reads
    description: "Log all search and get operations"
    match:
      operation: "search_*"
    action: log

  - name: audit-gets
    match:
      operation: "get_*"
    action: log