RAG Pipeline
Deskly reuses the base template's upload → chunk → embed → retrieve pipeline unchanged, with one addition: retrieval is scoped per bot, not per account.
Scoping
The documents table has a nullable bot_id column. A document uploaded against a specific bot (from /dashboard/bots/[botId]) is only ever retrieved for that bot's conversations — a visitor talking to Bot A never sees content uploaded to Bot B, even if both bots belong to the same account.
Existing per-account documents from the base template's dashboard chat feature have no bot_id and are unaffected; they continue to work exactly as before for that (non-widget) feature.
What happens on each widget message
In /api/widget/chat/route.ts, once the bot and rate limits are resolved:
const { data: botDocuments } = await supabase
.from("documents")
.select("id")
.eq("bot_id", bot.id)
.eq("status", "completed");
const documentIds = (botDocuments || []).map((d) => d.id);
if (documentIds.length > 0) {
const relevantChunks = await retrieveRelevantChunks(
message,
documentIds,
RAG_CONFIG.retrieval.defaultTopK,
supabase
);
// ...chunks get joined and injected into the system prompt
}
retrieveRelevantChunks accepts an explicit list of document IDs to search within, plus an optional Supabase client — the widget path passes the service-role client since there's no visitor session, while the dashboard chat path uses the caller's session-bound client.
If a bot has no documents
Retrieval is simply skipped — the bot falls back to its system_prompt (or a default prompt from RAG_CONFIG) with no injected context. This means a bot can answer general questions from its system prompt alone even before you've uploaded anything, which is useful for testing the embed before content is ready.
Uploading documents
Upload flow, chunking strategy, and embedding provider are unchanged from the base template — see the upload UI in /dashboard/bots/[botId]. Supported formats and size limits are the same defaults as the base template; tighten them per your own risk tolerance before opening bot creation to untrusted users.
Related
- Architecture for how
bot_idfits into the overall data model - Abuse Protection for what stops a visitor from running up an owner's retrieval + generation costs