Human-in-the-Loop Is a Design Problem, Not a Feature
The most common HITL pattern in the wild is “Slack approve-and-deny,” and it is the wrong pattern for most use cases.
The most dangerous phrase in enterprise AI deployment is not “the model hallucinated.” It is “we will add a human approval step.” The reasoning sounds reasonable. If the model might make a mistake, put a human in the loop to catch it before it reaches production. The problem is that the loop is never designed. It is bolted on. Someone builds a Slack bot that posts “Approve or deny?” messages to a channel, someone else wires the bot output to the agent’s approval node, and the team ships with the understanding that the human will catch whatever the model misses. What they miss is not the model’s mistake. It is the pattern: a human approval step without a human’s actual availability, attention, or decision framework attached to it.
I have seen this pattern in every enterprise deploying AI agents with a human-in-the-loop feature. The implementation varies. The structure is the same. An agent reaches a decision point and pauses. A message goes to a Slack channel, a Teams thread, or a custom approval widget. The message says something like “Agent wants to execute Action X against System Y. Approve or deny?” Someone on the team sees the message, sometimes. They are in a meeting more often than not. They are reading the message in the context of a Slack channel with twenty other messages around it. They approve or deny based on whatever context the message provides, which is almost never enough. The agent proceeds. If the action was wrong, the postmortem starts with “who approved that?”
The pattern fails for reasons that have nothing to do with the technology and everything to do with the design of the decision itself. An approval request stripped of the context that makes the decision meaningful is not a safety mechanism. It is a liability handoff. The human now owns the outcome of a decision they made with less information than the agent had when it proposed the action. That is not human-in-the-loop. That is human-as-scapegoat.
The fix is not a better Slack bot. The fix is admitting that most approval decisions do not need a human at all. They need a rule. If the agent wants to take Action X costing less than a certain amount against a read-only API, let it. No human required. If the agent wants to perform an irreversible action against a production database, escalate. The threshold between “let it go” and “wake someone up” is a design decision that most teams never make explicitly. They default to requiring human approval for everything, which guarantees that the human will eventually approve everything reflexively, including the actions they should have blocked.
I have argued in earlier posts that agent governance is not a tooling problem. It is a decision problem. Human-in-the-loop is the place where that argument hits hardest. The question is not what tool provides the approval mechanism. The question is what decisions need human judgment, what decisions need a rule, and what the escalation path looks like when the human does not respond. That last question is the one that catches teams most often. They design the approval workflow assuming the human will always be available within the expected window. Then the human goes on vacation. Or the human is in a four-hour block of back-to-back meetings. Or the human was the person who built the agent, and after their promotion nobody else knows what the approval criteria actually are.
The time-based escalation pattern solves this, but it introduces a new design problem. If the agent escalates to the backup approver after the primary approver misses the two-minute window, what does the backup know about the request? Do they see the same context the primary would have seen? Do they see why the primary did not respond? Do they have the authority to deny an action that the primary would have approved, and vice versa? These are not technical questions. They are organizational questions that express themselves as design failures when the technology forces them to the surface.
An audit trail for human-in-the-loop approval flows adds another layer of complexity. Most agent frameworks log that an approval was granted or denied. Few log what context the human had when they made the decision, how much time they spent on it, or what other decisions they were evaluating at the same time. If a regulator asks why a particular transaction was approved, the answer should include the full decision context, not just a line in a log saying “approved by user JWilson at 14:32:17.” The difference between “approved after reviewing the full transaction context” and “approved because the Slack notification popped up during standup and someone tapped the green button without reading it” is the difference between a defensible audit and a compliance finding waiting to happen.
The tools for this are emerging but immature. LangGraph’s interrupt_before pattern is the closest thing to a production-grade HITL mechanism in open source, and I will cover it in detail Thursday. It pauses agent execution at defined nodes, collects human input, and resumes. It handles the mechanics of the pause and resume. It does not handle the design of the decision itself. It does not know whether this particular pause requires a human or is a candidate for automated escalation. It does not know who the backup approver is, what the time-out behavior should be, or how to log the decision context for audit. It provides the loop. The team provides everything else that makes the loop safe.
The pattern I have seen work is conditional intervention gating. Not “pause for every decision of type X.” The agent executes autonomously within a defined safety envelope. The envelope is defined by criteria that the team sets explicitly at deployment time: dollar thresholds, API sensitivity levels, data classification tiers, deviation-from-expected-pattern detectors. Only when the agent’s action falls outside the envelope does the system pause and request human input. Inside the envelope, the agent runs free. This is harder to implement than a blanket approval requirement because it requires the team to think about what the safety envelope actually is. But it produces a system that the humans can actually operate, because the humans only get paged for decisions that genuinely need their judgment.
The hard truth is that most teams do not know what their human approval threshold is until an incident forces them to define it. They deploy with blanket approval, the human approves everything reflexively, and the first real incident is a prompt-injected agent that convinces the approver to approve a credential-exfiltration action because the approval prompt looked legitimate. The postmortem says we need better approval UIs. What it should say is that we needed a defined safety envelope before we ever put a human in front of an approval prompt.
If you are building an agent with human-in-the-loop right now, start with the envelope. Define what the agent can do without approval, what requires approval, and what happens when the approver does not respond. Build the envelope before you build the loop. The loop without the envelope is not safety. It is a design problem waiting for an incident to reveal it.
If this was useful, forward it to one engineer who needs less noise in their feed.


