charles forson

Verifying an agent's output cannot catch a broken measurement underneath it

4 min read

Three back-to-back mobile performance runs against one unchanged URL came back fifty-five, fifty-five and forty-three. Nothing about the site moved between them. The Red and Amber boundary on my scorecard sits at fifty, and mobile speed is the primary dimension there, capable of forcing an overall Red on its own. So the headline grade on that business, the first thing a prospect reads in a report, was decided by which of three identical runs happened to execute.

Everything I had built to make that report trustworthy was pointed at the writing. The synthesis stage that turns collected numbers into findings had a closed claim taxonomy, structured pointers back into the evidence, and a deterministic validator that would refuse to ship a finding with nothing to cite. That machinery worked. What it checks is whether each sentence is faithful to the snapshot it was drawn from, and the snapshot was where the damage was.

The same run turned up two more of that shape. The social collector reported an X account for a business that has never had one, because the handle pattern matched unanchored against x.com and fired inside a Wix telemetry URL that sits on every site built on that platform. One in twenty-two of the sites I fetched carried it. Separately, a collector script I had proven the day before, seven dimensions in under a minute, was referenced by nothing: a grep across every skill, rule and agent spec returned zero hits, while the live path ran an older, slower workaround that hedged on API keys which had been sitting in the environment the whole time.

Verification that reads the output cannot catch a corrupted input, and that gap is structural rather than a lapse in my own harness. When I went looking for prior art on checking whether generated text is faithful to its evidence, the whole family behaves the same way. RAGAS, TruLens, ARES, AlignScore, MiniCheck and the vendor groundedness services all take the retrieved context as ground truth and score consistency against it. A corrupted evidence base is out of scope for the field by construction. So a validator built on that assumption waves through a fabrication already laundered into the snapshot, and it does so with a real, resolvable pointer attached, which reads worse to a customer than a confident claim with no citation at all.

The fix has an established name, just not in the LLM literature. Per-field provenance is taint tracking borrowed from software security: sources, sinks, sanitisers, and every value carrying a marker into the synthesis prompt saying what established it. A handle pattern-matched out of a telemetry URL and a handle returned by a named first-party API call are different kinds of fact, and my snapshot stored them identically. The caveat is sharp. A marker is worth only as much as whatever assigns it, so provenance assignment has to be rule-based. Let a model decide what counts as verified and the confidently wrong step has moved one stage earlier rather than gone away.

For the noisy measurement itself, Google's own Lighthouse variability documentation already says to threshold on aggregate values rather than single results, and that the median of five runs is twice as stable as one. Median-of-N is half the answer. The other half is an explicit borderline band around the cut point in place of a bare inequality, and that pattern turns up independently in monitoring as hysteresis and flap detection, in exam standard-setting as scores within one standard error of a boundary, in clinical chemistry as the grey zone, and in record linkage as the clerical-review band between match and non-match. Four unrelated disciplines reaching for the same shape is about as strong as design evidence gets.

The third fix corrected me in the most flattering direction. A small golden set of graded fixtures felt like it would tell me how accurate the pipeline is. The arithmetic says otherwise: twenty-five items scoring eighty-four percent gives a ninety-five percent interval running from sixty-five to ninety-four percent, which spans materially unreliable to very good. What twenty-five items does well is catch a gross regression, with about eighty percent power against a seventeen-point drop and close to a coin flip at ten. Treating it as a tripwire is sound. Reading an accuracy figure off it is the same false confidence as eyeballing outputs that look fine.

None of this retires the human at the end. A rule set assembled from failures I have already seen is reactive by construction, blind to a new failure shape until someone finds one in production and writes the rule. What the work did change is the order. Stabilise and mark the measurements, then grade, then check the writing. Building the claim validator first felt like the rigorous move, and it was rigour spent one layer too high. A checker downstream of a coin flip inherits the coin flip.

Building the same things I write about — see what I'm working on in Projects, or get in touch.