Retrieval is implemented and reachable today through the MCP tools
search_knowledge and read_knowledge_page (and via canonic query’s underlying service). The CLI’s own canonic knowledge search command is a stub; see that page for status.Page format
A knowledge page is Markdown with YAML frontmatter. Its path determines scope and id.Scope
Two scopes, defined by path, not by a field you set by hand:knowledge/global/: shared, visible to everyone.knowledge/user/<id>/: personal, additive only.
global + their own user/<id>, never another user’s pages.
Retrieval
Search fuses two arms via Reciprocal Rank Fusion:- Lexical: a tantivy BM25 index over
body+summary+tags. Always available, withsummary/tagsboosted so a concise-field match outranks a body-only one. - Vector (optional): page embeddings from the local embeddings runtime, compared by cosine similarity. Present only when the
embeddingsextra is installed.
Graph traversal
After a search returns seed hits, an agent can pull connected context by traversing the reference graph without re-searching: from each seed,sl_refs / refs / [[links]] are followed breadth-first up to a bounded depth, deduped, and returned as one connected subgraph: the pages reached plus the live semantic entities they bind. This is what lets one hit on “active customer” surface its bound caveats, the policy page it links to, and the semantic source it describes, in a single round trip.
usage_mode
| Mode | Behavior |
|---|---|
reference | Found by search/traversal only. The default. |
caveat | Auto-surfaced whenever a bound sl_ref entity appears in a result: a relevant warning rides along even if nobody searched for it. |
policy | A business rule/definition page; ranked like reference but tagged distinguishably. |
definition | The canonical prose definition for a term; collisions follow the strict-additive rule. |
caveat page documents a risk. If the risk must be prevented, not just disclosed, it’s promoted to a contract guardrail: knowledge explains, the contract enforces.
Drift & freshness
A page never copies a measure’s SQL: it references the measure by name, and{{ sl:….expr }} renders the live expr at read time, so the rendered definition can’t fall out of sync. But the surrounding prose can still go stale: meta.bound_fingerprints records the measure-definition fingerprint each page depends on, and when that fingerprint changes, the page is flagged for review, a signal, not a silent edit. meta.last_validated_at similarly drives a staleness signal surfaced at query time, so an agent can caveat honestly about how recently a definition was checked.
Validation
Every reference is checked on write, whether the page comes from ingestion or a human edit: eachsl_ref must resolve to a live semantic entity, and each ref/[[link]] must point at an existing page in a visible scope. A broken reference blocks the write with a precise location: you cannot author a page that points at nothing. When ingestion later detects that a referenced entity disappeared, the stale sl_ref is proposed for removal as a normal reviewable diff, never a silent edit.