AI Assistant
A conversational assistant that answers questions over a tenant's docs and OpenAPI using agentic retrieval with Claude — not single-shot RAG.
A conversational assistant that answers questions over a tenant's docs and OpenAPI using agentic retrieval with Claude — not single-shot RAG.
The AI assistant is a slide-out chat panel that answers reader questions from a tenant’s own docs and OpenAPI spec. It is an agentic “Ask Assistant”: the model navigates the docs to find answers, cites its sources, and admits when it doesn’t know.
A first slice is built: an agentic /api/assistant route (the Vercel AI SDK calling
searchDocs / readPage / listPages / searchApi tools), the slide-out panel,
the navbar Ask Assistant button, the Cmd/Ctrl-I shortcut, and the ?assistant= deep
link. A dedicated Sources citation UI, multi-modal attachments, and an embeddings-backed
searchDocs are in progress. The model is configurable (see Model & routing below) —
without a configured AI route the endpoint returns a graceful 503 and the panel is
unavailable.
A naïve docs bot does one top-k vector lookup and stuffs the results into a prompt.
Papervine’s assistant instead lets the model decide how to search, iterating with tools
until it can answer — effectively a virtual filesystem over the vector store that the model
navigates with filesystem-like tools.
This is cheap to build because the tools are thin wrappers over capabilities Papervine already has — the content loader, the navigation tree, search, and the OpenAPI pipeline:
User question ──▶ /api/assistant (Vercel AI SDK streamText, configured model)
│ loop: the model calls tools until it can answer
├─ search_docs(query) → search index (titles / headings / body)
├─ read_page(slug) → full MDX for a page
├─ list_pages() → the navigation tree
└─ search_api(query) → OpenAPI operations
▼
streamed answer + Sources (cited page hrefs / #anchors)
Why tools instead of pure top-k:
Embeddings are optional for v1. Agentic search runs on the keyword index first — the model
iterates to compensate. A pgvector semantic backend can be added behind search_docs
later without changing the tool contract.
The model and how it’s reached are configuration, not code — set via environment,
resolved in one place (src/lib/ai-model.ts) that both the assistant and the editor agent
use. Papervine isn’t tied to any single provider:
PAPERVINE_AI_MODEL — a provider/model id (e.g. anthropic/claude-haiku-4-5,
google/gemini-3.1-flash-lite, openai/gpt-5-nano).AI_ROUTING=gateway (default) — route through the Vercel AI Gateway: one key
(AI_GATEWAY_API_KEY, or Vercel OIDC when deployed there) unlocks nearly every provider
and model without per-provider SDKs.AI_ROUTING=direct — bypass the gateway and call a provider’s SDK directly with
that provider’s own key (ANTHROPIC_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY,
OPENAI_API_KEY). Use this to bring your own keys or avoid the gateway entirely.ollama/, lmstudio/, or local/ model id runs
against your own hardware and pays nobody. See
Local AI models.Individual surfaces can override the model: PAPERVINE_AI_MODEL_AUTOMATIONS applies
only to automation runs, which write documentation that lands
in Git — worth a stronger model than the high-volume assistant needs. Anything without an
override falls back to PAPERVINE_AI_MODEL.
Because the assistant is agentic (it makes several model calls per question), pick a model
that’s both capable at tool use and not rate-limited by your provider tier. See
.env.example for the documented defaults and trade-offs.
The page the reader is currently on is injected into the system prompt as starting context, so a question like “how do I do this?” resolves locally without the model having to first re-discover where the reader is.
The chat UI is built on AI Elements (shadcn/ui + Vercel AI SDK components) rather than hand-rolled, and themed with the same CSS variables as the docs site so it matches the surrounding theme:
#anchors under each answer, navigable.The panel slides out from the right (expand + close), opened by an Ask Assistant button in the navbar, and carries the disclaimer “Responses are generated using AI and may contain mistakes.”
The assistant offers several invocation surfaces:
The navbar button opens the panel.
The keyboard shortcut. Cmd/Ctrl-K stays search — the two surfaces
are distinct.
Highlight text on a page to ask about the selection.
?assistant=YOUR_QUERY on any page auto-opens the panel and asks the question — used for
“Ask AI” links and shareable answers.
The assistant retrieves over the same content the rest of the site indexes:
noindex pages are excluded by default. Setting docs.json’s
seo.indexing: "all" includes them (Papervine already parses hidden / noindex
frontmatter).The assistant is not confined to the docs panel:
/api/assistant is an SSE endpoint (AI SDK data stream), with a compatible alias path
so existing integrations port over.<script> snippet — see the
embeddable widget; Slack and Discord bots are planned.search_docs / read_page / list_pages /
search_api are exactly the tools a generated read-MCP exposes, so the in-docs assistant
and the MCP server are one implementation behind two transports.Docs owners manage the assistant from a dashboard page (Automate → Assistant; see the control plane overview). The top of the page shows three overview cards — Total questions, Answered properly, Not answered — each with a month-over-month delta, plus a link through to Analytics.
Settings are grouped:
docs.json, so it takes effect
instantly without a Git commit./api/assistant endpoint to limit automated abuse and runaway token cost.Suggestions).Published behavior — starter questions, deflection email + help button, search domains
— is version-controlled in docs.json’s assistant block; the dashboard edits it through
the authoring layer so it stays in Git. Operational state —
the enable toggle, CAPTCHA, credits, plan — lives in the database for instant effect.
An operator running their own deployment reads it all from docs.json + environment
variables, no dashboard required.