Where an earlier post stopped
Picture an AI agent with a key to something real: a production database, a payment system, a customer inbox. In front of that key there is usually an approval step. A person looks at what the agent wants to do. The person says yes. Then the agent acts.
That approval step is the thing most teams count on. This note is about a gap in it.
In an earlier post I wrote about one choice in my publishing workflow that was recorded and then never read. I ended on this line: the decision has to survive the trip through the data. That post was about a bug in one tool. It turns out to be a pattern: another system I run had already closed the same gap, for a different kind of object. One bug is an accident. The same gap in two places is a pattern, and a pattern is worth seeing before you build your next system on top of one.
Instance one: the post that almost shipped unreviewed
I use a posting tool to manage my LinkedIn posts. It keeps every draft of a post as a numbered version, which the tool calls a variant. A post can have many variants before it goes out.
Checks, called gates, hang off each post. There are three. A voice review is a read for tone and facts. A process review is a read for whether the steps were followed. The last gate is my approval. Each gate now records which variant it was earned on. That record is called a binding: the gate is bound to one exact variant.
Once the binding existed, it found a live case on September 13. The register entry, the log where my agents record what went wrong, reads:
> "Post 6 publishes with a voice-review bound to variant 14, 'Here is a simple test for AI pilots', and an approval bound to variant 24, 'Not the demo. The workflow.' Different opening, different length, different text. The draft that ships was never voice-reviewed."
Nobody did anything wrong in the usual sense. A reviewer passed one draft. A newer draft was added later, in good faith. The approval was bound to variant 24, the newest draft. The record does not say which approval route was used. Every gate showed green. The lesson is right here: a green gate tells you a check passed, not which draft it passed on.
The mismatch was caught two days before the post's September 15 slot. Variant 24 went back through voice review, the gate was earned again, and post 6 went out reviewed. How the tool learned to refuse is the story I told in the earlier post. What interests me now is that the same problem was already solved somewhere else.
Instance two: the system that checked the exact commit
A second system tracks my agents' work. A pull request is a proposed change to code that someone reviews before it is merged into the main copy. Each saved state of the code is a commit. This system has to decide whether a merged pull request was really reviewed.
The simple version asks one question: does the pull request have an approving review? This system has asked a narrower question from the day the check was added. Was the commit the reviewer approved the same commit that merged? If the reviewer approved one commit and more commits landed before the merge, the review does not count as evidence.
A yes on yesterday's code is not a yes on today's. The common default does the opposite. On GitHub, an approval survives new pushes unless someone turns on the setting that dismisses stale reviews. That default is the post 6 case, written for code instead of prose.
Two kinds of object, one shape. A person says yes to a specific thing. The thing changes. Unless something checks, the yes stays attached to the name. The system that tracks my agents' work bound the yes to the exact commit from the day the check was added. My posting tool had the same check added after the miss.
The question that matters: does approval carry over?
Here is the question worth asking of every approval step, mine or a vendor's. When the object changes after you approve it, does your approval quietly carry over, or does it fall off?
Carrying over is the default almost everywhere, because it is convenient. Think about where you approve things today. A change ticket is approved by its title and description, not by the exact script that runs. A document gets signed off in a shared editor that keeps accepting edits. An agent proposes a plan, you say yes, and it revises the plan mid-run because a tool call failed. In each case the approval is attached to a container, and the container is allowed to change underneath it.
Convenience is a real reason. If every small edit dropped the approval, people would stop editing, or stop asking. Or they would approve without reading, because they know they will be asked again in an hour. Teams leave carry-over on because the alternative feels like friction with no payoff. The payoff only shows up on the day the edit was not small.
Agents change that math. A human editor makes a few revisions and usually remembers what changed. An agent can revise an object many times between your yes and its action. Each revision is reasonable on its own terms. Retry logic, self-correction and "let me fix that formatting" all produce a new object. If your approval carries over by default, every one of those revisions inherits a yes you never gave.
So the design choice is not whether to have a person in the loop. It is what the person's yes is bound to, and what happens to that yes when the thing changes. There are three options, from weakest to strongest:
- Bound to a name. "Approve the change to the billing job." Anything can happen under that name afterward.
- Bound to a version, with carry-over. The record names the version, but nothing checks it before acting. It feels safe because the record is correct.
- Bound to a version, with fall-off. Any change drops the approval, and the action checks that what it is about to run is what was approved.
The third option is my posting tool's rule now. If a gate was earned on an older variant, the tool will not let me approve the post or schedule it. The system that tracks my agents' work applies the same binding after the fact: a review on an older commit does not count as evidence.
The third option costs something. You will re-approve things that barely changed. The answer in my posting tool has been to make re-approval cheap rather than let approval carry over.
What to ask before you hand over the key
Ask the vendor, or your own team, one question: if the thing I approved changes before it runs, what happens to my approval? If the answer is "it stays approved," you have a person near the loop, not in it. If nobody knows, assume carry-over, because that is the default.
One of my two systems had this right from the day the check was added. The other learned it from a near miss. That is the reason to check yours.
review ---> variant 14
approval -> variant 24 -> publish
(never ran; 24 unreviewed)