When content becomes searchable — indexing (Desktop vs. Web)
AllFor content to appear in chat (RAG) and in search, it must be indexed. Which search backend handles that is explained in RAG & search. This article answers the other question: when indexing happens — and why it differs between Desktop and Web and across write paths.
Trigger matrix
Section titled “Trigger matrix”| Write path | Desktop | Web |
|---|---|---|
| KB editor (save / rename / move / delete) | incremental, immediate | incremental, immediate |
Chat & agent tool (create_knowledge_article / update_knowledge_article) | incremental after save | incremental after save |
| Import promotion | no incremental trigger — picked up by the periodic run | no incremental trigger — picked up by the periodic run |
| ”Re-index” (force re-index) | full run over the corpus | full run over the corpus |
“Incremental” means only the affected path is re-indexed — the content is searchable practically immediately. The editor and the chat/agent tools trigger this right after saving.
Note: Until cw-app#348, articles created via the chat/agent tool on Desktop were not indexed automatically. That is fixed — these write paths now behave like the editor.
Behavior at startup
Section titled “Behavior at startup”At application startup an “only-if-empty” gate applies: a full index runs only if the vector store is empty or absent (e.g. first launch). An already-populated store is deliberately not re-run at startup — otherwise every boot would re-embed the corpus, which is expensive and unnecessary.
Practical consequence: after the first successful index, the incremental triggers and the periodic run keep things current — not the restart.
Periodic run (cron)
Section titled “Periodic run (cron)”In addition, a periodic reconciliation synchronizes the corpus with the index (this is what picks up import promotions, for example):
- Web: scheduled via the interval
Knowledge:IndexIntervalMinutes(default: 60 minutes). → Environment variables & appsettings - Desktop: also runs since cw-app#348 — but only ticks while the app is open. Closed app = no cron. (This applies to scheduled tasks on Desktop in general. → Web vs. Desktop)
Guarantee for local vaults
Section titled “Guarantee for local vaults”Every local vault (internally “Local-typed”) marked as indexed is captured automatically — both the built-in personal vault and every user-created local vault. Concretely:
- Immediately on writes via the editor or the chat/agent tool (incremental).
- Otherwise within
IndexIntervalMinutesat the latest, via the periodic run.
Api-typed vaults (content of a peer/server) are indexed where they live and skipped locally — no double indexing.
Backend note: BM25 is always warm
Section titled “Backend note: BM25 is always warm”The lightweight in-memory BM25 file search is always warm and serves two roles (see RAG & search): when a vector backend is active it runs alongside as the second hit list of hybrid search; when no vector backend is reachable it carries search alone. In either case there is no incremental IndexPathAsync — the BM25 file search maintains itself separately from the vector index. The current backend status, and whether a vector store is active, is shown in the admin Vector store tab (visible when sqlite-vec is the active backend).
Troubleshooting: “My article doesn’t show up in search”
Section titled “Troubleshooting: “My article doesn’t show up in search””- Wait briefly / check the write path. Editor and chat/agent writes index immediately; an import promotion is only picked up by the periodic run (up to
IndexIntervalMinutes). - Desktop: Was the app closed in the meantime? Then the periodic run didn’t tick — open the app and wait briefly.
- Vault indexed? In the admin Vaults tab the vault must be marked as indexed. → Knowledge areas (vaults) & indexing
- Check the backend. Status in the admin Vector store tab; if no vector service is reachable, BM25 applies (lower result quality). → Set up Qdrant
- Force it. If the content still doesn’t appear, trigger “Re-index” (force re-index) in the admin area — a full run over the corpus. A re-index is also required after an embedding change.