Context Items
Overview
Section titled “Overview”Context items are reusable text snippets that can be attached to chats as system prompts. They support semantic search powered by pgvector embeddings, allowing users to find relevant context by meaning rather than keywords.
How context works
Section titled “How context works”When a chat is created with a context_text value, the backend inserts it as a system message at position 0:
POST /api/sessions/{session_id}/chats{ "model_name": "GPT-4", "title": "Medical Q&A", "context_text": "You are a medical assistant specializing in cardiology."}This results in the following message history:
| Position | Role | Content |
|---|---|---|
| 0 | system | You are a medical assistant specializing in cardiology. |
| 1 | user | What causes atrial fibrillation? |
| 2 | assistant | Atrial fibrillation is caused by… |
Every subsequent LLM call includes the system message, giving the model persistent instructions.
Context item management
Section titled “Context item management”Creating a context item
Section titled “Creating a context item”POST /api/context-items{ "title": "Cardiology Expert", "category": "medical", "tags": ["cardiology", "expert"], "content": "You are a cardiologist with 20 years of experience..."}When created, the backend embeds the text with whatever embedder this
workspace resolves to (see below) and stores the vector in
context_items.embedding. If the workspace has no embedder, or the one it has
does not answer, the item is created without an embedding — it still works
as a system prompt, it just will not be found by semantic search.
Listing context items
Section titled “Listing context items”GET /api/context-items?offset=0&limit=50Returns items owned by the current user plus shared items (where owner = 'all').
Searching context items
Section titled “Searching context items”GET /api/context-items/search?q=heart+disease&limit=10This endpoint:
- Embeds the query text with the workspace’s system embedder
- Performs a cosine similarity search using pgvector
- Returns results ranked by similarity score
SELECT *, 1 - (embedding <=> $1::vector) AS similarityFROM context_itemsWHERE (owner = 'all' OR owner = $2) AND embedding IS NOT NULLORDER BY embedding <=> $1::vectorLIMIT $3The embedding column is an unsized vector, so switching to a model with
a different number of dimensions needs no migration. It does need a
re-vectorise, though — see the caution below.
Which embedder a workspace uses
Section titled “Which embedder a workspace uses”Not Ollama’s, unless you chose Ollama’s. This page used to say embeddings
came from a nomic-embed-text you had to pull yourself, which was true when the
only embedder was a local Ollama and stopped being true when embedding moved to
provider:model against any configured provider.
One place answers the question — EmbedderService — and it answers it twice,
because a workspace has two embedder settings that are resolved separately:
| Setting | What it embeds |
|---|---|
| The system embedder | Context items, prompt search, the docs index |
| The Vault embedder | The research corpus (see the Vault) |
Each is stored as provider:model — novita:baai/bge-m3,
ollama:nomic-embed-text, and so on — so the provider is part of the choice,
not an assumption.
Query suggestions
Section titled “Query suggestions”A separate table query_items stores pre-populated query suggestions with embeddings. The suggestions endpoint finds semantically similar queries:
GET /api/suggestions?q=explain+transformers&limit=5Response:
[ { "id": "...", "query": "How do transformer models work?", "similarity": 0.92 }, { "id": "...", "query": "Explain attention mechanisms", "similarity": 0.87 }]Ownership model
Section titled “Ownership model”Context items have an owner field:
'all'— Shared with all users (read-only for non-owners)- User UUID string — Private to that user
RLS policies enforce this at the database level:
- Anyone can SELECT items where
owner = 'all'orownermatches their user ID - Users can only INSERT, UPDATE, and DELETE items they own
Frontend: ContextPicker
Section titled “Frontend: ContextPicker”The ContextPicker.svelte component provides a search interface for context items when creating a new chat. It calls the search endpoint as the user types and displays results ranked by similarity. Selecting an item populates the context_text field in the Add Chat dialog.
pgvector indexing
Section titled “pgvector indexing”The context_items table uses an IVFFlat index for fast approximate nearest neighbor search:
CREATE INDEX idx_context_items_embedding ON public.context_items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);