Retrieval and context
Memory is useful only if the current, relevant item ranks ahead of stale history without making the system dependent on a network service. Knowl therefore uses a local vector-primary path with a bounded lexical fallback.
Current retrieval
Agent retrieval through MCP knowl_query is vector-primary by default, using the repository's
configured local embedding profile. New repositories default to Granite Small English R2. Its
project candidate set is reranked with bounded BM25 lexical results plus
exact-identifier, freshness, status, confidence, and recency adjustments. Normal MCP queries
return active items unless another status is requested. Exact filenames, item IDs, and
symbol:// locators receive lexical support even when semantic similarity is weak.
In a single repository, the public knowl query CLI uses a project-local FTS/BM25/LIKE candidate
path. A current query in a linked workspace also fans out to peers; when vectors are enabled, it
attempts a query embedding and local vectors for federated semantic ranking, then falls back to
lexical results if embedding preparation fails. Historical --as-of queries remain local.
What a result carries
Each knowl_query result is compacted before it is returned:
content— up to 2,000 characters of the stored fact, withtruncated: truepresent only when it was cut. Around 91% of items on a typical store arrive whole. The ceiling was 600 until 3.1.0, which returned roughly half of every fact with nothing saying so.affectedPaths— up to six repository-relative files the item depends on, each up to 120 characters. Withheld for an item owned by another repo in a workspace: its paths are relative to a checkout that is not yours, and linked repos are often fork siblings where the same path exists in both and means something different.score— the ranker's fused relevance in [0,1] when a calibrated one exists, or the stringuncalibrated (<reason>)when it does not. A string means the ranker has an order but no opinion on strength, so judge the content rather than the position. Reasons arelexical-only(no semantic half ran),not embedded(vector ran but never saw this row), andlayered namespaces(each namespace scored against its own corpus, so the numbers are not comparable to each other).
Titles are capped separately at 200 characters, and previews of things retrievable in full
elsewhere — evidence excerpts, timeline assertions, skill markdown, knowl_skill_run output —
stay at 600.
# Current CLI query; single-repository candidates are lexical.
knowl query "auth token design"
# Prepare and control vectors used by MCP/agent retrieval.
knowl reindex --vectors
knowl config set search.vector.enabled false
Choosing an embedding model
search.vector.preset selects the local embedding model. A preset bundles model, dtype and
pooling together, because pooling is not discoverable at runtime and the wrong value produces
plausible-looking vectors that rank badly with no error.
| Preset | Model | Size (q8) | Context | Languages |
|---|---|---|---|---|
arctic-embed-m-v2 |
Snowflake/snowflake-arctic-embed-m-v2.0 |
~305MB | 8k | English + multilingual |
granite-small-en-r2 (default) |
onnx-community/granite-embedding-small-english-r2-ONNX |
~52MB | 8k | English |
granite-97m-multilingual |
onnx-community/granite-embedding-97m-multilingual-r2-ONNX |
~98MB | 32k | 200+ languages |
bge-small-en |
Xenova/bge-small-en-v1.5 |
~34MB | 512 | English |
minilm-l6-en |
Xenova/all-MiniLM-L6-v2 |
~23MB | 512 | English |
custom |
whatever you name | varies | varies | varies |
Every preset except arctic-embed-m-v2 emits 384-dimension vectors; arctic is 768. Switching
between the 384-dimension presets never changes the stored vector width.
knowl config # interactive picker
knowl config set search.vector.preset granite-97m-multilingual
knowl config set-model onnx-community/your-model-ONNX # verifies, then downloads
The default is English-only. If you store knowledge in other languages, pick
granite-97m-multilingual.
knowl config set-model is the path for a model of your own: it checks the repository exists and
ships onnx/model_quantized.onnx, reads its pooling method from 1_Pooling/config.json, and asks
you which to use when the repository does not say. Setting search.vector.model directly has no
effect while a named preset is active — the preset decides it — and Knowl says so rather than
reporting a silent no-op.
Changing the model makes every stored embedding stop matching, so vector search falls back to
keyword-only results until knowl reindex --vectors runs. Knowl offers that rebuild as soon as the
change is saved. Nothing is ever mis-scored in the meantime: each row records a fingerprint of the
model, dtype and pooling that produced it, and only rows matching the active profile are searched.
That also means an interrupted rebuild leaves a smaller searchable set rather than a mixed one.
Existing repositories are never migrated. knowl upgrade cannot change your preset, and a
configuration written before presets existed keeps its model and its original pooling.
In a workspace, every repository must share one embedding profile, since cross-repo ranking
compares vectors directly. knowl workspace repin-embedding moves the whole workspace to the
current repository's model and lists the peers that must then reindex.
knowl init tries to warm the model cache but does not make initialization depend on a download.
Offline BM25 retrieval remains available. A normal write embeds the item only when the model is
already cached: write-time embedding never downloads a model and never fails the write.
knowl reindex --vectors is the explicit model-preparation and backfill path for existing items.
Two environment controls support offline or deliberately lexical operation:
KNOWL_SKIP_MODEL_DOWNLOAD=1 knowl init
KNOWL_DISABLE_WRITE_EMBEDDING=1 knowl decide "Title" "Content"
KNOWL_SKIP_MODEL_DOWNLOAD prevents setup from fetching the model; it does not prevent a later
enabled MCP vector query from initializing or downloading it. An enabled vector query can fail
when the model cannot be prepared. For guaranteed offline retrieval, use the lexical CLI or set
search.vector.enabled to false before calling MCP.
KNOWL_DISABLE_WRITE_EMBEDDING skips best-effort embedding during writes; BM25 still indexes the
content.
Historical retrieval and assertions
An asOf query returns historical content assertions for project items selected through their
current lexical metadata:
knowl query "sqlite persistence" --as-of 2026-01-01T00:00:00Z
This is intentionally narrower than a current query. Selection uses the item's current
title/content/reasoning and current status, then replaces only content and confidence from the
assertion valid at the requested time. It does not reconstruct historical title, category,
status, or freshness. Historical lookup is project-only and lexical: it does not use vectors,
workspace peers, session/organization/global namespaces, linked evidence, ranking explanations,
or access logging. Pair it with knowl timeline <item-id> when the history of one atom matters.
Bounded context packs
knowl context composes a handoff-sized selection instead of printing the full store:
knowl context \
--query "authentication rollout" \
--task "Review token migration" \
--token-budget 1500
The composer loads up to 30 ranked candidates from the current session and project, then prepends
all active project constraints and removes duplicate constraints from the ranked set. Constraints
are pinned first, so non-negotiable rules consume the budget before ranked facts, decisions,
architecture, or state. The budget is an estimate based on characters / 4, not a model-specific
tokenizer; callers should leave headroom for their own prompt envelope.
knowl_context does not include workspace peers or organization/global namespaces. For a peer
fact, run an explicit current knowl_query, then construct the downstream prompt deliberately.