Files
template-app/modules/knowledge

knowledge

The retrieval module: named collections of the app's documents, an idempotent document-AI enablement flow (knowledge.settings.enableDocumentAi), durable index/remove jobs, and cited search over the indexed chunks.

Search backends

The worker binds one of two KnowledgeSearchService adapters per deployment (KNOWLEDGE_BACKEND, see apps/worker/src/ports.ts):

  • vectors (default): chunk locally, embed through the AI gateway, store in the bound vector store (KNOWLEDGE_VECTOR_STORE): Qdrant when a service is linked (QDRANT_URL) — the enablement flow links a managed one — or pgvector over the app's own Postgres when chosen explicitly (KNOWLEDGE_VECTOR_STORE=pgvector, on a Postgres that has the extension; the platform's default managed Postgres image does not). With neither, the module binds an unavailable search service: readiness answers unavailable with the reason, an index job fails its row with vector_store_unavailable, and the migrate job creates no vector table, so a fresh app deploys on any Postgres.
  • platform: the platform's managed documents-index service through the kit-platform Knowledge client. The service's document_ref is the object's pathname inside the project's Blob prefix and options.content_sha256 is required. The adapter hashes the job's bytes, resolves that pathname through the files module's scoped storage reference, and maps returned citations back through the same project scope. Foreign or stale references are omitted; public file views still do not expose storage keys.

Why the module is Postgres-only (no Convex profile yet)

module.convex.ts ships a fail-closed Convex binding for a future wiring, but the module is not registered in the Convex profile (convex/lib/runtime.ts), and the manifest stays profiles: ["postgres"]. The integration review (2026-10-23) kept it Postgres-only because the module genuinely cannot run on the Convex runtime today:

  1. knowledge.search is an effect procedure — every backend leaves the process (the managed service over HTTP, or embeddings through the AI gateway plus a vector store). Convex queries/mutations cannot perform network I/O; effects need an explicit action composition like the files module's action→mutation workflows, and none exists for search.
  2. The index/remove jobs must run where the platform SDKs can leave the process. The Convex binding fails closed (… must run through the Convex Node action boundary); unlike documents' documentsActions:process, no composed Node action exists for these jobs yet, so every indexing request on the Convex profile would dispatch straight into the fence.
  3. knowledge.settings.enableDocumentAi is a write whose use case performs network I/O (eligibility, quota, the Qdrant probe/link) — impossible inside a Convex mutation; it needs its own action composition.
  4. knowledge.status resolves the effect search port for the readiness snapshot, which the Convex container does not bind.

Wiring the profile means composing those Node actions first (mirror convex/documentsActions.ts); registering the module before then would ship a broken search, a broken enablement flow and always-failing jobs, not a fail-closed gate.