This is a submission for the Sanity Challenge, Path One: Ship an Agent That Queries Real Content
What I Built
Next.js changes fast and the old answer keeps ranking. fetch stopped caching by default, params became a Promise you await, next/font replaced @next/font, Turbopack became the default bundler. Ask a plain model "does the App Router cache fetch by default" and it will confidently say yes, because that was true in Next.js 14 and most of its training data still says so.
So I built Still True, an agent that answers Next.js questions only from a Sanity Context Knowledge Base and refuses to give you a stale or contradicted answer. When two sources disagree on the same fact it shows both with their sources and says which one is current. When the base does not cover something it says so instead of guessing.
The part a keyword search cannot do is the whole point. Keyword retrieval returns whichever document mentions "fetch caching" first. This agent returns the claim the structured content marks as current and it surfaces the disagreement instead of burying it.
Demo
Live agent: https://still-true.vercel.app/ask
The home page runs a live head to head: the same MiniMax model with no knowledge base on the left, the grounded agent on the right. Try these.
- "Does the App Router cache fetch by default?" The plain model says yes, cached by default, which is the Next.js 14 answer. The grounded agent says no. Not cached by default. Opt in with
cache: 'force-cache'. The board shows the two sources that disagree with the reason sitting on the edge between them. - "In Next.js 16 are params and searchParams a Promise I must await?" It answers yes, shows the
awaitcode and notes that Next.js 14 was synchronous and is now deprecated. - "Are all my .env.local variables available in the browser?" It answers only the
NEXT_PUBLIC_ones and flags the source that claims otherwise.
Every answer lists the Knowledge Base entries it read, so you can see it is grounded and not improvising.
Code
Repo: https://github.com/zkasuran/still-true
The agent is a small tool-use loop that hands retrieval to the model over three tools on the Sanity Context client.
-
list_knowledgereturns the Knowledge Base outline, every entry path with its title and scope. -
read_entriespulls the full cited body for the paths the model picks. -
list_conflictsreturns the open conflicts Context raised.
Retrieval is structure driven, not a blind top-k. The model reads the outline first, picks the entries that match, then widens only if the evidence is thin. Every answer returns its toolTrace. For the fetch question it is list_knowledge, read_entries(1), list_conflicts, so you can see it read one entry rather than dumping the base. When the outline has nothing on topic the agent abstains with a plain "Not covered" instead of hallucinating. It ships two ways in the repo, a standalone CLI in agent/ and a server route at /api/ask behind the chat UI. It talks to any OpenAI-compatible model through one env var. The public routes are rate limited and same-origin guarded because they cost money to run.
How I Used Sanity
This is built on Sanity Context and a Knowledge Base. The contradiction handling is Context's own feature, not something I bolted on.
I created the Knowledge Base and imported real Next.js source material, deliberately including pairs that disagree: current guidance beside the older guidance it replaced, plus an official recommendation beside a contradicting community one. Sanity Context distilled those sources into a small set of cited entries and did two things I leaned on.
- Reconciliation. Where sources described the same fact across versions, Context merged them into one timeline-aware entry, so the agent can say the current way is X while the old way was Y.
- Conflict raising. Where two sources asserted the same fact incompatibly with no version to reconcile them, Context raised a conflict into its Issues queue with both claims and their sources. That is the fetch-caching case the demo shows.
The whole pipeline runs headless from the CLI: create the base, import sources, build. The agent reads it through the Sanity Context client (entries.list, entries.get, issues.list), the same content Context serves to an MCP endpoint. It also runs against a live Context MCP URL through one env var. Because the base is small the agent can read every relevant entry, so it never misses the one that matters.
Sanity Project Details
- Project ID: mx12urdz
- Public dataset: production
- Knowledge Base: kbOSaaWFy5yI ("Developer Facts That Drift")
The same project backs the Path Two board, which renders the underlying claim graph. The claims, sources and typed edges live in the public dataset and are queryable over GROQ.
Agent Session
AI assistance (Claude Code, Anthropic) was used to build this. The design, the verification and the decisions were mine. The agent runs on MiniMax-M3 and its answers are grounded in the Sanity Knowledge Base, verified live at the URL above.


Top comments (0)