In July 2026 the Laravel AI SDK added human-in-the-loop tool approval: an agent can now pause before a sensitive tool runs and wait for a person to approve or reject the call. n8n workflows have been able to stop and wait for a person's answer for a while. The mechanism is no longer the hard part.
The hard part is the design. Which actions get a gate, what the reviewer sees, what happens when nobody answers, and how you stop people from approving everything without reading it. Those decisions decide whether a gate is a safety system or a ritual.
Which actions need a gate
I use one question: if this action is wrong, can I quietly undo it before anyone outside notices? If yes, it usually does not need a gate. If no, it does.
| Action | Gate? | Why |
|---|---|---|
| Read a record, search a knowledge base | No | Nothing changes |
| Create an internal draft or a pending record | No | A person reviews it later anyway |
| Send a message a customer will read | Yes | You cannot unsend it |
| Charge, refund, or change a price | Yes | Money moves |
| Delete data or change permissions | Yes | Often irreversible |
| Anything the agent has never done before | Yes, for now | You have no history to trust |
Notice the second row. A lot of agent actions can be redesigned so they produce something reviewable instead of doing something irreversible. That is often better than a gate.
What the Laravel AI SDK gives you
The feature arrived in laravel/ai v0.10.0. In short:
- A tool requires approval by implementing the
Approvablecontract with theInteractsWithApprovalstrait, or by defining aneedsApprovalmethod that returns a boolean or anApprovalwith a reason. That lets approval depend on the arguments, so a refund of 50 can pass while a refund of 5,000 waits. - The agent can override this when it registers its tools, with
withoutApproval()orrequireApproval(). - When the model calls a gated tool, the run pauses before the tool executes. The response reports
hasPendingApprovals()and lists each pending call with its ID, tool name, arguments, and reason. - You resume by continuing the conversation with a
Decisionsinstance keyed by tool call ID, usingDecision::approve()orDecision::reject(). A rejection with a message goes back to the model so it can adjust. A rejection without one stops the loop. - Every pending call needs a decision, or the SDK throws an
ApprovalMismatchException. - The agent must be conversational with persisted history, because the run has to resume where it stopped.
The detail that will bite you
Pauses apply per tool call, not per step. If the model asks for three tools in one step and only one is gated, the other two run immediately while the gated one waits.
That has a direct design consequence: any ungated tool with an external side effect must be safe to run even if its gated sibling is later rejected, and safe to run again if the conversation is retried. In practice that means idempotent side effects, such as an idempotency key on anything that calls an external API, or a gate on the whole group.
Gating the artifact instead of the call
This site still runs an older version of the SDK, so its gate sits somewhere else: at the artifact. The AI writer and the article MCP server can only create drafts with the status pending_review. A separate PublishDraft action, run by a signed-in person in the admin, turns a draft into a public article and records who approved it and when.
Gating the artifact has real advantages. The reviewer sees the finished result rather than a tool name and a JSON blob, and they can edit it rather than only say yes or no. For content, configuration changes, and anything that can sit in a queue for an hour, I prefer it.
Gating the call is the right choice when the action has to happen inside a live conversation. Think of a support agent that offers to issue a credit while the customer waits.
Sometimes the right person to hold the gate is the customer. On LaunchLancer, our store builder for Pakistani merchants, we are adding a WhatsApp order confirmation with Confirm and Cancel buttons before a cash-on-delivery order ships. It is the same pattern: pause before the expensive, hard-to-undo step, and ask the person with the most at stake.
The same idea in n8n
In n8n, where I build most of the automations in my workflow library, the pattern is a workflow that sends a message and waits for the answer. The Slack and Gmail nodes can send a message with approve and decline options and hold the execution until someone responds. The workflow then branches on the decision. Two settings matter more than the node itself:
- A timeout, so an unanswered request does not hold an execution open for days.
- A safe default on timeout, which should almost always be "decline and tell someone."
Designing a review people will actually do
A gate that people approve without reading is worse than no gate, because it creates false confidence. Some rules that help:
- Show what will happen, not what the model said. Show the tool, the exact arguments, the reason, and the consequence in plain words: "Refund 1,200 to invoice #4411."
- Make rejection cheap and useful. A rejection should take one click and, ideally, one sentence that goes back to the agent. If rejecting is harder than approving, everything gets approved.
- Fail closed. No answer means no action.
- Record every decision with who, when, and what they saw. When something goes wrong, the question is never just "what did the agent do" but "who approved it and what were they shown."
- Watch the approval rate. A gate that has been approved every time for months on a low-risk action is a candidate to relax, with the logs to justify it. A gate that keeps being rejected is telling you the agent needs fixing, not more supervision.
A lesson from the plant floor
Before software, I spent eight years in industrial automation at Siemens. Control rooms learned long ago that too many alarms train operators to acknowledge without looking. Approval gates have the same failure mode. I go further into what the plant floor teaches about agents in What PLC Safety Interlocks Taught Me About AI Agent Guardrails. Keep them rare enough that each one gets read, and put them only where a mistake cannot be quietly undone.
My take
Human-in-the-loop is a feature, not a fallback for agents you do not trust yet. Done well, it lets you give an agent real tools sooner, because the dangerous ones have a person standing behind them. Start with gates on everything irreversible, redesign what you can into reviewable artifacts, and let the decision logs tell you when a gate has earned its removal.