A contextualized common-sense knowledge base: an in-memory or on-disk store of sentexes (sentence + context), indexed by a count-aware trie, with forward/backward inference and JTMS truth maintenance.
As a dependency — Leiningen [com.vaelii/vaelii "0.5.0"], or deps.edn
com.vaelii/vaelii {:mvn/version "0.5.0"} — from Clojars.
To work on it instead:
lein deps
lein test # integration tests
lein repl # loads namespace vaelii.core
Conventions: predicates are camelCase, individuals CapitalCamelCase, types
snake_case (unary predicates, e.g. (dog Fido)), contexts end with Context.
(require '[vaelii.core :as v] '[vaelii.starter :as starter])
(def kb (v/open-kb {})) ; in-memory records + index
; {:backend :disk :dir "/path"} to persist
;; a read sees what its context sees, up the genlContext cone — so say that the
;; world context reads the general one, or the rules below are invisible from it
(v/assert kb '(genlContext NaturalWorldContext UniverseContext) 'UniverseContext)
;; a type hierarchy + a typed individual; genl is transitive and cached
(v/assert kb '(genl dog animal) 'UniverseContext)
(v/assert kb '(genl animal thing) 'UniverseContext)
(v/assert kb '(dog Fido) 'NaturalWorldContext)
(v/isa? kb 'Fido 'animal) ;=> true (via genl; no context arg, so unscoped — any context counts)
;; a rule is a sentex; forward chaining + truth maintenance
(v/assert-rule kb '[(parentOf ?x ?y) (parentOf ?y ?z)] '(grandparentOf ?x ?z) 'UniverseContext)
(v/assert kb '(parentOf Tom Bob) 'NaturalWorldContext)
(v/assert kb '(parentOf Bob Ann) 'NaturalWorldContext)
(v/sentexes-matching kb '(grandparentOf Tom Ann) 'NaturalWorldContext) ;=> derived, placed in NaturalWorldContext
(let [bob (:id (first (v/sentexes-matching kb '(parentOf Tom Bob) 'NaturalWorldContext)))]
(v/retract! kb bob)) ;=> tears down what it solely supported
;; or skip all of the above: the bundled starter ontology, on its own stores —
;; the space number names the store, so a second KB wants one of its own
(def starter-kb (starter/load-into (v/open-kb {:space 2})))
The unit of knowledge is a sentex: a sentence — a Clojure s-expression, ground or a
pattern with ?x variables — plus the one context it holds in.
A sentex canonicalizes into one of two records, split so a fact does not carry the
rule-only slots: an AtomicSentex holds [sentence context id truth strength], and a
RuleSentex adds [antecedent consequent varmap direction defeasible assumption constraint]. A rule is a sentex too, indexed additionally by its antecedent and
consequent predicates, so it gets a handle, truth maintenance and retraction for free.
A handle is the integer id a stored sentex or justification is referenced by, allocated in assertion order. A justification is antecedent handles plus an informant, pointing at a conclusion and carrying the strength it confers; the JTMS reads these to compute belief. Sentences identical up to variable names, antecedent order, symmetric argument order or comparison direction dedup to one handle.
Transitivity is not done with rules. The genl closure over types and the genlContext
closure over contexts are cached and recomputed when an edge changes, as is the equality
partition behind rewriteOf / sameAs / equals.
Four properties hold everywhere:
genlContext cone:
facts, rules, taxonomy edges and definitional checks alike.Assert known-true content with {:strength :monotonic}. The default is :default, which
is most of a common-sense KB, and a default is defeasible at the edges.
lein run -m vaelii.web # serves a starter-loaded KB on http://localhost:3000
Browse the upper ontology, any term (every sentex containing it), a sentex (its supporting justifications and dependents), or a justification (its arguments and conclusion) — all cross-linked.
The browser loads more than the starter: the core vocabulary alone, a generated corpus of
a chosen shape, a vaelii export dump, an on-disk store, or a translated OpenCyc KB. Drop
one under ~/.vaelii/kbs/ and it appears on the /kbs page with no restart, loading in
the background and browsable before it finishes.
OpenCyc needs the reader plugin, which ships separately as vaelii-foreign. The whole route — from one dependency to a 1.2M-sentex KB, and the small vendored fixture to try it on first — is docs/kbs.md.
Drive a KB from the shell, or serve it over the network — both drive vaelii.core
and add nothing to it. See docs/operations.md.
# command line (--dir persists via the disk backend, recovered on open)
lein cli assert '(dog Fido)' NaturalWorldContext --dir /var/lib/vaelii
lein cli match '(dog ?x)' NaturalWorldContext --dir /var/lib/vaelii # => [(dog Fido)]
lein cli repl --starter # interactive
# headless daemon: one process owns one KB, serves it as EDN over HTTP
lein serve 4200 /var/lib/vaelii
;; a thin client (zero-dependency java.net.http), conn threaded explicitly
(require '[vaelii.client :as c])
(def conn (c/client "localhost" 4200))
(c/assert conn '(dog Fido) 'NaturalWorldContext)
(c/query conn '(dog ?x) 'NaturalWorldContext)
docs/ carries one note per subsystem. Four to start with: kbs.md to get a KB in front of you, api.md for the calls, naming.md for the spellings the KB enforces, and contexts.md for what a read can see. glossary.md defines the vocabulary. When something does not do what you meant — an empty query, a rule that will not fire, a KB holding facts nobody asserted — troubleshooting.md is indexed by symptom.
CONTRIBUTING.md — the build, the conventions, and the contributor terms. Commits are signed off under the DCO, and a first pull request prompts for the CLA. Security reports go through .github/SECURITY.md rather than the issue tracker.
Server Side Public License, version 1 (LICENSE).
Copyright © 2026 Vaelii LLC and the Vaelii contributors.
The SSPL is source-available rather than OSI-approved. The project intends to move to an OSI-approved license; the contributor license agreement is what makes that possible without re-collecting permission from every contributor.
Cyc and Cycorp are registered trademarks of Cycorp, Inc. Vaelii is not affiliated with, endorsed by, or derived from Cycorp — it reads the published OpenCyc distribution through a separate plugin, and ships none of it.
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |