Verified Decisions API
The flagship neuro-symbolic-recursive surface. Instead of generating free text, it returns an auditable decision —approved | denied | refused — with a cited proof chain, a
confidence, and a safe refusal when the engine cannot ground the answer well enough to be
accountable.
This is the use case where a pure LLM is unsafe: it will confidently approve actions that
violate policy. The symbolic layer gives deterministic, provenance-traced decisions relative to
the supplied facts and rules; the recursive layer handles multi-hop policy (transitive role
access, bill-of-materials/recall explosion, chained eligibility); the neural layer reads messy
natural-language requests.
Every request also runs through the canonical Grounded Symbol System (GSS) and a
tenant-scoped NSRMachine. Machine inference is mandatory for verified decisions — if the
seed pack is unavailable or inference does not complete, the API fails closed with HTTP 503.
This page reflects NSR v0.7.0. Several rule-evaluation semantics were corrected in v0.6.0
and v0.7.0 — see Behavior changes. If you wrote rules
against earlier docs, read that section.
Endpoints
Request
Rule effects
A rule may declare its policy intent explicitly viaeffect, which is authoritative over
predicate-name conventions — better for tenant-specific or non-English vocabularies.
effect: "review" became a first-class declared effect in v0.6.0. Before that it was
expressible only via predicate-name inference, and an inline rule declaring it would fail with
a 422 “unknown variant”. Review rules are subject-bound in the same way deny rules are.Negation-as-failure
A condition may setnegated: true: the rule fires only when no fact matches the atom. A
free variable in the negated atom is a wildcard, so not fraud_flagged(?o, ?r) fails whenever
any fraud_flagged(?o, *) exists.
negated is serde-default and skipped when false, so existing payloads are unchanged.
Outcomes
Cited symbolic policy is evaluated after GSS safety gates but before conversational
uncertainty and execution-runtime state. This matters when policy authorizes an action but
answer composition is ambiguous or live runtime state disagrees.
Response
cited_rules is the audit trail, reduced to the backward dependency path. When the request
carried inline policy, the proof also carries a SHA-256 over the canonicalized request-scoped
facts and rules, pinning the decision to the exact policy inputs it was evaluated against.
Behavior changes in v0.6.0 and v0.7.0
Several of these were fail-open correctness bugs. If you built against earlier documentation, the following now behave differently — in every case, more conservatively.Confidence is capped by the weakest supporting fact (v0.7.0)
Decision confidence was1.0 - grounding_uncertainty, decoupled from the proof and
non-monotonic — a 0.4-confidence fact could yield higher confidence than a 1.0 one. An
approval is now capped by its weakest supporting fact:
Subject and action binding (v0.6.0)
A rule fires for whatever the fact base satisfies, not for what the question asks. Givenmay_authorize(?p,?act) :- has_authority(?p,?act) and the fact
has_authority(ceo_kim, approve_wire), the engine proves may_authorize(ceo_kim, …).
The gate previously counted any cited request-scoped effect wholesale, so a wire could be
authorized for stranger_sven off the CEO’s authority, or delete_account authorized off
refund authority. A single conclusion-head check now covers all effects: the cited rule’s
effect only applies when its ground conclusion binds the request’s own subject and action.
Two related binding fixes:
- Numeric builtins — the binding gate replays a cited rule’s body to reconstruct which
subject it fired for, but the replay matcher did not evaluate comparison builtins (
leq,geq,lt, …). It returned “can’t tell”, so no mismatch was detected. A rulemay_refund(?o) :- order_amount(?o,?v), leq(?v, 500)could approve a refund for an order whose amount did not qualify. The matcher now computes comparison builtins under the binding, exactly as the solver does. - Single-character subject tokens — the subject-binding token match dropped tokens shorter
than 2 characters, so
ord-9andord-4(sharingord, differing only in the 1-char suffix) were treated as the same subject. A rule that fired forord-9could bind a decision aboutord-4. The match now requires every alphanumeric token, single characters included. Phrasing variance (order A1vsorder #A1) still grounds.
Abduction no longer asks for un-suppliable builtins (v0.7.0)
A failed comparison builtin such asleq(850,500) was reported in missing_facts with a
resolves_with, telling an agent to “supply leq(850,500)” — impossible. Comparison builtins
are now excluded; the actionable ask is the base predicate that binds the value, e.g.
amount.
MCP server
The NSR MCP server gained a per-request timeout (NSR_TIMEOUT_MS) so an agent never hangs on a
slow endpoint, plus client-side input validation that names the exact malformed rule or field
instead of surfacing a cryptic 422 deserialize error.
Verification
NSR ships a verifier-as-oracle evaluation apparatus: a 1,260-case auto-labeled decision-soundness corpus, a deterministic generator, and a runner that checks any live/v1/decisions deployment against the ground-truth labels — plus in-process property-based and
generative multi-invariant soundness tests.
Related
- Neuro-Symbolic Architecture — the conceptual model
- NSR-L — the rule language