At Laracon US 2026 in Boston, the Laravel team announced a human-in-the-loop (HITL) API for the Laravel AI SDK. It landed via laravel/ai#773 and shipped in v0.10.0 on July 21. Previously, once an agent began calling tools it ran to completion unattended — acceptable for read-only tools, but risky for actions like deleting files, refunding payments, or emailing customers. With HITL, an agent can pause before executing a tool and wait for a person to approve, reject, or edit its arguments.

Approval is opt-in per tool. A tool implements the Laravel\Ai\Contracts\Approvable contract and uses the InteractsWithApprovals trait, which makes approval mandatory by default. For finer control, a needsApproval method can inspect the arguments and return a boolean or an Approval instance with a reason — for example, only requiring sign-off when a refund exceeds $20. Requirements can also be overridden at registration time in the agent's tools() method using withoutApproval() and requireApproval().

When the model calls an approvable tool, the agent stops and exposes pending calls on the response via hasPendingApprovals() and pendingApprovals; each entry carries the tool call ID, tool name, arguments, and reason. To resume, the conversation is continued with a Decisions instance keyed by tool call ID, using Decision::approve() or Decision::reject() — plain true/false booleans work as shorthand. Every pending call needs a decision, otherwise an ApprovalMismatchException is thrown; approveRemaining() and rejectRemaining() set defaults for the rest. A rejection including a result string is fed back to the model so it can continue, while a rejection without one stops the generation loop.

Several implementation details matter. The agent must be Conversational with persisted history (the RemembersConversations trait) so the paused call can be resumed. Approval works with prompt, stream, queue, broadcast, broadcastNow, and broadcastOnQueue; during streaming it surfaces as a tool_approval_request event, with native approval parts in the Vercel AI SDK stream protocol, and queued agents receive the response in a then callback plus a ToolApprovalRequested event. Pauses are per call, not per step — non-approvable tools in the same step run immediately, so side effects should stay idempotent via $request->toolCallId(). Results of approved tools are recorded before the model continues, so if generation fails afterwards, resume with a plain text prompt rather than resubmitting decisions.

Upgrading to 0.10 brings breaking changes: a new nullable approval_state column on the conversation messages table, and a storeApprovalResults() method that custom ConversationStore implementations must provide. The documentation includes a full flow with a pair of routes handling both new messages and decision submissions from a chat screen.