← all posts
// architecture · architecture

Designing the human into the loop without killing the flow

There are two ways to ruin an agent with oversight, and they sit at opposite ends. The first is to make it ask permission for everything, every file read, every command, every step, until using it is so tedious that people turn it off or, worse, start reflexively clicking "yes" without reading. The second is to let it act freely on everything and discover after the fact that "everything" included deleting the wrong data or emailing the wrong customer. Real human-in-the-loop design lives in the gap between those failures, and it's an interaction-design problem more than a technical one.

The organizing principle is that the gate belongs on the irreversible, not on everything. Reversibility is the test you apply to each action. Reading a file, running the test suite, searching the codebase, drafting something into a buffer, these cost you nothing if the agent gets them wrong, so let them happen without interruption. Deleting data, pushing to production, sending a message, spending money, these you can't take back, so they stop for a human. Most actions an agent takes are reversible, which means most of the time the right amount of friction is none, and the gate only appears at the handful of moments that actually warrant it. Get this split right and the human barely notices the oversight while still catching the thing that mattered.

Trust isn't static

A good gating policy changes over time. A brand-new agent, or a familiar agent on an unfamiliar task, deserves tight gates, because you don't yet know how it behaves. As it proves itself on the reversible stuff, you can loosen, granting it more autonomy on the actions it's handled well. The mistake in both directions is treating trust as fixed: granting full autonomy on day one before anything's been earned, or continuing to gate actions that have proven safe a thousand times until the gate is pure ceremony. The trust gradient is part of the design, not an afterthought.

Approve the plan, not the keystrokes

The fastest way to make oversight unbearable is to interrupt per action. The fix is to batch. Let the agent think, produce a plan or a complete proposed change, and present that for a single approval before it executes. You approve the diff, not each line as it's typed. For a coding agent this is the difference between a usable tool and one that asks you a question every fifteen seconds, and it preserves real oversight because you're reviewing the substance of what it intends to do, all at once, with the context to judge it.

Which leads to the part people botch: the approval has to be informative. A confirmation dialog that says "the agent wants to proceed, OK?" with no detail is a speed bump that trains people to click through without thinking, and a gate everyone reflexively approves is functionally the same as no gate at all. Show what it's about to do and why, with enough context that a human can actually make the call in a couple of seconds. The quality of the information in the gate is what determines whether the gate does anything.

Long-running work needs the human off the critical path

When an agent runs for minutes and hits a point that needs approval, it cannot sit there holding a thread open waiting for a person who might respond in an hour. It has to park, persist its state, and wait for an event, the approval arriving asynchronously through whatever channel the human actually lives in, chat or a ticket, rather than a modal they're expected to babysit. The approval comes to the human where they are, and the agent resumes when it arrives. This is the same durable-state machinery that lets the agent survive a crash, now serving the pause.

Knowing when to ask is its own skill

There's a flavor of human-in-the-loop that escalates a decision instead of gating an action: the agent recognizing it's uncertain or out of its depth and handing off to a person, with context, rather than guessing. This is the right design for customer support and for any system where confidently wrong is expensive, and it's the same instinct that drives a model cascade to escalate the hard cases. An agent that knows what it doesn't know and asks cleanly is far more valuable than one that always has an answer.

For code agents specifically, the human gate is the review, and that only works if the change is small enough to actually review. A six-hundred-line diff with an "approve?" button underneath it is a rubber stamp with extra steps. Nobody reads it. Keeping the agent's changes small and reviewable is what makes the human-in-the-loop real rather than nominal, which is one more reason the bottleneck in agentic coding is review, and why you design for reviewable units.

Human-in-the-loop is a design with a goal, not a checkbox bolted on at the end: maximum autonomy on the safe actions, a meaningful and well-informed gate on the dangerous ones, trust that adjusts as the agent earns it, and the human kept off the critical path for anything long-running. Done well, the person hardly feels it and catches the one thing that would have hurt. Done badly, you get friction people route around or oversight that was never really there, and those two failures are how most "human-in-the-loop" systems quietly become neither.

#architecture#agents#ux