Back to News & Insights
Artificial Intelligence September 21, 2026 · 7 min read

An Agent That Counts My Receipts, Not My Claims

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

An Agent That Counts My Receipts, Not My Claims

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

My ledger says three outside engineers found the same defect. Ask the agent how many locatable receipts support that row and it says one.

Finding B8 has 1 locatable comment (3ee98 by Pushpendra). Although three outside finders are recorded, the receipts for Vinh Nguyen and quashudev were not found in the comment trees searched.

It does not turn three recorded names into three verified receipts. The dataset stores finders and receipts as different things, and the agent is not permitted to add them together.

It does that over a public Sanity record of 120 documents: 74 articles, 14 findings, 10 people, 3 patches, and 19 claims. The claim documents separately store asOf, status and expiryStatus, rather than asking the model to reconstruct those distinctions from prose.

Three things it will tell you about its own author: the fix for finding B1 is not merged into origin/main — it reports inMain: false of 14 findings, 12 were raised by the 8 outside engineers and 2 are internal (one raised by my coding agent, recorded as Ka'el, and one by an internal audit). Two are implemented; twelve are not it cannot see what happened to that branch after the record was built, and says so

https://ask-the-record.vercel.app — no login, no user-supplied key, five buttons.

Measured answers on this deployment ran 13.8–33.8 seconds across the five questions — the raw timings are in evidence/web-latency-2026-09-21.json. Evidence-bearing answers must survive a retrieval check: a substantive verdict returned with no successful read is marked a contract violation. INSUFFICIENTEVIDENCE is allowed to abstain without pretending a source was retrieved. Retrieval or auth failures return an error instead of an answer. Every answer that renders cleanly is required to carry five fields:

Press the Kubernetes button and it returns INSUFFICIENTEVIDENCE and no number, because the Knowledge Base evidence available to that question does not establish a count. It is not claiming the dataset could never yield one. On the graded run, the agent abstained rather than supplying a number; the validator does not independently establish that every abstention contains no unsupported claim.

The page also checks its own output. If an answer is missing a required field, has empty uncertainty, or fails the citation requirement for the instrument that produced it — a URL for dataset answers, an entry path and the Knowledge Base id for Knowledge Base answers — the page shows the violation instead of rendering the answer cleanly. It checks citation presence and syntax. It does not resolve URLs, and it does not yet prove that every emitted citation belongs to the evidence actually retrieved.

The Python harness and the serverless agent use only the Python standard library. The Studio uses Sanity's normal React and TypeScript dependencies.

The schema makes the distinctions representable; the endpoint instructions require the agent to keep them separate; the harness independently enforces retrieval, required output fields, citation syntax and named-object guards around the answer. It does not yet re-verify the returned values against the document field by field — the instructions carry that, not the validator.

One honest wrinkle in my own design: the response VERDICT is a single enum that mixes claim state, finding state, expiry metadata and retrieval outcome. That is a presentation-level classification. The underlying status and expiryStatus stay separate in the dataset, and the graded claim lookup reported both separately in its answer text — but the validator does not yet guarantee that separation for every future answer, and a stricter contract would split the output the way the schema does.

Three schema choices do the work: status and expiryStatus are separate. A claim can be standing and noexpiryset at the same time. noexpiryset means nobody dated it — not "permanently true," not "expired." Collapsing those two facts into one is how a record quietly rots, so the schema represents them as separate fields instead of forcing one value to stand for both. A finding has commentOn and writtenUpIn. Where someone raised a defect and where I wrote it up are different articles. pm25coder found B1 in the comments of one article; it was written up in another. One field would have glued the wrong attribution to the wrong post. patch.inMain is a boolean. Public is not merged. All three recorded patches are pushed and none is in main. Asked about B1, the agent reports inMain: false rather than inferring merge state from the branch being public.

I built this on a Knowledge Base first. It handled the four prose-routed frozen questions in the graded run. But I could not reliably recover a specific claim's status and expiry from the indexed representation, and the measurement shows why:

The values existed in the indexed prose but were not bound to claim-ledger-population. A prompt cannot make that binding reliable when retrieval did not preserve it, so I routed that question shape to GROQ — which is what Sanity recommends when the schema already says where to look.

I did not grade my own work here. Independent review means separate, owner-assigned AI reviewer sessions that did not implement the candidate — not outside human testers. The first live graded run they carried out exposed the wrong-object failure on exactly that question. Synthetic breaker controls then found more: failed retrieval could reach the model, unsupported answers could exit zero, parts of the output contract were not enforced, and the contracted tool-discovery step was missing. The VERDICT.md in evidence/ is a BLOCK and it stays there.

So the agent routes by question shape. Four of the five frozen questions — B1 attribution, B1 merge state, B8 receipts and Kubernetes — stay on the Knowledge Base. Only the exact claim-field lookup routes to GROQ.

Want to discuss this further?

Book a free strategy call with our team to see how these insights apply to your specific business goals.

Book a consultation