cd /news/ai-agents/i-made-my-agent-prove-every-quote-ag… · home topics ai-agents article
[ARTICLE · art-137773] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

I made my agent prove every quote against the source document

A developer built TSB Oracle, an agent that answers car repair questions from NHTSA public records while verifying every quoted sentence against the exact document it cites. The project, tagged v1.0 on GitHub, uses a Sanity content model of bulletins, claims, contradictions, and decisions, with Context MCP tools plus custom GROQ-backed applicability checks, and surfaces unresolved conflicts rather than guessing. The demo dataset covers unexpected automatic emergency braking on the 2017–2022 Honda CR-V, where an open federal investigation (EA24-002) extends beyond the model years covered by Honda's software update 26-091.

by read5 min views1 publishedSep 23, 2026

This is a submission for the Sanity Challenge, Path One: Ship an Agent That Queries Real Content

My agent kept citing real documents for words those documents never contained. Not hallucinated quotes: real sentences, attributed to the wrong source. So it now proves every quoted phrase against the exact document it cites, straight from the dataset, and marks the ones that fail.

TSB Oracle answers car repair questions from the public record, and shows you where that record contradicts itself.

Ask why your car brakes on its own and you will find a service bulletin naming a cause, a revision of that bulletin a week later that quietly drops the sentence, a federal investigation covering more model years than the fix does, and owners saying the dealer called it normal. All of it is true at once. A search engine hands you whichever page ranks best, and a chatbot picks one and sounds certain.

This agent retrieves all of it. Every sentence carries the NHTSA id it came from, quotes are checked against the document they are attributed to, and when two sources disagree about your exact car, the disagreement is put in front of you instead of resolved by guesswork.

The dataset is one vehicle and one system, imported from NHTSA's public API: unexpected automatic emergency braking on the 2017 to 2022 Honda CR-V. The conflict at the centre of it is real. NHTSA's investigation EA24-002 covers 2017 to 2022. Honda's software update 26-091 stops at 2019 and excludes the LX trim. A 2021 owner is inside an open federal investigation with no published remedy, and nothing in the record says one is coming.

What the agent does with that:

The demo car is a 2021 Honda CR-V EX. The vehicle in the header is editable, so these all work:

Vehicle Ask What it shows
2021 CR-V EX My CR-V brakes hard on its own with nothing ahead. The dealer says that's normal. Is there a fix? the coverage gap, already settled by review
2018 CR-V LX Does Service Bulletin 26-091 apply to my car? a trim exclusion
2018 CR-V EX Honda and NHTSA disagree about what causes the braking. Which applies to my car? an open contradiction, and a proposal
1994 Civic del Sol Are there any recalls for this car? no sources, and it says so

While it works, it shows what it is reading rather than a spinner:

Every question is a live model call against my own API balance, so if the demo stops answering, that is why.

github.com/pyarchana/tsb-oracle, tagged v1.0.

The content model. Four types do the work. tsb is a source document, a bulletin, dealer message, investigation or owner complaint, with its model years, excluded trims and a link to the NHTSA record. claim is one statement with the exact words it rests on. contradiction joins two claims that disagree and explains why. decision records how a contradiction was resolved, who resolved it, and whether a person has approved it yet.

What I pointed Context at. The Knowledge Base is built from the tsb and claim types, with the claim's source reference unfolded so each claim carries its document's id. I deliberately left contradiction out. If I had included it, the Knowledge Base would have read my conflicts back to me. Excluding it meant Context had to find disagreement in the sources on its own.

The tools. The agent gets initial_context and knowledge_base_read over the Context MCP endpoint, plus two of my own:

check_applicability runs GROQ over the dataset and returns which documents cover this year, make, model and trim, which contradictions touch them, and whether any has been settled. It answers questions the Knowledge Base cannot: is this trim excluded, is this VIN in range, is this argument already over.record_decision writes a proposal, never a settled decision. So Context supplies the wording and GROQ supplies the structure. The Knowledge Base tells the agent what a bulletin says; the dataset tells it whether that bulletin applies to the car in front of it.

What the Knowledge Base build caught. Four issues, all real. NHTSA's own summary of bulletin A18-006 writes "OTC" where the codes are DTCs and "MIO" where the display is the MID. Two entries merged NHTSA's complaint counts with its per-vehicle totals: 31 crashes alleged in complaints against 47 across all reports, 50 injuries against 93. I resolved each in favour of what the source actually supports, and resolutions carry into every later build.

What it did not catch, and why I left that alone. None of my curated claims conflicted. Every one of them says who made the statement it records, so "version 1 of the bulletin says X" does not flatly contradict "version 2 says Y". I could have written an unattributed claim to make the issues feature fire. Staging a conflict to demo conflict detection would have proved nothing.

Why the knowledge base cannot back a quote I assumed Knowledge Base entries could back up a quotation. They cannot, and should not. An entry is a synthesis: it merges several documents into one topic, paraphrases them, and attaches footnotes. That is right for retrieval and wrong for quoting, because a phrase can appear in an entry that no source ever used. So the app checks quoted words against the dataset's verbatim copy of the cited document instead. On a live run it caught the agent quoting version 1 of a bulletin and citing version 2, which is exactly the kind of mistake that sends someone to a dealer asking for the wrong repair.

Persistence. When the agent proposes a resolution, it writes a decision with status proposed. A person opens it in the Studio and approves or rejects it. Approving flips the decision and its contradiction in one transaction, so the two can never disagree about whether a question is settled. From then on, the next person asking about that vehicle gets the settled answer and its rationale instead of the argument.

That review step exists because the demo is public. Without it, one conversation could settle a question for everyone who asks after it.

Project ID: e72p6sym, dataset production, which is public.

A live query against it, no token needed:

https://e72p6sym.api.sanity.io/v2026-09-01/data/query/production?query=*[_type=="tsb"]{tsbNumber,title,sourceType,status,modelYears}

The Studio is embedded at /studio in the app, and the schemas are in sanity/schemaTypes.

── more in #ai-agents 4 stories · sorted by recency
── more on @tsb oracle 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-made-my-agent-prov…] indexed:0 read:5min 2026-09-23 ·