Skip to content
Talk to our solutions team

Rules

The Rules block runs decision logic that lives outside your application code: you author rule sets in GRL, hand the engine a set of facts, and read back whatever the rules wrote. The deployable service is rules.svc.

A rule set is a named collection of rules. A rule is a condition and an action block:

rule ApproveSmallInvoice "auto-approve small invoices" salience 10 {
when
invoice["total"] < 5000
then
out.Set("approved", true);
Retract("ApproveSmallInvoice");
}

Execution is forward chaining, not a script. Every cycle the engine re-evaluates the when of every rule that has not been retracted, then fires exactly one rule — the runnable rule with the highest salience. It repeats until nothing is runnable, a rule calls Complete(), the caller’s context is cancelled, or the cycle cap is exceeded. The cap is fixed at 5000 cycles on both surfaces; neither the CLI nor rules.svc exposes a setting for it. Tripping it fails the execution and discards everything the run produced.

Facts go in as a map. Four names are bound by the engine after your facts and are not yours to use:

NameDirectionWhat it is
outwriteKey/value output collector. out.Set(k, v), out.Append(k, s). This is the result.
auditwriteAppend-only trail. audit.Log(ruleID, msg), audit.LogWithData(ruleID, msg, data).
findingswriteSeverity-graded validation list. Not constructible from a rule — see below.
inreadMemory slots and value transforms: in.MemSet, in.Transform, in.NewMapWithValues.

A fact you supply under any of those names is silently replaced. Facts you supply under a helper namespace (util, num, strings, time, math, map, array) silently replace the helper.

The block also carries a spatial document model — OCR ingest, word merging, line and block reconstruction, reading order, tables, fields, checkboxes, fuzzy matching and confidence scoring. Documents are addressed from rules through the bbox namespace, so a rule can ask what is written below this label rather than parsing text.

Both surfaces reach the same capabilities:

Capabilitykis CLIrules.svc
Rule-set load and executionyesyes
Utility namespaces (strings, num, time, math, map, array, util)yesyes
Document model, extraction, OCR ingestyesyes
log namespacenono

A document reaches a rule the same way on both: you name the document alongside the facts, and the engine binds the analysed document into that execution under bbox. On the CLI that is kis rules --bbox <name>=<path>; over HTTP it is a reserved bbox object on the POST /rule body, carrying the same document-name to word-box map.

{
"name": "invoice-checks",
"total": 1200,
"bbox": {
"page": {
"pages": [
{
"number": 1,
"width": 612,
"height": 792,
"words": [
{"text": "Borrower", "box": {"x0": 72, "y0": 100, "x1": 150, "y1": 115}, "confidence": 0.98}
]
}
]
}
}
}

The value under each document name is the .bbox word-box JSON described in OCR input, and the key (page here) is the name a rule passes to bbox.Get.

The rule text is identical either way — bbox.Get("page") returns the document, and every field, checkbox, table and matching call on it behaves the same. See Documents in rules for the bindings and Running rules.svc for the rest of the request.

The document and rule commands (kis rules, kis ocr, kis bbox, kis hocr2bbox) are proxy commands: the unified CLI passes every argument to a separately installed plugin binary. When it is not installed you get Error: 'rules' is not installed. and nothing runs. See the CLI.

Setup happens once; steps 4 onward repeat per execution.

  1. Construct the engine on the grule backend — the only backend — with the document namespace and the utility namespaces registered.
  2. Initialise namespaces. Each namespace initialises once; the facts it contributes are bound into every execution from then on.
  3. Load rules. GRL text is parsed and compiled into a rule set at load time. Syntax errors, unsupported constructs and duplicate rule names all surface here, never at execution.
  4. Bind facts into a fresh data context: start-up facts, then your facts, then the per-execution document bindings, then out/findings/audit, then in. Later bindings overwrite earlier ones.
  5. Clone a fresh knowledge base for the rule set, so concurrent executions never share state.
  6. Cycle. Check the context, evaluate every non-retracted when, stop if none are runnable, else fire the single highest-salience rule and repeat.
  7. Return the result — output, audit trail, findings, firing count and wall-clock duration.

Any evaluation error, action error, cycle-limit breach or context cancellation returns an error and no partial result: no output, no audit, no findings.

Loading is not concurrency-safe; execution is. Rule sets load before they are served, and executions then run concurrently without sharing state.

The engine ownsYou author
Parsing and compiling GRL into a rule set; reporting the line and column of every parse errorthe .grl rule text
Conflict resolution — one rule per cycle, highest salience firsta distinct salience per rule
Termination — Retract(), Complete(), the cycle cap, context cancellationa Retract() in every then that does not falsify its own when
Fact binding by reflection, and the reserved names abovethe fact map, and accessor syntax that matches the fact’s Go type
Provenance — every out.Set records the firing rule; one audit entry per firingextra audit.Log calls where you want them
Per-execution isolation and a fresh collector set per callnothing
Value normalisation primitives (trim, upper, lower, normalize_spaces, trim_currency, regex extraction)the in.Transform chain
Document analysis — word merging, line formation, reading order, tables, fields, checkboxesthe queries your rules make against it

Two things the engine does not do: it does not validate facts against a schema, and it does not isolate a failing rule from the rest of the set.

ConcernPage
One rule set, executed end to endQuickstart
Rule sets, salience, retraction, chainingWriting rules
GRL syntax, operators, fact accessThe rule language
Everything callable from a then blockFunctions
Working rule shapes to copyPatterns
Boxes, words, blocks, lines, reading orderThe document model
Fields, checkboxes, anchors, regionsExtraction
Table and master-detail detectionTables
hOCR ingest, converters, text cleanupOCR input
Fuzzy matching and confidence scoringMatching
Reaching a document from a ruleDocuments in rules
Running rules and converting documents locallyThe CLI
POST /rule, tenancy, rule deliveryRunning rules.svc
Bootstrap keys, flags, TLSConfiguration
Empty responses, silent boots, stale rulesTroubleshooting
Error codes and messagesErrors