A rule document is one of three things: a single rule, a rule set, or a decision table. Every object in it has a closed set of keys, so an unknown key is a validation error, not something silently ignored.
The formal contract is a JSON Schema (draft 2020-12): download rule-schema.json. engine.Validate is the authority: it also checks what a schema can't express, such as unique ids and whether a regular expression compiles.
Document shapes
The root has
It is
Loads as
id and condition
a single rule
a rule set of one rule
rules
a rule set
a rule set
decisionTable
a decision table
a rule set, one rule per row
Rule set
Key
Required
Type
Meaning
rules
✓
array of rules
At least one rule. Ids must be unique.
name
string
For people. Surfaces as RuleSet.Name.
description
string
For people. Ignored by the engine.
stopAfterFirstMatch
boolean
Stop after the first rule whose condition holds. false by default.
params
object
Named expressions every rule may reference. See Scoped params.
Rule
Key
Required
Type
Meaning
id
✓
string
Unique in the set. Reported in results, traces and errors.
condition
✓
condition
A group or a leaf.
actions
array of actions
Applied when the condition holds. May be empty or absent.
else
array of actions
Applied when the condition doesn't hold.
priority
integer
Higher runs first. 0 by default; ties keep document order.
enabled
boolean
false skips the rule entirely. true by default.
failureMessage
string
Non-empty. Surfaces on result.Failures when the rule is evaluated and its condition doesn't hold. Excluded from the content hash.
params
object
Named expressions for this rule only, shadowing the set's on a name collision. See Scoped params.
description
string
For people. Ignored by the engine.
layout
any
For visual editors. Ignored by the engine and excluded from the content hash.
Condition group
Key
Required
Meaning
type
✓
Always "group".
operator
✓
AND or OR (one or more children), or NOT (exactly one).
whatever the function named in name expects, or none
Any, All, None
none: condition instead
Conditions explains each, and what each does with a null.
Action
Key
Required
Meaning
type
✓
setOutput, addToOutput, appendToOutput, removeOutput, or a custom action type the engine registered.
target
✓
The output name.
value
see meaning
A scalar or an expression. Required for the built-in writers, forbidden for removeOutput, optional for a registered custom type (the handler then sees null).
A call names a value function the engine registered; operands is optional (a no-argument call), and a function that declares a required operand count gets calls arity-checked at load. A param references a scoped param in scope, and is not valid inside a quantifier's element condition. Computed values has the semantics.
Scoped params
params maps names to expressions. The set's params are visible to every rule; a rule's are visible to that rule and shadow the set's on a name collision; a decision table may carry params for its then cells. Definitions may reference sibling and outer params, but never cyclically — a cycle is a validation error at the offending definition. References are inlined at load, so params never change what a rule computes, only how the document reads; a param-authored document gets the same content hashes as its hand-inlined twin. Scoped params is the guide.
Columns of conditions: { "field": "…", "operator": "…" }. operator defaults to Equals.
outputs
✓
Columns of actions: { "target": "…", "type": "…" }. type defaults to setOutput and may name a registered custom action; removeOutput isn't allowed.
rows
✓
{ "when": [ one cell per input ], "then": [ one cell per output ] }.
hitPolicy
collect (default) or first.
params
Named expressions the then cells may reference. See Scoped params.
id
The prefix of the generated rule ids: <id>-0, <id>-1, …, or row-0, row-1, … when omitted.
name, description
For people.
A nullwhen cell is a wildcard, and a nullthen cell writes nothing. Decision tables has worked examples.
Known differences between the schema and the engine
Extra keys on an expression object. The schema rejects a key it doesn't know on an expression ({ "field": "Order.Total", "note": "…" }); the engine's validator decides an expression's kind from op, field or literal and ignores any other key. Documents that pass the schema always load.