An AI agent that searches and finds nothing reports “not found.” The person who delegated the search hears “doesn’t exist.” Those are different claims. The first is a fact about a query: its terms, its scope, the index it ran against. The second is a fact about the world. Delegated verification fails silently in the gap between them, and the failure is invisible precisely because nothing came back to look at.
Positive findings carry their own audit trail. When an agent reports a duplicate at line 240 of a file, you can open the file and check line 240. A negative finding arrives with nothing attached: no artifact to open, no line number to visit. Just the agent’s confidence, delivered in the same fluent tone whether the search was sound or quietly broken. That makes “no collisions found,” “never sent,” and “doesn’t exist anywhere” the highest-risk sentences in an agent’s output. They are the ones you cannot check by reading what came back.
I’ve watched this fail up close. An agent, asked to verify that an event had happened, searched a chat workspace, got zero results, and told the person it was working for that the event never happened. The event was real. The search was broken in two ways at once. One query carried a display name, spaces and all, in a field that expected an ID; the API accepted the malformed filter and answered with empty results instead of raising an error. Another query returned a result set so large it overflowed to a file, and the agent never opened the file before concluding, though it likely held the answer. The agent had even run a control query to confirm the tool worked. The control never exercised the broken clause, so it confirmed nothing.
The absence that almost deleted two articles
Recently the mirror image of this failure came for my own writing: a plausible claim that something existed, when it did not. It’s the cleanest demonstration I have of the cure.
I keep a backlog of unpublished drafts in my knowledge base, and agents verify that backlog in periodic sweeps. An inventory note from one sweep flagged two files as stale copies of already-published articles and queued them for deletion under my single-source-of-truth rule. The note was easy to believe. Both files carried full publication metadata: titles, slugs, dates in December 2025, even canonical URLs pointing at my own site. Both belonged to a series I had been publishing on AI-assisted development, with published entries on the live site before and after those dates. Everything at the surface agreed: already published, safe to delete.
The claim was false. A later sweep re-checked it against primary sources instead of trusting the note, and the primary sources all said otherwise. The site’s build output did not contain those two articles. A full listing of every published post across my sites, 454 of them, did not include either article. And the site repository’s history held the disproof outright: a commit from December 19, 2025 that removed both drafts from the publish path, 2,841 lines, under the message “Move draft articles to source materials.” The two files were not stale copies of published work. They were the never-published articles ten and eleven of that series, staged for publication and then withdrawn. Word counts, since I am about to spend an article on measurement discipline: 12,424 and 3,705 by wc -w under LC_ALL=C, which is not the same number every locale will give you.
I have not found a publish-or-kill decision for either one. I want to be careful about how I say that, because it is the exact shape of claim this article exists to warn about. What I checked was the series project’s own records, the commit that removed them, and the sessions around that date. A decision could live in a conversation I never wrote down, and if it does, my not finding it means nothing at all.
Notice the shape of the disproof. It was not another search. It was bounded reads of complete artifacts (the build output, the full listing of every published post) plus one positive artifact, the withdrawal commit. That is what proving an absence actually looks like.
One more detail worth sitting with: the original note even carried its own warning label, stating it had been reported by an earlier sweep and not independently re-verified. The label changed nothing. A warning on a cached claim protects you only if something forces the re-verification before anyone acts. Without the forcing step, sixteen thousand words of finished writing get deleted as duplicates, and the record keeps saying they were published, so no future session ever asks again.
What a zero result actually is
A zero result is a measurement of your instrument, not of the world. Searches return nothing for things that exist all the time, for reasons that never announce themselves:
- The index lags. Recent items and entire content classes (thread replies are a common one) haven’t been ingested yet.
- The scope is wrong. The query ran against the wrong repository, the wrong account, the wrong host. From the outside, “no access” and “not found” look identical.
- A filter failed silently. A malformed modifier that should have raised an error was accepted and matched nothing.
- The answer was in the part nobody read: a truncated listing, clipped output, a result set that overflowed to a file.
- The terms missed the target. The thing exists under vocabulary the query never used.
Every one of these produces the same clean, confident “not found.”
The protocol
Five rules. I’ve written them into my agents’ standing instructions, and they ship as part of synthesis-grounding-discipline, an open skill (a reusable instruction module for AI agents) in my public collection. They are for the human reviewing agent output as much as for the agent itself.
Scope every negative claim to the instrument. The honest form is “this query, over this scope, returned zero.” Never “it doesn’t exist.” The wording matters: the scoped claim invites the follow-up question, and the unscoped one forecloses it.
Establish absence with a bounded direct read. Searching is not how you prove absence. Reading is. Go to the primary source where the thing would be if it existed (the specific channel, the specific directory, the specific log) and read it directly, with explicit bounds. The claim that results is “not present in this channel between March 3 and March 10,” and the bounds are part of the claim. An absence claim without stated bounds is a search that stopped early.
Run a positive control through the same mechanism. Before trusting any zero, make the same instrument find something you already know exists, of the same kind, through the same query path, exercising the same clauses. The chat-workspace agent failed exactly here: its control exercised a healthy query path and left the broken clause untested. A control that skips the suspect component validates nothing.
Re-run modifier-bearing queries bare. Any query carrying filters, field modifiers, or date restrictions gets re-run without them before its zero is believed. If the bare query finds the target and the modified one does not, you have found the failure, and it was never in the world. I treat every filtered zero as unproven by default; the re-run costs seconds.
Treat truncated output as a pointer, not content. “Showing 50 of 1,244,” a trailing ellipsis, results written to an overflow file: these tell you where to look next, never what is true. Open the source before any conclusion depends on what a listing did not show.
Protocol, not vigilance
The instinct after a near-miss like mine is to resolve to be more careful. That resolution is worthless, for a specific reason: a false “not found” reads exactly like a true one. There is no tell for care to catch. Vigilance works against failures that look wrong. This failure looks right.
So the fix has to be structural, and it belongs in two places. In the agent’s standing instructions, so negative findings get built to the standard rather than repaired to it afterward. And in your own acceptance criteria as the delegator: a negative finding is complete when it arrives carrying three things. The instrument: what was queried, with what terms, over what scope. The bounds: what was read directly, over what window. The control: proof the mechanism finds things of this kind. A “not found” without those three is not a finding. It goes back.
The burden of proof here is asymmetric, and the asymmetry is the point. Establishing that something happened takes one sighting. Establishing that something did not happen requires showing you looked everywhere it would have left a trace, with an instrument you’ve demonstrated can see it. Every retrieval-backed agent hands you claims of the first kind dressed as claims of the second, and almost none of the workflows built on those agents instrument for the difference.
Two finished articles went back into my publish queue because a protocol, not anyone’s alertness, refused to let a plausible claim stand unproven.
