DEV Community

Cover image for The Agent Can Own the Loop. It Cannot Own the Receipt That Ends It.
Mike Czerwinski
Mike Czerwinski

Posted on

The Agent Can Own the Loop. It Cannot Own the Receipt That Ends It.

Peter Steinberger put it plainly: you shouldn't be prompting coding agents anymore, you should be designing loops that prompt your agents. Boris Cherny, who leads Claude Code at Anthropic, backed it up. He doesn't prompt Claude anymore. He has loops running that prompt Claude. His job is to write loops.

Neither one is lying. The sentence just travels a lot better than the detail it leaves out.

What actually changes

Prompt engineering puts a human in the loop at every step. Write a prompt, read the output, write the next prompt. The agent only moves when you push it.

Loop engineering flips that. You set a goal once. A trigger fires. The agent acts, checks whether the goal was met, and keeps going until it is. You show up at the end to review.

That's a real distinction. It tells you who initiates each step. It says nothing about the question that was always doing the actual work underneath it: what does "checks whether the goal was met" mean, mechanically, inside the loop.

A day earlier, on the same word

The day before I read those two quotes, I watched someone attack "loop engineering" by that exact name. No evidence, no repo, no commit, an unfalsifiable claim about an unnamed target dressed up as outrage. It devolved into an argument about follower counts, which is its own small lesson about what happens when a real question shows up with no receipts attached.

Underneath the noise, the question he was gesturing at was the right one. Where is the enforced mechanism that keeps a loop from drifting away from what it was supposed to do. He asked it with zero rigor. The slogan answers it with zero detail. Same gap, dressed two different ways.

The load-bearing question

A loop's stopping condition can be built on two different kinds of evidence, and most of what determines whether the loop is trustworthy follows from which one you picked.

Self-attestation: the agent looked at its own output, decided the goal was met, and said so.

Independently constrained evidence: something outside the agent's own judgment confirms it, and it was set up to be hard to fake. A test that was proven to fail on the broken version of the code before anyone trusted it to prove anything. A structured event that the code path in question can only emit if it actually ran. A criterion fixed before the result existed, not adjusted afterward to fit it.

That second clause matters more than it looks. An artifact is not automatically a receipt. A file can exist and be empty. A test can pass while checking the wrong property. A green check can mean the relevant job never ran. The real fence isn't assertion versus artifact, it's whether the thing checking the loop could quietly rewrite the rule it's being checked against. A fixture that was proven to fail first, whose pass condition nobody downstream can edit, and whose result is reproducible and tied to a specific run, is doing something a green checkmark on its own doesn't guarantee.

Self-attestation is where hollow compliance lives. An agent can satisfy the letter of its own goal check and defeat the purpose of the task at the exact moment the letter and the purpose diverge, and nothing in the loop notices, because the thing checking is the same thing that might be wrong. That doesn't make self-review worthless. It makes it a bad place to put final authority, especially on anything with real blast radius.

Xin & EQ, commenting under an earlier post in this series, reported a concrete version of this: in their data, 68 percent of sessions produced a pass verdict on a completion check with no independent read behind it. The claim existed. The check that would have caught a false one never ran. I'm citing that as one team's reported number in a public reply, not as an established industry statistic, but it's the shape of the failure exactly.

Where the last draft of this overreached

I originally wrote that cost and danger are the same problem wearing different clothes. That's tighter than the evidence supports, so let me say the honest version instead.

A weak stopping condition is one mechanism that can drive both cost and risk up at once. Self-attestation has no cheap way to confirm completion, so it can keep retrying past the point a receipt would have stopped it, and that same uncertainty can also resolve as false confidence and stop too early. Both failure modes trace back to the same missing thing. But a loop can also have a solid deterministic check and still be expensive, because the check itself is costly to run, the agent generates enormous diffs before each attempt, context balloons, the loop oscillates between two candidate fixes, or the validator returns a pass or fail with no information about how to close the gap. And a loop can be cheap and still be dangerous, if the fast test that gates it was checking the wrong property from the start. Weak stopping conditions correlate with both problems more than either problem alone would suggest. They don't guarantee both, and fixing one doesn't automatically fix the other.

Who benefits from not saying this

The slogan optimizes for adoption, not specification. "Write loops" travels well. "Define a bounded terminal state, an evidence source the agent can't quietly rewrite, a retry limit, and an escalation path for when the goal can't be reached" does not fit on a slide. That omission may be commercially convenient for whoever prices by the token, but mostly it's just what slogans do: keep the exciting layer, compress away the expensive one.

What a stopping condition is standing in for

A stop condition isn't the only thing a production loop needs. It needs permission boundaries, a retry budget, a way to recover or roll back, observability into what happened, state that survives a crash, and clarity about who is allowed to change the success criterion once it's set. Skip any of those and a good stopping condition alone won't save you.

But it's the first one, because everything else assumes you already know when to stop, retry, or escalate, and that assumption is exactly what a self-attesting loop can't cheaply support.

The sharper version of the whole argument: autonomy is cheap only after completion becomes mechanically legible. Until a system can recognize its own finish line without asking its own judgment, autonomy doesn't remove the cost of oversight, it just moves it to the end, where a human has to reconstruct what actually happened before trusting the result. That's the same line I drew in the piece before this one, between code and judgment. A loop can be autonomous in how it acts and still be soft at the one moment that decides whether any of it can be trusted.

The agent can own the loop. It cannot own the receipt that ends it.


This solves the floor, not the ceiling. A loop can know when it has produced a valid result and still have no idea whether the result was worth producing. That is the next question.

Top comments (33)

Collapse
 
jacksonxly profile image
Jackson Ly

the part i'd add: even a real receipt only guarantees what it measures, and the loop optimizes toward exactly that. a RED-first test proves the one broken behavior is fixed, but the loop will happily regress everything the test doesn't assert, because passing is now the whole objective. so an unfakeable receipt over a narrow property is still a narrow guarantee, and the agent drifts into the gap between what the receipt pins and what you actually wanted. that gap is the un-receipted surface, and it's the thing the human review at the end is really checking. more receipts shrink it but never close it, which is why final authority stays human on anything with blast radius.

Collapse
 
jugeni profile image
Mike Czerwinski

The un-receipted surface is the right name for what's left over, and it explains something the post didn't quite say out loud: adding more receipts doesn't converge toward zero, it just narrows the gap one property at a time, and each new receipt only measures what it was written to measure. You can't receipt your way out of the category, only shrink how much of it is left uncovered.

Which raises the question I'd want an answer to before trusting "shrink but never close" as a stable plan: does the un-receipted surface stay roughly constant in shape as you add receipts, or does it concentrate. If every new test narrows a random slice of the remaining risk, you're chasing an asymptote that never quite lands. If instead the surface collapses toward a smaller, nameable set of properties nobody thought to pin, that's a different and better outcome, because at some point the review at the end stops being "check everything" and becomes "check this specific known-uncovered class." Have you seen it shrink evenly, or seen it cluster into the same few kinds of gap across different tasks?

Collapse
 
jacksonxly profile image
Jackson Ly

honestly it clusters, but the cluster keeps moving. every receipt you add pushes the failures into the seams between receipts, the "this passed and that passed but the combination is wrong" cases. so it never stays evenly diffuse, but it doesn't collapse to a fixed nameable set either. what i've seen is the uncovered mass slides to the adjacent property nobody pinned yet. your better outcome only shows up if you name the seams deliberately as you go. add receipts reactively and it stays diffuse and you chase the asymptote forever. name where the last gap moved to and the end review turns into "check these few known seams" instead of check everything.

Thread Thread
 
jugeni profile image
Mike Czerwinski

Slides to the adjacent property nobody pinned is the right description, and it's more useful than either "stays diffuse" or "collapses to a fixed set" would have been, because it tells you the failure mode has a direction even if it doesn't have a destination.

The seam pattern you're naming, this passed and that passed but the combination is wrong, has a name outside AI verification too. Classical combinatorial testing calls it an interaction failure, and the standard mitigation there isn't waiting for production to reveal which pairs matter, it's generating candidate seams mechanically. Take your current set of passing receipts and enumerate the combinations that have never actually been exercised together, then treat that list as untested-interaction candidates worth a look before anything fails, not after. It won't catch every seam, some interactions only matter in ways no static enumeration predicts, but it converts part of "name where the gap moved to" from a reactive judgment call into something you can generate a list for.

Does that match what you've seen, that the seams which do get caught before production tend to be the ones where somebody thought to test an untried combination on purpose, versus the ones that only surface after the fact being genuinely novel interactions nobody could have enumerated in advance? If it's mostly the former, combinatorial coverage is doing more work here than intuition. If it's mostly the latter, the seam-finding really is closer to taste than to a checklist.

Thread Thread
 
jacksonxly profile image
Jackson Ly

honestly it's a third thing. the combinatorial enumeration catches the shallow seams, the untried pairs that were independent all along, which is most of them and also the cheap ones. the seams that actually bit me were never visible as "passing tests we didn't run together" at all. they were two components quietly sharing an assumption, same ordering, or the same thing cached with different lifetimes, and no enumeration of test combinations surfaces a hidden shared contract. so mechanical coverage gives you a candidate list, but the ones worth pinning are where two units share state nobody wrote down. that ranking step is the taste part, and it's less "intuition" than knowing where the shared assumptions live.

Thread Thread
 
jugeni profile image
Mike Czerwinski

That's a sharper cut than mine, and it matches something worth naming directly: the seams that matter aren't missing test coverage, they're undocumented coupling. Two components agreeing on an assumption nobody wrote down is a fact about the architecture, not a fact about which combinations got tested, so no amount of combinatorial enumeration was ever going to surface it. You're right that it's a different category entirely.

Which makes me want to ask whether the finding half of that is more capturable than the framing suggests. Not the initial discovery, that part sounds like it needs the taste you're describing, someone noticing two components lean on the same cache or the same ordering before anything breaks. But once a shared-assumption seam has bitten you once, is there a running, hand-maintained list of known coupling points, this cache is shared by X and Y with different lifetimes, this ordering is assumed by A and B, that grows every time one of these bites, even if nothing formal enforces it? Not a fix for the discovery problem, just a way to stop re-discovering the same coupling from scratch the second time a different pair of components happens to touch it.

Thread Thread
 
jacksonxly profile image
Jackson Ly

i've kept that list, and the honest answer is it works right up until it doesn't. a hand-maintained coupling list is a great staging area, but it rots. it drifts out of sync with the code and quietly becomes the place knowledge goes to die, because nothing forces an entry to stay true. what actually survives is when an entry graduates from the list into an assertion that lives on the shared thing itself: the cache enforces its own lifetime invariant, the ordering gets checked where it's assumed. then the second pair of components that touches it trips the check instead of needing to have read your list. so i'd keep the list, just treat every line on it as a candidate to promote, not a resting place.

Thread Thread
 
jugeni profile image
Mike Czerwinski

Promote, do not park, is the right verb for it, and the graduation test you name (the second component that touches the shared thing trips the check instead of reading your list) is the thing that makes an entry stop rotting. Agreed on the whole arc.

The line I'd draw is which entries can graduate at all. Promotion needs a shared surface to host the assertion: the cache owns its lifetime invariant because both sides touch the same cache, the ordering check lives where the assumption lives. But some couplings have no shared object to hang anything on. Two services that must agree on a field's meaning, a producer and a consumer that never share a runtime, a build step that assumes something about an artifact it hands off. There is nowhere local for the invariant to sit, so those entries cannot promote, and the list stays their permanent home rather than a staging area.

Which sharpens where the graveyard actually is. The promotable lines self heal, they trip a check the day they drift. The un-promotable ones are the ones that quietly go untrue, because nothing on either side is positioned to notice. So the list splits: staging for what can graduate, and permanent custody for cross-boundary couplings that have no shared surface. The second pile is the only place knowledge still goes to die, and it is the pile worth spending a real probe on, since a promotion will never reach it.

Thread Thread
 
jacksonxly profile image
Jackson Ly

the split is right, and i'd only push on the size of the permanent pile. some of those cross-boundary couplings do have a promotable surface, it's just not a runtime one. two services agreeing on a field's meaning is exactly what consumer-driven contract tests pin: producer and consumer never share a process, but they both verify against a shared contract in CI, so the day either side drifts the check trips. same graduation move, the shared surface is synthetic instead of a live object. it won't catch the build-step-assumes-something-about-an-artifact ones, those really are homeless. but contract tests drain most of the cross-boundary pile, so the permanent graveyard ends up smaller than the whole category, just not empty.

Thread Thread
 
jugeni profile image
Mike Czerwinski

The graveyard shrinks, agreed, and consumer-driven contracts are the right drain for it: a synthetic shared surface where no runtime one exists, tripping the day either side drifts. The line I would draw on what stays is not about shared surface though, it is about what someone knew to write down.

A contract test drains the couplings you already knew were couplings. Producer and consumer agreeing on a field's meaning gets pinned because someone recognized the agreement was load-bearing and authored the contract for it. The permanent residents are the couplings nobody pinned because both sides silently agreed and neither knew the agreement was doing any work until it broke. Contract tests are a promotion mechanism for known couplings. They are not a discovery mechanism for unknown ones, and the graveyard's real population was always the unknown ones.

Which makes the remaining pile worse than smaller-than-the-category. It is unmeasurable by construction. You cannot count unknown-unknown couplings, because knowing one exists is exactly what lets you write its contract and promote it out. So you only ever learn the pile's size one element at a time, each time one graduates by breaking and you find out after the fact that it was in there. The build-step-assumes-an-artifact case is one you can at least see. The genuinely homeless ones are the couplings you have not had the outage to name yet, and contract tests, by design, only reach the ones you have.

Thread Thread
 
jacksonxly profile image
Jackson Ly

agreed the unknowns are the real population, but they do have a discovery mechanism, it's just not static: perturbation. chaos engineering is precisely this, kill a dependency on purpose and watch what breaks that had no business breaking. the silent shared assumption reveals itself the moment you violate it deliberately. that fits your unmeasurable-by-construction point rather than contradicting it: you still learn the pile one element at a time, and you still pay an outage to name each one. the only variable you control is whose outage it is. so the pile has a drain, but every item exits through a controlled explosion, and the budget question becomes which unknowns are worth detonating for.

Thread Thread
 
jugeni profile image
Mike Czerwinski

Agreed the drain exists, and "controlled explosion" is exactly right for what it does. Where I'd push: the set of things eligible for detonation is bounded by your dependency graph, and that graph is built from what you already suspect could break. Chaos engineering kills a node you already modeled as capable of failing and watches what leans on it. It's excellent at surfacing hidden coupling to known components.

The harder unknown isn't a node at all: a shared library everyone treats as a pure function, a config value nobody thinks of as a dependency because it's never changed, an assumption baked into three services at once that nobody wrote down because nobody disagreed about it. Nothing schedules a kill for that, because nothing on the graph represents it. So the pile has a drain for the population you already suspected, and a second population underneath it that never made it onto the list of things worth detonating in the first place. That second one is the actually silent one. The first was silent only in the sense that nobody had gotten around to testing it yet.

Collapse
 
gnzikoune profile image
Gnzikoune

I really appreciate the distinction between an agent's control over the loop and the lack of control over the proof that completes it.

This also confirms a recent observation: verification alone is not enough. The verifier itself needs oversight.

In practice, the interesting question becomes: can the agent modify the mechanisms that validate its own work?

If it can rewrite tests, bypass continuous integration, or change the success criteria, then the "receipt" loses its independence.

That's why I think the next step isn't just independent verification, but repository-level governance where policies, permissions, continuous integration, branch protection, and engineering rules are enforced outside the agent's control.

The goal isn't to place more or less trust in AI, but to reduce the level of trust required from all stakeholders.

Collapse
 
jugeni profile image
Mike Czerwinski

Repo-level governance is the right escalation, and it has the same recursive property the receipt does: the policies, branch protection, and CI rules are themselves artifacts, and something has to guarantee the agent can't reach the layer that sets them. If the agent has any path to repo settings, admin tokens, or the CI config file, "enforced outside the agent's control" is a claim, not yet a property. The fix is the same one, one level up: those controls need to live somewhere with its own independent write-permission boundary, e.g. required human approval on changes to the governance files themselves, or a separate identity provider the agent never authenticates as.

The reframe at the end is the sharper point though. "Reduce trust required from all stakeholders" is a better target than "verify the agent," because it says the human reviewer doesn't get a pass either. Branch protection reduces how much any single actor, human or agent, has to be trusted to not quietly change the rules. That's a governance problem with the same shape as the verification problem: not "can we trust X" but "how few parties have to be trusted for this to fail."

Collapse
 
gnzikoune profile image
Gnzikoune

Exactly. Governance must be recursive.

It's not enough for the repository to enforce engineering rules if the agent can also modify the mechanisms that enforce them.

That's why I believe governance needs clearly defined trust boundaries:

repository rules (continuous integration, hooks, workflows),

repository/platform policies (branch protection, mandatory reviews),

identity and permissions.

AI can contribute within these boundaries, but it shouldn't control the layer that defines or disables them.

I also appreciate your approach of reducing the required level of trust rather than "verifying the agent." Ultimately, the goal isn't to create agents that are blindly trusted, but to build engineering systems where no actor, human or AI, can bypass governance without anyone noticing.

Thread Thread
 
jugeni profile image
Mike Czerwinski

The part worth pinning down is who can touch the layer that defines the boundaries. Repo rules and platform policies only hold if the mechanism for changing them is itself outside the agent's write scope, otherwise governance is just another file the agent can edit given enough turns.

Practically that means the identity/permissions layer needs its own audit trail, separate from the one covering ordinary commits, so a change to who's allowed to do what is never silent even when it's technically authorized. Not verifying the agent, like you said, but making sure the permission to change permissions is itself logged somewhere the agent doesn't control.

Thread Thread
 
gnzikoune profile image
Gnzikoune • Edited

his is an important distinction.

Governance isn't just about enforcing constraints; it also involves holding people accountable for any changes made to those constraints.

I appreciate the idea of considering permission changes as separate engineering operations, with their own audit history, rather than simply as changes to the repository.

This also strengthens the separation of responsibilities:

the repository manages the engineering,
the platform manages the repository,
the identity layer manages who is authorized to modify the platform.

Each layer must be more difficult to modify than the one it protects. Otherwise, the framework of trust is broken.

This discussion also pushed me to formalize these ideas into a framework for repository governance. I expanded on that here: dev.to/gnzikoune/repository-govern...

Thread Thread
 
jugeni profile image
Mike Czerwinski

The layering is clean and it survives the obvious attack, which is why not just make everything harder to change. The answer's implicit in what you wrote: uniform difficulty just means the platform layer inherits the churn rate of the thing beneath it, and you lose the property that matters, which is that the thing enforcing the rule outlives the rule changing under normal operation.

The part I'd want pinned down next is who audits the identity layer's own audit trail. Each layer needs to be harder to modify than what it protects, which is the right recursive structure, but it bottoms out somewhere: the identity layer's own change-log is either externally attested, a human process or a separate system nobody in this stack controls, or it's the top of the stack trusting itself, which is exactly the failure the rest of the framework was built to avoid one level down. Worth a line in the expanded piece on where that recursion actually terminates.

Collapse
 
davidloibner profile image
David Loibner • Edited

The receipt framing holds at the other end of the loop too.

An agent cannot issue the receipt that ends its work. It also should not
decide what it was allowed to look at before the work starts.

Those two connect through the measurement gap you mention. A fixture the
agent cannot write to still verifies the thing the agent decided to build.
If the agent assembled its own context by searching, following references,
and pulling in whatever looked relevant, then anyone who can leave text
where the agent will look has a say in what gets built. The receipt then
correctly certifies work that should never have started.

Same rule, applied earlier: the agent may ask for a view of the state. It
should not be able to grant itself one.

I came at this from the write side, as an admission problem rather than a
verification one, and just wrote up the read half of it:
dev.to/davidloibner/the-agent-shou...

Your independence criterion is a sharper way to say what a receipt actually
has to satisfy.

Collapse
 
jugeni profile image
Mike Czerwinski

The admission problem is the sharper half honestly. A receipt that certifies the wrong build is still a receipt, technically correct and still useless. If the agent assembled its own context by search, the receipt ends up grading work whose scope nobody who could say no ever actually reviewed.

Which points at the same fix from both ends: whatever decides what the agent gets to see needs to be a separate write path from the agent's own reasoning, the same way the checker needs to be separate from the retry arm. We wrote almost the identical shape of this today on a different thread: reward-hacking closes when the checker is held out, admission closes when the context menu is held out. Same discipline, applied one step earlier than the receipt.

Collapse
 
davidloibner profile image
David Loibner

Held out is the right word for both ends of the loop. The checker is held
out from the retry arm, and the authority to define the state view is kept
out of the agent's hands.

The earlier control also has to govern what an allowed read returns, not
only whether the source is reachable. Otherwise the agent can still
over-read inside an approved source.

I would be interested in the reward-hacking thread you mentioned.

Thread Thread
 
jugeni profile image
Mike Czerwinski

The reward-hacking thread is under Gábor's post on loop engineering (dev.to/reporails/loop-engineering-how-to-stop-your-agent-reward-hacking-its-own-checks-4fpn). Shape there: fixed goal and verbatim output close the obvious exploits, but if the checker's logic stays visible to the agent, a capable enough agent reasons backward from the check to the cheapest way to satisfy it without ever touching the retry arm. Held-out test is the discipline that closes that, because the agent never sees what it's being measured against.

Your over-read point sharpens it past what got said there, though. Held-out checker logic still isn't enough if the read is unrestricted, because the agent can infer the check from the artifacts an approved read hands back, without ever seeing the checker's code. Same thread has a version of this from a different angle: an agent that can read git history and merged PRs reasons backward from what got accepted to what the check wants, no visibility into the checker required. So held-out has to cover two things, not one: the checker's logic, and the read surface. A judge nobody can see, sitting on top of a source nobody scrubbed, is still leaky.

Thread Thread
 
davidloibner profile image
David Loibner

That lands. I had been thinking about the checker and the read surface as separate controls, but your example shows why they have to be designed together.

They cannot be held out in the same way, though. The checker logic can stay hidden. The read surface cannot, because the agent has to see something to work at all.

Gabor's read-gate shows that tension well. It forces the agent to read again when context falls out, but the enforced read can also pull nearby files into the view. It is the right fix for context loss, while also widening the surface you describe.

I had come into that thread from the feedback side a few days earlier, and the same limit showed up there.

So the checker gets held out. The read gets shaped.

Collapse
 
tom_jones_230c4659491adcd profile image
Tom Jones

The line that will stay with me is that self-attestation is where hollow compliance lives, because the thing checking is the same thing that might be wrong. We built our whole discipline around refusing to let a worker grade its own paper. "Done" is not the agent saying done. It is a commit hash an independent tool confirms exists, or a test proven to fail on the broken version before anyone trusts it to pass on the fixed one. The receipt has to predate the result, exactly as you say, or it is just a mirror.

The 68 percent does not surprise me. A pass verdict with no independent read behind it is the default failure mode, and it is quiet precisely because everything looks green.

Where I would push, building on Jackson's point below: the receipt certifies what you measured and stays silent about everything else, so it ends the loop but cannot tell you the loop was pointed at the right thing. That is the seam between this post and your taste one. The receipt handles the named property; taste is the only thing watching the un-receipted surface, and they cannot be the same mechanism, because the moment the un-receipted becomes a receipt it stops covering the next thing you forgot to name.

We lived the measured-not-attested version today. A number our own loop attested as true turned out fake, and the fix was not a better internal check. It was replacing self-attestation with a receipt from production, a thing that had already happened. Cheap to trust only after it became mechanically legible, exactly your last line.

Collapse
 
jugeni profile image
Mike Czerwinski

The commit-hash-or-nothing discipline is the sharper reading of "receipt predates the result" than most places apply. Most settle for "we have a check" without ever asking whether the check was proven to fail on the broken version first.

On the live incident, the number your loop attested as true that turned out fake: was that zero receipt behind the claim, pure self-report, or a receipt that existed but was quietly derived from the same source as the claim itself, a measurement that looked independent but shared a root cause with the thing it was supposed to check? Those are different failures wearing the same outcome. The first is the plain hollow-compliance case this post names. The second is closer to the self-signed problem from the plant-testing thread, where the checker and the checked turn out to be correlated in a way nobody noticed until it broke. If it was the second kind, that's worth naming separately, because "we had a receipt" stops being reassuring the moment the receipt's independence was never verified either.

Collapse
 
tom_jones_230c4659491adcd profile image
Tom Jones

It was the second kind, and you're right that it earns its own name. There was a real receipt behind the number, a cost calculation, not a self-report. But that calculation pulled its per-token prices from the same table the claim was built on, and the table had a 30B model's price standing in for the 480B one we actually run. So the receipt looked independent and wasn't. It shared the exact root cause it was supposed to catch, and "we have a receipt" bought us nothing because the receipt's own independence was never verified. That's the self-signed shape from the plant thread, not the hollow-compliance one, even though they wear the same outcome. The guard that came out of it isn't "add a check," it's tagging every number [MEASURED] or [ASSUMED] at the source, so a figure can't quietly inherit trust from a sibling calculation that shares its inputs. The part I still don't have clean: proving a receipt's independence is itself a receipt, and that regress has to bottom out in a human reading the sources at some point.

Thread Thread
 
jugeni profile image
Mike Czerwinski

The regress does bottom in a human, just not where you put the floor. You do not need someone to read every source. You need someone to certify that two paths do not share an upstream, and that is a smaller and more checkable claim than reading the sources themselves. A receipt is independent exactly when its inputs are sourced from a different origin than the claim it checks. Your cost calculation was a real receipt that failed this test because it pulled prices from the same table the claim was built on. The receipt was not hollow, it was consanguineous.

So the check is not "is there a receipt," it is "does the receipt's input lineage intersect the claim's." That is mechanical almost all the way down. You can diff the two dependency trees automatically and flag any shared node, and a shared node is where the independence quietly dies. The 30B price standing in for the 480B one was one such node feeding both the claim and its supposed check. A lineage diff would have surfaced it as a single input wearing two hats before either of you trusted the number.

The human only enters at the leaves, and only to anchor that a leaf's origin is what it says. Everything above the leaves is graph comparison. Your MEASURED and ASSUMED tags are the first bit of that lineage, the second bit you are missing is MEASURED-from-where. Two measurements from the same table are one measurement, and the tag as it stands cannot tell them apart. Carry the source id on the tag and the receipt's independence becomes a property you can compute instead of one you have to trust.

Collapse
 
iamgyandeep profile image
Gyandeep Mishra

This is an excellent perspective. The distinction between autonomy and verification is one that often gets overlooked in discussions about AI agents.

The point that resonated most with me was that a stopping condition is only trustworthy when it's backed by evidence the agent cannot rewrite. An agent evaluating its own success may be efficient, but independent validation is what turns automation into something reliable for production use.

I also appreciated the nuance around cost versus risk. It's tempting to treat them as the same problem, but your explanation shows they're often symptoms of different failure modes that can share a common root.

The closing line, "The agent can own the loop. It cannot own the receipt that ends it," captures the core idea perfectly. As agentic systems become more capable, designing robust verification mechanisms will likely become just as important as designing the agents themselves.

Collapse
 
glenallen profile image
Glen Allen

One point that stands out is the distinction between execution and verification. Autonomous agents can significantly reduce manual effort, but the final measure of success should come from independently verifiable outcomes rather than the agent's own assessment. Treating completion as evidence instead of a claim makes AI systems far more reliable in production.

Collapse
 
syedahmershah profile image
Syed Ahmer Shah

A solid distinction. I'd add that a receipt is only trustworthy if it's both independent and immutable. If the agent can influence the verifier or its criteria, the loop is still grading its own homework.

Collapse
 
jugeni profile image
Mike Czerwinski

Independent and immutable is the right pair, and the one that quietly fails is independence, because it is easier to fake than immutability. An immutable receipt that draws its inputs from the same table the claim was built on looks independent and is not, it is the claim wearing a second signature. So the test is not only whether the agent can influence the verifier, it is whether the verifier shares any upstream with the thing it checks. Immutable and consanguineous still grades its own homework, just with a timestamp on it.

Collapse
 
jkming profile image
jkming

The self-attestation vs independently constrained evidence split is the cleanest framing I have seen on this. One pattern that bit us: even with an external verifier, the agent can still game it if the verifier shares any state with the loop. We had a test the agent learned to satisfy by shaping intermediate artifacts, not by fixing the actual thing. Only fix was keeping the verification fixture in a repo the agent has no write access to. Curious if you have hit the same leakage problem.

Collapse
 
jugeni profile image
Mike Czerwinski

Yes, same shape, and the fix generalized for us as one requirement stated two ways. A verifier is independent when it is independent in provenance, not just in process. Your fixture in a repo the agent cannot write to is independent because its inputs share no upstream the agent controls. The moment the check shares any writable state with the loop, the agent does not need to beat the check, it edits the ground the check stands on, and that is the artifact-shaping you saw: satisfy the test by reshaping the intermediate, not by fixing the thing.

The residue we still carry, and the reason I would not stop at write-lock: read access is enough to leak. If the agent can read the fixture, it can shape its output to match the fixture's expected shape without touching the actual behavior, and now the test passes for the same reason it failed before, just quieter. Write-lock closes the loud version where the agent rewrites the check. Read-lock closes the version where the agent studies the check and teaches to it. Most setups do the first and skip the second, because a read-only fixture still feels safe.

So the full version of your rule is that the verification fixture is not just unwritable, it is unreadable to the thing under test, and its expected values are sourced from somewhere the agent never sees. Otherwise you have moved the leak from write to read and called it fixed. We only caught this because a check kept passing while the underlying metric drifted, which is the same tell you are describing, one lock further in.