← all archetypes
rag chatbot
Fill {{SCENARIO}} and {{DOMAIN}}, copy, paste into your coding agent.
# Kickoff — RAG Chatbot
Paste everything below into your coding agent after filling {{SCENARIO}} and {{DOMAIN}}.
---
You are working in this repo: Next.js 16 App Router + TypeScript + Tailwind, Clerk auth
(already wired in `middleware.ts` + `ClerkProvider`), Drizzle + Neon Postgres (schema
`perficient` — see `lib/db/schema.ts`, `runs` and `documents` tables exist), Anthropic SDK
with `ANTHROPIC_API_KEY` in env. The app is already deployed on Vercel; keep it deployable
(no native deps, no filesystem writes at runtime).
Build a RAG chatbot for this scenario: {{SCENARIO}} (domain: {{DOMAIN}}).
## Order of work — AI layer first, UI polish never
1. **Synthetic corpus.** Script `scripts/generate-corpus.ts`: one Claude call (model
`claude-sonnet-4-6`, streaming) generates 10-12 realistic {{DOMAIN}} documents
(250-400 words each) as structured JSON. Requirements that make retrieval demonstrable:
at least 2 docs dense with exact identifiers (codes/SKUs/tickets), 2 docs that say the
same thing in different words, and 1 topic deliberately absent (refusal demo). Insert
into the `documents` table chunked to ~250 tokens per row (word-count/0.75 heuristic is
fine), with `meta: { docId, chunkIndex }`.
2. **Retrieval.** Already half-built — use it: `lib/embed.ts` has `embed()` (OpenAI
text-embedding-3-small primary / Gemini backup, 1536 dims, normalized)
and `searchDocuments()` (pgvector cosine search with HNSW index, user-scoped). Embed
chunks at ingest into `documents.embedding`. Add keyword scoring over the same rows and
fuse both rankings (reciprocal rank fusion, k=60) for hybrid. Take top-5 into the
prompt. Log every query to `runs` (archetype "rag").
3. **Grounded generation.** `app/api/ask/route.ts`: system prompt — answer ONLY from the
numbered context passages; cite like [1][2] on every factual claim; if the passages
don't contain the answer, say exactly "I can't answer that from the documents" and name
what's missing. Return the retrieved chunks alongside the answer.
4. **UI** at `/app`: question box, answer with citations, and a "sources" panel showing
the retrieved chunks with scores — retrieval must be VISIBLE, that's what gets asked
about. Include 3 example-question buttons: one exact-identifier, one paraphrase, one
off-corpus (refusal).
5. **Mini eval.** `scripts/eval.ts`: 5 question→known-source pairs generated alongside the
corpus. For each: is the right doc in the top-5 (Recall@5)? Print a table. This is the
"how do you know it works" answer, runnable live.
## Constraints
- Working software over polish. Milestone after each step so I can demo mid-build.
- Every model call: `max_tokens` explicit, errors caught, degrade gracefully (retrieval
keeps working if generation fails — show sources with no answer).
- No hardcoded secrets. All Claude calls through one `lib/ai.ts` module.