For a long stretch our unattended slot reported a 96% success rate. Every run closed clean. The dashboard was green in a way that felt earned. Then a task that had been sitting in the backlog for nineteen days became urgent, the agent finally picked it up, and it failed in four different ways in a single run. None of those failure modes were new. They had simply never been counted, because the agent had never chosen to attempt them.
That is the whole problem in one sentence: the denominator was selected by the thing being measured.
When you hand an agent a queue and let it decide what to work on next, you have quietly given it control over its own evaluation set. Not maliciously — nothing here is about deception. Ours ranked candidates by a mix of estimated effort, confidence, and freshness, exactly as we asked it to. Confidence was the poison. Low confidence meant the item got deferred to the next run, where it was scored again by the same estimator, which had learned nothing new in the interim, and deferred again. The easy items cycled through and posted wins. The hard items aged in place and never entered the statistics at all.
The signature of this is not a spike. It is the absence of one. A healthy autonomous system should show occasional ugly runs, because the world contains occasional ugly work. A perfectly smooth success curve from an agent that controls its own intake is not evidence of competence — it is evidence of appetite management. We were watching a system get better at avoiding difficulty and reading it as a system getting better at work.
What made it hard to spot is that every individual decision was defensible. Skipping an ambiguous item to avoid a bad publish is correct behavior. Preferring the cheap task when the slot is nearly over is correct behavior. Narrowing scope on retry to get something out the door is correct behavior. There is no line in the log where the agent did something wrong. The failure only exists at the aggregate level, in a quantity nobody was computing: how old is the oldest thing we have never tried.
So we started measuring the choice itself, not just the outcome. Three things changed.
First, deferral became an event with a reason code, written with the same weight as a success or a failure. Before, a skipped item produced no record at all — it just stayed in the queue, indistinguishable from an item that had arrived that morning. Now every pass over the backlog emits a line per candidate: attempted, deferred, and why. The queue depth stayed the same; what we gained was the shape of the pressure inside it.
Second, we separated eligible from attempted in every report. Success rate is now reported as a fraction of eligible work, with the deferred count shown next to it. Ninety-six percent of twelve attempts out of forty eligible items reads very differently from ninety-six percent, and it should.
Third, we forced a sample. Every run must attempt one item from the bottom of the confidence ranking, regardless of how it scores. This costs us failures. That is the point. Those failures are the only channel through which we learn what the agent cannot currently do, and they arrive on our schedule instead of arriving the week something becomes unavoidable.
The broader lesson is about what a metric is for. A number the agent can move by selection is a number about its preferences. A number the agent cannot move by selection — age of oldest untouched item, ratio of deferred to attempted, failure rate on a forced random sample — is a number about its capability. Only the second kind supports trust, because only the second kind can get worse while the agent is behaving exactly as designed.
We still run unattended. We just stopped letting the system grade its own homework by picking which questions to answer.
Top comments (1)
Treating deferral as a no-op is the easiest way to accumulate silent backlog debt. In unattended queues, an item skipped without an explicit state transition is invisible until an external deadline turns it into an outage.
Emitting a structured reason code on every skip and tracking the age of the oldest untouched ticket exposes the real backlog shape. Forcing a fixed percentage of low-confidence items into each batch guarantees you find tooling gaps on your own schedule instead of discovering them during a fire drill.