Everyone says their AI system has a human in the loop.
Almost nobody says where in the loop, which is the only part that matters — because a human placed at the wrong point in a loop is not oversight. It's ceremony with a salary.
I want to describe a failure mode I built into my own product without noticing, because I think it's about to become extremely common, and because the fix is boring, structural, and about fifty lines of code.
The shape of the trap
My content pipeline can generate topic ideas as well as articles. That's the point of it. The wizard suggests topics. I can ask for a batch of ideas. An auto-replenish job keeps the queue from running dry.
It also has a scheduler that picks topics off the queue and generates articles, unattended.
Read those two paragraphs again and find the bug. It took me weeks.
AI-suggested topics and human-approved topics landed in the same bucket. The scheduler drew from that bucket.
So: the machine proposes a topic. The machine (via a scheduler with no opinion) approves it by picking it up. The machine writes it. And three days later I'm reviewing a publish-ready article about something I would never in a hundred years have chosen to write about.
Was there a human in the loop? Technically, yes! I was reviewing the output. I was in the loop at the point where saying no costs the most — after the ideation spend, after the research call, after the expensive draft, after the scoring pass. My "no" cancelled work that had already been done and money that had already been spent.
A human placed at the end of a pipeline isn't oversight. It's a returns department.
Why the fix isn't a prompt, a policy, or a review step
The instinct — my instinct, at the time — is to fix this in the model's instructions. Only suggest topics that fit our editorial strategy. Or to fix it in process: review the queue weekly.
Both are the same mistake wearing different hats. They put the boundary somewhere soft.
A prompt is a request. It works most of the time, and "most of the time" is not a boundary — it's a probability distribution with a bad tail.
A review process is a promise about future human behaviour, made by a human who is currently well-rested and unbusy. It survives exactly until the first crunch week.
If you want a boundary, it has to be structural: a thing that cannot be crossed because the mechanism to cross it does not exist.
What I actually built
A new status. That's it. That's the whole intervention.
Topics can now be `Ideas`, `Queued`, `Generating`, `Done`, or `Skipped`. The board renders them as lanes. And underneath it, one hard property:
The auto-generate scheduler only ever consumes `Queued`.
Quick-added notes, bulk-pasted lists, AI ideation batches — every one of them lands in `Ideas` and sits there until a person moves it.
An ungroomed idea structurally cannot leak into the generation pipeline. Not "shouldn't." Not "we have a process." Cannot — because the scheduler's query doesn't select that lane, and there is no path from `Ideas` to a running generation that doesn't pass through a human hand.
The deliberate paths still go straight to work: topics from the setup wizard and from auto-replenish land in `Queued` directly, because those flows already encode my intent — I asked for them, in a context where I was making a decision.
The distinction isn't "AI-made vs human-made." It's "reviewed intent vs raw suggestion." That's the line worth defending, and it's not the same line.
Make approval cheaper than the thing it gates
Here's the part people get wrong even when they get the structure right.
If your approval step is expensive, it becomes the new bottleneck, and then somebody — probably you, at 11pm — will route around it. The gate has to cost less than the work it authorises, or it will not survive contact with a deadline.
So there is no approval dialog. No confirmation modal. No form.
You drag a card from `Ideas` to `Queued`. That's approval. Drag it back — demoted. Drag it within `Queued` and you've reordered generation priority, because the queue order is the schedule.
One deliberate shortcut: hitting Generate on a batch that includes `Ideas`-status topics treats that as implicit approval. If you're explicitly telling the machine "write these," making you drag them first is ceremony, and ceremony is how gates get resented and removed.
The whole feature is about fifty lines of status handling wrapped in drag-and-drop. It is the difference between a content factory I supervise and one I babysit.
The general principle, which is going to matter a great deal soon
Every automation system I have built ends up needing the same thing:
A structural boundary between suggested and approved, placed where saying no is cheapest.
Prompts don't enforce that boundary. Review steps don't enforce it. Statuses and schedulers enforce it, because they're mechanisms rather than intentions.
And the placement is the whole art. "Where saying no is cheapest" is almost always before spend — before the expensive model call, before the side effect, before anything irreversible. If your human checkpoint is downstream of the cost, you have not built a checkpoint. You've built a regret-collection interface.
This is about to be everyone's problem. We're wiring agents into systems where they propose and execute, and the industry's standard answer — "there's a human in the loop" — is, in most implementations I've seen, exactly the pattern I just described: a person at the end, reviewing completed work, whose "no" is expensive enough that they'll say yes.
Ask of any agentic system, including your own:
- Can the machine's suggestion reach execution without a human touching it? If yes, you don't have a loop. You have a chute.
- Where does the human sit relative to the spend? Before it, or in the returns department?
- Is the boundary a mechanism or an intention? If it's phrased as a rule people follow, it's an intention, and it will erode.
- Is saying yes cheaper than saying no? If so, you'll get yes, from a tired human, at 11pm.
The machine can propose all day. It just doesn't get to approve itself.