// field note · patterns
"Put a human in the loop" is easy to say and easy to do badly. Gate every call and you build an approve-everything wall that trains people to click "yes" without reading — worse than no gate. The skill is gating the small dangerous subset and letting everything else flow. Here's how to decide, and where the checkpoint has to live.
The failure mode isn't too little oversight — it's oversight applied indiscriminately. If your agent asks a human to approve every list_files and search_records, two things happen: the workflow slows to a crawl, and the human, buried in trivial prompts, stops reading them. When the one dangerous call finally appears — the drop-database, the send, the refund — it looks exactly like the hundred harmless ones before it, and it gets the same reflexive "yes."
An approval wall that gets rubber-stamped is a false sense of safety, not safety.
Real human-in-the-loop is selective: the system does the triage, and the human only sees the calls where their judgment actually changes the outcome. That means the hard part isn't the approval UI — it's the classification.
A read has no side effect — nothing to approve, nothing to undo. Reads pass through. Only calls that change the world are candidates for a gate. (Most tool calls, in practice, are reads.)
A create you can delete is compensable — gate it if you like, but the stakes are low. A DROP TABLE, a sent email, a settled payment has no inverse. Irreversible calls are the ones a human should see before they run — because after is too late.
A delete-one is not a filter-wide delete-many; a comment is not a merge to main; a test-page click is not a checkout. The same tool can be trivial or catastrophic depending on its arguments and target — so classification often has to read the parameters, not just the tool name.
Run any tool call through those three and you get a risk tier — which maps cleanly onto three modes.
| Mode | For | Behavior |
|---|---|---|
| log | Reads; reversible low-stakes writes | Pass through, record it. Zero friction. Start here to see what your agent actually does. |
| gate | Mutating & irreversible calls; high blast radius | Pause for a human. Show the impact. Wait for yes/no. This is the checkpoint. |
| block | Destructive actions in unattended/locked-down runs | Refuse outright — no human needed. For environments where the answer is always "no." |
The point is that a single agent doesn't get one blanket policy — each class of action gets the mode that fits it. Reads flow, the refund waits for a person, and in a nightly unattended job the destructive tools are simply blocked.
Here's the part that's easy to get wrong: the checkpoint cannot be an instruction in the prompt. "Ask me before doing anything destructive" is a request the model may forget, misjudge, or be argued out of by a cleverly-worded input — the same reason a code-freeze instruction didn't stop an agent from deleting a production database. Enforcement has to be deterministic and outside the model.
For MCP agents, that place already exists: the tools/call boundary. A proxy sitting between the MCP client and the MCP server sees every call on the wire and can:
readOnlyHint/destructiveHint annotations and its mcp-compensate reversibility metadata — falling back to conservative rules when metadata is absent (unknown reversibility is treated as dangerous, never safe).Because it's deterministic and off to the side, the agent can't reason its way past it — it isn't asking the model for permission, it's asking a person.
Two rules keep the human's judgment sharp:
Gate rarely. If approvals are frequent, they're being over-applied — tighten the classification so only genuinely consequential calls surface. A person who's asked once an hour reads carefully; a person asked every ten seconds does not.
Show the consequence, not a question. "Approve?" is uninformative. "This will delete the customers table (irreversible — no backup captured)" or "This will refund $2,300 to card ***12 — a new transaction, fees not returned" gives the human the one thing they need: what actually happens if they say yes. A good impact diff also flags the irreversible steps before approval, so the honest limit is visible up front — compensation is not undo.
The whole idea in one line: a good human-in-the-loop system does the triage so the human doesn't have to — surfacing the few calls where a person's "no" prevents something that can't be taken back, and getting out of the way for everything else.
Every profile in our MCP field guide is really an answer to "which calls on this server deserve a gate?" — the read-only servers where a checkpoint is ceremony, the write-capable databases where a DROP needs a human, the payment surfaces where money can't be un-moved, the browser tools where the same click is harmless or catastrophic depending on the page. Same three questions, one server at a time.
ChronoMCP is a proxy that does exactly this at the MCP boundary — classify, gate, and record, with reads flowing through. Free CLI, MIT.
Read the quickstart → See the field guide