Inspiration
Watson is shot in the leg in one Sherlock Holmes book and in the shoulder in another. Conan Doyle wrote both. Nobody caught it for a century.
It happens to every long story. Nobody holds nine books in their head, but the audience always notices.
What it does
CONTINUITY reads a whole script and records everything it states: one row per fact, each carrying the sentence it came from. Then, wherever one person holds two different values for the same thing, it asks: can both be true?
The model proposes. The database confirms or refuses. Every finding arrives with both quotations and the line each came from, so you can disagree with it.
How we know it finds rather than remembers
Every model has read Sherlock Holmes. So we wrote a second script: The Long Quiet, eight episodes written from scratch after the models' training cut-off, with six contradictions planted on purpose and an answer key in the repo.
It finds three of the six every time, and four more we hadn't planted. One of its eight findings is a false positive, and the interface shows the surrounding dialogue so you can see that yourself.
How we built it
Gemini 3.7 Flash extracts, resolves names, and judges each pair. Everything
lands in ClickHouse Cloud, reached at runtime through the official
mcp-clickhouse server. A query agent built with Google's Agent Development
Kit on Vertex AI Agent Engine turns questions into SQL, and shows you the
SQL it wrote. The site runs on Cloud Run, credentials from Secret
Manager.
The judge is not an agent, deliberately: a pair in, a verdict out, no tools and no iteration. The pipeline is reproducible because it isn't agentic.
What ClickHouse does that another database wouldn't: materialized views fire on insert, so a contradiction surfaces as you write instead of waiting for a batch. Try it on the site. Recursive SQL turns 1,285 stated links into 2,885 ordered pairs. And every screen shows the SQL it ran with the rows it scanned.
We ran ClickHouse's own 28 Agent Skills rules against our schema and fixed what
they caught: query safety limits, LEFT ANY JOIN, lightweight DELETE.
We also attacked our own surfaces: 13 SQL injection attempts, 13 blocked; 5 prompt injections, 0 dangerous queries produced.
Challenges
The judge isn't deterministic, even at temperature 0. We measured it. So every model comparison runs several times, and the findings that appear every time count for more than the average.
A badge that always appears is decoration. "Verified in source" used to show whenever a quotation existed. Now the server searches the file first, and when it can't find the sentence the badge is absent.
Prompt wording alone isn't a guarantee. The agent counted 1,524 facts where the answer was 1,526, because it filtered on a raw name instead of joining the identity map. Rewriting the rule in its negative form fixed it: a prohibition is something a model can check its own output against.
What we learned
Retrieval is the wrong tool. RAG finds what's similar, and a contradiction isn't similar to anything. You can only spot one by holding two statements side by side and asking whether both can stand: a database question, not a search one.
And a number without a ruler is an impression. We once called our entity resolution "good" by looking at it. Scored against ground truth it was 3 of 10.
Built With
- agent-development-kit
- clickhouse
- clickhouse-cloud
- cloud-run
- css
- docker
- flask
- gemini
- google-cloud
- gunicorn
- html
- javascript
- mcp
- model-context-protocol
- python
- secret-manager
- sql
- vertex-ai
- vertex-ai-agent-engine

Log in or sign up for Devpost to join the conversation.