# Knowledge Bases The **Knowledge Base** (KB) is the RAG system: upload documents → chunk → embed (pgvector / app-level cosine for SQLite) → search via `kb_search` tool during completions. ### KB CRUD ``` GET /knowledge-bases → { "data": [KB objects], "total": N } POST /knowledge-bases ← { "name", "description", "scope", "team_id" } GET /knowledge-bases/:id → KB object PUT /knowledge-bases/:id ← partial update { "name", "description" } DELETE /knowledge-bases/:id ``` **Auth:** All endpoints require a valid JWT. `POST` additionally requires the `kb.create` permission (checked via `RequirePermission` middleware). **Scope rules for `POST`:** | Scope | Requirement | |-------|-------------| | `personal` (default) | Any authenticated user with `kb.create` | | `team` | `team_id` required; caller must be team admin (or system admin) | | `global` | Caller must be system admin | KB object (as returned by CRUD endpoints): ```json { "id": "uuid", "name": "Product Docs", "description": "Internal product documentation", "scope": "personal|team|global", "owner_id": "uuid|null", "team_id": "uuid|null", "embedding_config": {}, "document_count": 12, "chunk_count": 48, "total_bytes": 245760, "status": "active|processing|error", "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-15T10:30:00Z" } ``` > **Note:** The `discoverable` field is stored in the DB and present on > the raw model, but is **not** included in the `kbResponse` struct > returned by CRUD endpoints. It is managed via the dedicated > discoverable endpoints below. ### Documents **Upload:** ``` POST /knowledge-bases/:id/documents Content-Type: multipart/form-data ``` **Auth:** Requires `kb.write` permission (checked via `RequirePermission` middleware). Also requires a configured embedding model role — returns `412 Precondition Failed` if missing. Field: `file` (max 10 MB). Currently supported types: **TXT, MD, CSV, HTML**. Binary formats (PDF, DOCX, XLSX, PPTX) are planned but require an extraction sidecar that is not yet wired in. Returns the document object with HTTP `202 Accepted`: ```json { "id": "uuid", "kb_id": "uuid", "filename": "guide.md", "content_type": "text/markdown", "size_bytes": 12345, "chunk_count": 0, "status": "pending", "error": null, "uploaded_by": "uuid", "created_at": "2025-01-15T10:30:00Z", "updated_at": "2025-01-15T10:30:00Z" } ``` **List:** ``` GET /knowledge-bases/:id/documents ``` Returns `{ "data": [document objects], "total": N }`. **Status** (poll during processing): ``` GET /knowledge-bases/:id/documents/:docId/status ``` Returns a subset of the document object: ```json { "id": "uuid", "status": "chunking", "chunk_count": 0, "error": null, "filename": "guide.md" } ``` Status progression: `pending → extracting → chunking → embedding → ready | error`. **Delete:** ``` DELETE /knowledge-bases/:id/documents/:docId ``` Deletes the document, its chunks, and the stored file. Returns `{ "deleted": true }`. ### Search ``` POST /knowledge-bases/:id/search ``` ```json { "query": "How do I configure SSO?", "limit": 5, "threshold": 0.3 } ``` `limit` defaults to 5, max 20. `threshold` is the minimum cosine similarity score (defaults to 0.3). Returns `{ "data": [...], "query": "...", "total": N }`: ```json { "data": [ { "content": "To configure SSO, navigate to...", "source": "admin-guide.md", "kb": "Product Docs", "similarity": 0.87, "metadata": {} } ], "query": "How do I configure SSO?", "total": 1 } ``` ### Rebuild Re-chunks and re-embeds all documents. Skips documents whose extracted text is missing (would need the original file from object store). ``` POST /knowledge-bases/:id/rebuild ``` Returns `202 Accepted`: ```json { "message": "rebuild started", "total_docs": 12, "rebuilding": 10, "skipped": 2 } ``` Returns `503` if the ingestion pipeline is not configured, or `400` if the KB has no documents. ### Channel KB Bindings A channel can have KBs explicitly bound to it (in addition to any KBs coming from the active Persona or parent Project). **Get:** ``` GET /channels/:id/knowledge-bases ``` Returns `{ "data": [ChannelKB objects] }`: ```json { "kb_id": "uuid", "kb_name": "Product Docs", "enabled": true, "document_count": 12 } ``` **Set** (replace all): ``` PUT /channels/:id/knowledge-bases ``` ```json { "kb_ids": ["kb-uuid-1", "kb-uuid-2"] } ``` Validates that the caller has access to every referenced KB before setting the bindings. ### Discoverable KBs The `discoverable` flag controls whether a KB appears in the user's KB picker. Non-discoverable KBs are hidden from direct access but still searchable through Persona bindings (enterprise KB mode). **List discoverable** (for KB picker UI): ``` GET /knowledge-bases-discoverable ``` Returns `{ "data": [KB objects] }` — only KBs the user can see (personal + team + discoverable global). Uses the same `kbResponse` format as the CRUD endpoints. **Toggle discoverability:** ``` PUT /knowledge-bases/:id/discoverable ``` ```json { "discoverable": false } ``` **Auth:** Requires `loadAndAuthorize` (KB must exist, caller must have basic access). Additionally, only the KB **owner** or a **system admin** may change the flag — all other callers receive `403 Forbidden`. ### KB Resolution Chain When a completion fires, KBs are resolved in priority order: ``` Persona KBs → Project KBs → Channel KBs → Personal KBs ``` The `BuildKBHint` function assembles all applicable KBs into the system prompt, and the `kb_search` tool searches across all of them. The `kb_search` tool additionally resolves project-bound KBs and personal KBs at search time, so all user-accessible KBs are searchable even if not explicitly listed in the hint. ### Persona KB Bindings Managed via the Persona endpoints — see [personas.md](personas.md). Persona-KB binding is the primary enterprise mechanism for controlled KB access. The `auto_search` flag on persona KB bindings controls whether top-K results are prepended to context automatically (planned, see v0.28.4) vs available only through the `kb_search` tool (current behavior). ---