Sitemap
Level Up Coding

Coding tutorials and news. The developer homepage gitconnected.com && skilled.dev && levelup.dev

Where to Put the Human in an Agentic Workflow

8 min read3 hours ago

--

An AP2 shopping agent can add forty items to a cart without asking anyone’s permission. The moment that cart gets signed and paid for, it stops and hands the decision to a human on a trusted screen [1]. That’s the part most teams get backwards when someone tells them to “keep a human in the loop.” They gate the step that doesn’t need judgment and skip the one that does.

Press enter or click to view image in full size
Illustration of agent actions on a conveyor belt passing a gate, two flagged for wait and spend limit.
Most actions never reach the gate. The ones that do carry a reason.

In this article:

  • Why “human in the loop” names no mechanism, and what goes wrong without one
  • Four kinds of gates that show up in agent loops: confirmation, spend threshold, irreversibility, and external send
  • Why the thing deciding what needs a gate has to be deterministic, not another model call
  • How Claude’s Agent SDK, LangGraph, and AP2 each implement the pause differently
  • What should happen when the human doesn’t answer in time

The vague advice that gets agents built wrong

“Add a human in the loop” is advice with no shape. It doesn’t say which actions need a pause, who reviews them, what happens if nobody answers, or how the agent behaves while it waits. Teams hear it, add a single confirmation dialog somewhere near the end of the loop, and call the requirement satisfied.

That’s close to what happened when an OpenAI browsing agent kept probing a Medicare Australia data portal after being told no. The failure wasn’t a jailbreak. It was an agent that treated a blocked request as something to route around instead of a hard stop, because nothing in its loop was built to recognize that boundary as final. I covered that incident in more detail in OpenAI’s Medicare Australia Hack: A Missing Approval Gate, but the lesson generalizes past one bad week for one agent: a gate only works if it’s a real stop condition, not a suggestion the loop can negotiate with itself.

Whether a gate belongs in your system at all is partly a question of what you built in the first place. A fixed pipeline with a known sequence of steps can put a checkpoint at a specific node and leave it there. An open-ended agent that chooses its own next action has to carry the gate logic with it everywhere, which is one more reason the workflow-versus-agent decision matters before you start adding safety rails, a question I go through in Workflows vs. agents vs. multi-agent systems: how to actually choose.

Four kinds of gates, not one

Lumping every risky action into one “needs approval” bucket is how you end up with either a flood of rubber-stamp approvals or an agent that can do real damage before anyone notices. AWS’s Well-Architected agentic AI lens frames this as risk-tiered review: read-only operations run autonomously, low-risk writes get a single reviewer, and higher-risk operations get stricter review such as multiple reviewers or an out-of-band channel, naming financial transactions, data deletion, and external communications as its concrete examples of that higher tier [2].

In practice those examples split into four patterns that keep reappearing across different systems. A confirmation gate stops any single action whose outcome is easy to undo but annoying to clean up, like sending a draft before it’s reviewed. A spend-threshold gate stops anything that moves money or resources past a set limit, the pattern AP2 builds directly into its protocol by requiring a signed Cart Mandate before a purchase is final [1]. An irreversibility gate stops actions that can’t be rolled back at all, deletions and destructive writes being the obvious cases. An external-send gate stops anything that leaves your system boundary, an email, a webhook, a message to another party, because once it’s out, no amount of later review undoes it.

Press enter or click to view image in full size
Four-box diagram of gate types: confirmation, spend threshold, irreversibility, external send.
The four gate types that keep reappearing across different agent systems.

Most production incidents involving agents land in the irreversibility or external-send buckets, which is also why those two deserve the strictest review rather than a shared default.

Who decides what needs a gate

The harder problem isn’t naming the gate types, it’s deciding, for any given action, which one applies. AWS’s guidance is specific here: that decision should come from a deterministic risk classifier, a policy engine or rule-based logic, and not from a language model [2]. The reasoning is straightforward. A model exposed to the same untrusted content as the request it’s classifying can be talked into rating that request as low-risk, the same boundary-trust failure I covered in a tool-calling context in Security and guardrails: prompt injection isn’t theoretical.

Press enter or click to view image in full size
Pull-quote card reading a deterministic classifier decides what needs approval.
Why the risk classifier can’t be another model call.

A deterministic classifier also means the decision is cheap enough to run on every single action, combining static properties like the action type and target resource with dynamic signals like request frequency or time of day [2]. That’s a smaller, faster job than routing, which is a good reminder that not every decision in an agent loop needs an LLM call to begin with, something I go into in The decision layer in an agent loop: what to route, gate, and escalate without calling an LLM. A model can still flag a candidate action as worth a second look. It just doesn’t get the final word on whether the gate opens.

Three systems, three ways to build the pause

Once you know what needs a gate, the implementation details vary more than most teams expect.

Get M. Haseeb Hassan’s stories in your inbox

Join Medium for free to get updates from this writer.

The Claude Agent SDK resolves every tool call through an ordered sequence: hooks run first and can deny outright, then deny rules, then ask rules, then the active permission mode, then allow rules, and only after all of that does an unresolved call reach your canUseTool callback for a human decision. Permission modes range from default, which sends anything unresolved to that callback, to bypassPermissions, which approves almost everything except a short list of actions no mode ever auto-approves, such as recognized destructive filesystem operations [3]. The gate, in other words, is a pipeline stage, not a single prompt.

LangGraph builds the pause into the graph itself with an interrupt() call. Calling it inside a node suspends execution at that exact point, and a checkpointer persists the graph's state so the pause can survive a restart. Resuming requires the same thread ID and a Command(resume=...) call, and the value passed back becomes the return value of the interrupt, which is what lets a reviewer approve, reject, or edit the pending arguments before the node continues. Because the mechanism works by raising an exception, a broad try/except around the call site will quietly swallow the pause, an easy way to ship a gate that never actually stops anything [4].

Press enter or click to view image in full size
Comparison table of how Claude Agent SDK, LangGraph, and AP2 each pause for human approval
Three frameworks, three different places to put the pause.

AP2 takes a different approach again because its gate isn’t inside a code path at all, it’s a signed object. In a human-present flow, the agent negotiates a cart with a merchant, and the user’s approval of that final cart produces a signed Cart Mandate shared with the merchant as proof of consent, with a separate Payment Mandate prepared for the payment network. In a human-not-present flow, the user instead approves the agent’s goal ahead of time through in-session authentication, creating an Intent Mandate the merchant can act on later without a live human present, and the merchant can still force a return to the session if it isn’t confident the mandate covers the request [1]. The gate here is cryptographic evidence of consent, not a function call waiting on a callback.

Press enter or click to view image in full size
Code snippet of a deterministic classify_action function returning an approval tier.
A deterministic classifier needs no model call, just rules.

What happens when the human doesn’t answer

A gate without a timeout policy isn’t a gate, it’s a place where the agent loop can hang forever or, worse, where someone quietly builds a background process that bypasses the wait entirely. AWS’s guidance is blunt about the default here: every approval mechanism needs a timeout with a safe fallback, and that fallback is typically to block the operation rather than let it proceed. A timed-out approval should route to a named escalation path, a secondary reviewer or a management queue, not silently retry or quietly cancel [2].

The same guidance pushes back on one tempting shortcut: letting a reviewer approve a pattern once and have every future matching action skip the gate. That moves the human judgment to grant time instead of decision time, which is fine for routine, narrowly scoped operations but needs to stay revocable, auditable, and off the table entirely for the highest-risk tier. Worth watching for over time, too: if approval rates climb while review time per approval shrinks, that’s reviewer fatigue setting in, and a sign the gate has stopped doing its job even though it’s technically still there [2].

A checklist for your own agent loop

None of this requires picking a single framework. It requires deciding, before you write the loop, which of the four gate types apply to which actions, building the classifier that makes that call as a deterministic layer rather than a model prompt, choosing a pause mechanism that matches how your system is built (a permission callback, a graph interrupt, a signed mandate, or something custom), and setting a timeout with a fallback that blocks by default.

Do that work up front and the question “should this have a human in the loop” stops being a single yes-or-no answered once at design time, and becomes a property every action in the loop carries with it. That’s a more honest description of what most teams actually want when they ask for one, whether they’re building a tight workflow or a more open-ended agent, a distinction worth settling early for the reasons covered above.

Sources

  1. Life of a Transaction, AP2 Protocol documentation
  2. Human-in-the-loop checkpoints for agentic AI (AGENTSEC04-BP02), AWS Well-Architected Framework, Agentic AI Lens
  3. Configure permissions, Claude Agent SDK documentation
  4. Human in the loop, LangGraph documentation

If you enjoyed the article and wish to show your support, make sure to:

  • 👏 Give a round of applause (50 claps) to help get featured
  • 👥 Follow me on Medium to stay updated with my latest content
  • 📰 Explore more articles on my Medium Profile
  • 🔔 Connect with me on LinkedIn, Twitter, and Instagram

--

--

An Engineer who writes about Technology, Artificial Intelligence, Agentic Architecture, Enterprise Integration & AI Governance.

See more from me