Skip to content

Use case: reasoning & inference

little big brain can answer questions using facts you never explicitly wrote, by deriving them from what you did write. This is the reasoning layer, and it comes in two forms that compose:

  1. Type closure — an RDFS subClassOf hierarchy, so a query for a broad type also matches its subtypes.
  2. Rule inference — SHACL-AF rules that entail new edges to a bounded fixpoint (transitivity, role/classification derivation, and more).

Reasoning is deterministic, transparent, and snapshot-consistent: derived facts are computed the same way every time, you can see how they were derived, and you can pin reasoning to any historical snapshot.

If your ontology says ElectricCar is a subclass of Car, which is a subclass of Vehicle, then a query for Vehicle instances also returns Car and ElectricCar instances — without you duplicating any facts. The type is a field on the record and the closure is resolved at query time, so there is nothing to rebuild when the hierarchy changes.

The rdfs:subClassOf closure is on by default. Turn it off for exact-type-only matching:

# Default: subClassOf closure on — matches Vehicle and all its subtypes.
lbb.sparql("SELECT ?v WHERE { ?v a <https://littlebigbrain.com/class/vehicle> }")
# Exact type only — no closure.
lbb.sparql(
"SELECT ?v WHERE { ?v a <https://littlebigbrain.com/class/vehicle> }",
entailment="none",
)

Rules derive new edges from existing ones — computed to a bounded fixpoint. A classic example is transitivity: if A reports_to B and B reports_to C, a rule can entail A reports_to C. The same mechanism handles role derivation, classification, and other “if these facts hold, then this fact holds” patterns.

The workflow is preview → store → query:

  1. Preview the derived edges before committing to a rule set — they are computed and returned but never written to the graph.
  2. Store a rule set on the branch so queries can run over the inferred facts.
  3. Query with reasoning folded in.
// 1. Preview what a rule set would derive (nothing is written).
// lbb_query
{ "mode": "infer", "rules": [ /* SHACL-AF rules */ ] }
// 2. Store the rule set on the branch.
// lbb_configure
{ "action": "define_rules", "rules": [ /* SHACL-AF rules */ ] }
// 3. Validate or select over inferred facts.
// lbb_query
{ "mode": "shacl", "shacl_mode": "select", "include_derived": true, /* … */ }

Two independent switches control what a read sees:

Control Effect Default
entailment RDFS subClassOf type closure on (entailment: "none" disables)
reason fold in edges entailed by the stored rule set off (reason: true enables)
include_derived (SHACL) validate/select over inferred facts off

They compose: a query can use type closure and rule-derived edges at once. When neither is set, you get only the facts exactly as written — useful when you want literal ground truth.

Reasoning here is not a black box:

  • Transparent. Derived facts are produced through a single, inspectable reasoning step rather than silently mixed in — you can trace why a fact was inferred, the same way provenance explains a written fact. Preview mode shows exactly what a rule set would derive before you store it.
  • Snapshot-consistent. Reasoning runs over the same snapshot as the rest of a query, and you can pin it to a point in time with as_of_valid_time / as_of_commit_seq — so you can reason over the graph as it was at a past commit.

An AI agent should not have to re-derive what the system can entail. Reasoning gives an agent:

  • Deterministic derivation. Transitive relationships, classifications, and type generalizations are computed the same way every run — unlike ad-hoc LLM reasoning that varies from call to call and burns tokens.
  • Better recall without more writes. A query for a broad concept surfaces the specific instances beneath it via type closure, so the agent doesn’t have to enumerate every subtype.
  • Auditable inferences. Because derivations are transparent, the agent (and you) can justify an inferred fact instead of trusting an opaque guess.

See why RDF & SHACL suit AI agents and agent long-term memory for how this fits an agent loop.