Skip to content
Talk to our solutions team

Evaluating records

POST /rules/evaluate runs a static scope once per record you name. Each record is read as the caller with its related records and the scope’s knowledge, the rules decide, and their proposals come back. With apply: true they are written, as the caller.

Only a static scope with data.over can be evaluated.

{ "scope": "invoice-routing", "ids": ["inv-big", "inv-small", "nope"], "apply": false }
KeyMeaning
scopethe static scope
idsthe records’ keys (the scope’s over.key): between 1 and rules.evaluate.maxids, 100 by default
applywrite what the rules propose. Needs the apply action; without it the call needs evaluate and writes nothing
input, factsfacts added to every record’s, as for execute

With the rules of rules/routing/route.grl:

rule Senior "large invoices go to a senior reviewer, with a task" salience 10 {
when
in.Double("invoice.total", 0.0) > 1000.0
then
act.Set("review_tier", "senior");
act.Create("shop", "task", map.Of("id", "t-" + in.Str("invoice.id", ""), "subject", "review " + in.Str("invoice.id", "") + " for " + in.Str("customer.segment", "a customer")));
out.Set("tier", "senior");
}
rule Auto "small invoices are approved" salience 5 {
when
in.Double("invoice.total", 0.0) <= 1000.0
then
act.Set("review_tier", "auto");
out.Set("tier", "auto");
}

the call answers 200:

{
"scope": "invoice-routing",
"stamp": "sha256:84853064e9fe118a5c7c4882e0dc5fa321305e2b941d6304cbf1642b3db8efb8",
"principal": { "id": "u-shop-owner", "ptyp": "user" },
"apply": false,
"records": [
{
"key": "inv-big",
"out": { "tier": "senior" },
"findings": [],
"actions": [
{ "op": "set", "field": "review_tier", "value": "senior", "rule": "Senior", "cycle": 1 },
{ "op": "create", "source": "shop", "entity": "task",
"fields": { "id": "t-inv-big", "subject": "review inv-big for gold" }, "rule": "Senior", "cycle": 1 }
]
},
{
"key": "inv-small",
"out": { "tier": "auto" },
"findings": [],
"actions": [
{ "op": "set", "field": "review_tier", "value": "auto", "rule": "Auto", "cycle": 1 }
]
}
],
"missing": ["nope"]
}

missing lists the keys that found no record the caller may read: a key that does not exist and a record the caller’s access hides look the same.

The same call with "apply": true, for inv-big:

{
"scope": "invoice-routing",
"stamp": "sha256:84853064e9fe118a5c7c4882e0dc5fa321305e2b941d6304cbf1642b3db8efb8",
"principal": { "id": "u-shop-owner", "ptyp": "user" },
"apply": true,
"records": [
{
"key": "inv-big",
"out": { "tier": "senior" },
"findings": [],
"actions": [ "… as above …" ],
"applied": [
{ "source": "shop", "op": "update", "entity": "invoice", "key": "inv-big",
"fields": { "review_tier": "senior" }, "before": { "review_tier": null } },
{ "source": "shop", "op": "create", "entity": "task",
"fields": { "id": "t-inv-big", "subject": "review inv-big for gold" } }
]
}
]
}

applied is what was written, in order, after no-ops were dropped; an update of the record being evaluated carries before, the fields’ values as they were read. data.svc records the caller as the writer of each.

FieldWhat it is
keythe record
out, findings, actionsas for execute: the decision, the findings, the proposals
appliedwith apply: each write made
conflictthe record changed after it was read, twice: it was decided again once, and changed again
partialthe record’s writes span sources and a later one failed: what applied before it stays applied
error{code, message} when the record could not be decided or written

One record’s failure never fails the call: the call answers 200, and each record says what happened to it.

error.codeMeans
rules-execution-failed, rules-execution-timeouta rule failed or ran out of time on this record; out holds what was written before
rules-write-not-declareda proposal the scope’s writes do not allow; none of the record’s proposals is applied, dry or not
rules-write-conflictwith conflict: true, as above
rules-write-partialwith partial: true, as above
rules-source-deniedthe source refused the caller this write
rules-source-unavailablethe source could not be reached
StatusCodeWhy
400rules-facts-invalidno ids, or more than rules.evaluate.maxids; a scope without data.over; facts the scope does not take, or named like the record (over.as), a related record or a knowledge read
403rules-access-deniedthe caller may not evaluate, or not apply
404rules-scope-not-foundno static scope of that name
403 / 503rules-source-denied / rules-source-unavailablethe scope’s knowledge could not be read
  • Sweeps: the same decision over every record the scope matches.
  • act: proposing writes.
  • Errors.