The shape of a rule

A rule has a match expression (when to fire), an outcome (what to do), and optional parameters (how to do it). Rules are ordered; the first match wins. Rules live in a plain-text policy file and are loaded into RelayOne with a content-addressed hash; that hash is pinned in every evidence receipt produced under the rule.

Outcomes: allow, reroute, rewrite, block, hitl. The engine is CEL-compatible, so any CEL primer applies.

Available context

Every rule sees a request object with envelope fields, an identity object with user/team/agent claims, a tenant object with posture and budget state, and a flow object with destination-specific metadata (model, endpoint, content-category tags).

request.envelope.origin_region: string    // e.g. "ca-central-1"
request.envelope.destination:   string    // e.g. "openai:gpt-4o"
request.envelope.cross_border:  bool
request.envelope.content_tags:  list<string>  // e.g. ["pii.email","pii.phone"]

identity.user:    string
identity.team:    string
identity.scopes:  list<string>
identity.agent:   string

tenant.id:            string
tenant.posture:      string  // "on-prem" | "sovereign" | "hybrid" | "cloud"
tenant.budget.month_usage_cents: int
tenant.budget.month_cap_cents:    int

flow.model:       string
flow.tx_amount_cents: int   // for commercial transactions; 0 otherwise

Worked examples

1. Block unverified-tenant requests to external GPT endpoints

rule "block-unverified-external-gpt" {
  match:   !("tenant.verified" in identity.scopes)
           && request.envelope.destination.startsWith("openai:")
  outcome: block
  reason:  "tenant not verified for external GPT"
}
If the identity does not carry the tenant.verified scope, and the request is headed to any OpenAI endpoint, block it. Plain-English reason attached so the user sees why.

2. Reroute customer-data-bearing calls to internal R1 agents

rule "reroute-customer-data-to-r1" {
  match:   request.envelope.content_tags.exists(t, t.startsWith("customer."))
  outcome: reroute
  parameters: {
    target: "r1://internal/customer-safe-summarize",
    on_heroa: tenant.posture == "sovereign"
  }
}
If any content tag starts with customer., redirect the request to an internal R1 agent. If the tenant is sovereign, route via R1 on Heroa so the data never leaves the jurisdiction.

3. Enforce per-team monthly AI spend caps

rule "monthly-spend-cap" {
  match:   tenant.budget.month_usage_cents > tenant.budget.month_cap_cents
  outcome: block
  reason:  "monthly AI spend cap reached; contact finance"
}

rule "monthly-spend-warning" {
  match:   tenant.budget.month_usage_cents > (tenant.budget.month_cap_cents * 9 / 10)
  outcome: allow
  emit_event: "budget.near_cap"
}
Hard cap at 100% usage. Warning event at 90% so the finance dashboard lights up before requests start failing.

4. Mandate HITL approval on agent transactions over a threshold

rule "hitl-large-tx" {
  match:   flow.tx_amount_cents >= 50000   // $500 or more
  outcome: hitl
  parameters: {
    approvers: ["finance-leads", "compliance-ops"],
    timeout_seconds: 900,
    fallback: "block"
  }
}
Any agent transaction of $500 or more routes through a human-in-the-loop approval step. Finance leads and compliance ops get paged; fifteen-minute timeout; if no approver acts, the transaction is blocked.

Authoring workflow

  1. Edit the policy file locally. Rules are plain text; version control them.
  2. Run relayone policy lint to catch syntax issues.
  3. Run relayone policy simulate --against last-24h to preview decisions against recent traffic.
  4. Deploy with relayone policy apply. The content-addressed hash appears in evidence receipts from the next request onward.

Evidence integration

Every rule evaluation is recorded in the request's evidence receipt: the rule name, the policy snapshot hash, the outcome, and (when present) the reason string. An auditor verifying a bundle can replay the rule evaluation against the pinned policy snapshot to confirm the decision was consistent with the version then in force.