Rule DSL
Write BlazeRules rule files in YAML: schema, fields, lookups, decisions, and the condition tree.
A BlazeRules rule file is a single YAML document. The engine compiles it once into an immutable execution plan and then reuses that plan for every batch. This page walks the file top to bottom so you know exactly which keys go where.
A complete file at a glance
A rule file has a small set of top-level keys. Most are optional — the only thing you always need is a ruleset.
| Key | Required | Purpose |
|---|---|---|
schema_version | Yes | YAML format version. Use "2.1". |
fields | Optional | Type hints for input fields. Omit them and BlazeRules infers types from the first batch. |
lookups | Optional | Named CSV sets used by in_lookup / not_in_lookup. See Lookups. |
decisions | Optional | Default action and precedence ladder. See Decisions & Scoring. |
ruleset | Yes | The rules themselves: name, version, and a list of rules. |
The agent has one extra keyA top-level
instances:block configures the multi-instance ingest agent (blazerules_agent). It is not part of rule evaluation. See Production YAML Guide for a complete multi-instance file and CLI & Agent for agent runtime behavior.
Minimal example
The smallest useful file declares a version, an optional field hint, and one rule:
schema_version: "2.1"
fields:
amount: {type: float32, nullable: false}
ruleset:
name: My Ruleset
version: "1.0.0"
rules:
- id: high_amount_emulator
action: review
severity: HIGH
weight: 25
conditions:
and:
- {field: amount, op: gt, value: 1000}
- {field: device_type, op: eq, value: emulator}Fields are optional hints
The fields: block declares the type — and optionally the nullability and allowed values — of each input field. You do not have to provide it. When you omit a field, BlazeRules infers its type from the first evaluated batch (see schema inference in Core Concepts).
Why give hints at all?Hints make types explicit and stable across batches, catch typos in field names early, and let you pin a
categoricalfield to a known set ofvalues. Inference is convenient for prototyping; hints are better for production.
Field type hints use these column types:
float32 · float64 · int32 · int64 · categorical · entity_key · timestamp_ms · boolean · string
A few real declarations from the canonical sample file:
fields:
event_id: {type: string, nullable: false}
card_token: {type: entity_key, nullable: false}
amount: {type: float32, nullable: false}
account_age_days: {type: int32}
country_code:
type: categorical
values: [US, GB, IN, DE, BR, CN, RU]
device_type:
type: categorical
values: [ios, android, web, emulator]
merchant_bin: {type: int64}
ip_address: {type: string}
event_ts_ms: {type: timestamp_ms}
optional_note: {type: string, nullable: true}The entity_key type marks the field used to group an entity's history for Windows (here, card_token).
Per-rule fields
Each entry in ruleset.rules is one rule. The fields you will use most:
| Field | Purpose |
|---|---|
id | Unique identifier for the rule. Appears in winning_rule_ids on the result. |
action | One of approve, flag, review, block, score. |
severity | One of LOW, MEDIUM, HIGH, CRITICAL. |
weight | Integer added to the record's score when the rule matches. |
conditions | The condition tree (below). |
A rule also supports priority, reason_code, and shadow. Those drive how a verdict is chosen and how you roll rules out safely — see Decisions & Scoring for full treatment.
The condition tree
conditions is a tree. A leaf is a single test on one field; branches combine leaves with boolean logic.
A leaf usually looks like {field, op, value} or {field, op, values}:
- {field: amount, op: gt, value: 1000}
- {field: country_code, op: in, values: [US, GB]}Some operators take extra keys instead of value — for example cross-field operators use other_field:, bitfield operators use mask:, lookups use lookup:, and geo operators use lat_field / lon_field / other_lat_field / other_lon_field. The full list lives in the Operator Reference.
Branches nest with and, or, and not:
conditions:
and:
- {field: amount, op: gt, value: 1000}
- or:
- {field: country_code, op: not_in, values: [US, GB]}
- {field: device_type, op: eq, value: emulator}SQL and expression forms
Two forms let you express richer logic inside a leaf.
A sql: leaf accepts a SQL-style boolean expression, including any_match(...) over arrays of objects:
- sql: "amount > 100 AND account_age_days >= 0"
- sql: "any_match(items, x -> x.price > 100 AND x.category = 'electronics')"An expr: leaf computes arithmetic (add, sub, mul, div) and then compares the result with an op / value:
- op: gt
expr:
op: div
left: amount
right: available_credit
value: 0.8Derived forms build on these ideas: ML Scoring for model_score, Vector Similarity for vector_distance, and Windows for velocity aggregates.
Nested YAML vs SQL for the same logic
The condition tree and a sql: leaf can express the same predicate. Here is amount > 1000 AND country_code in [US, GB] written both ways:
conditions:
and:
- {field: amount, op: gt, value: 1000}
- {field: country_code, op: in, values: [US, GB]}Where to go next
A full production YAML with fields, lookups, rules, and multiple agent instances.
All 50 operators, grouped by family, with copy-pasteable YAML.
Velocity and aggregation windows over an entity's recent history.
Match fields against CSV membership sets.
How matched rules become a decision, a score, and a risk band.