Human-in-the-loop approvals
Control D routes destructive tool calls through laravel-flow’s approvalGate(). Two commands make setup turnkey and verifiable.
Install
Require laravel-flow
composer require padosoft/laravel-flowCreate the flow tables
php artisan ai-guardrails:hitl-installRuns laravel-flow’s migrations scoped straight from vendor (no
vendor:publish, no unrelated host migrations, idempotent).Enable + persist
LARAVEL_FLOW_PERSISTENCE_ENABLED=true AI_GUARDRAILS_HITL_ENABLED=trueVerify
php artisan ai-guardrails:hitl-statusExits non-zero with targeted guidance until HITL can actually gate a call.
Route a destructive tool
use Padosoft\AiGuardrails\Facades\AiGuardrails;
$gated = AiGuardrails::routeForApproval($refundTool, 'refund');
// destructive calls are parked; the model gets a non-secret run reference, not the token.
A tool is “destructive” if its name matches hitl.destructive_tools under the destructive_match policy.
The approval lifecycle
Pending approvals and the approve/reject actions are exposed by GET /approvals and POST /approvals/{token}/approve|reject in the admin API — the decision actor is derived server-side, never trusted from the client.
Diagnostics
ai-guardrails:hitl-status reports each prerequisite:
| Check | Meaning |
|---|---|
| laravel-flow installed | the package is present |
| flow persistence enabled | laravel-flow.persistence.enabled |
flow_runs / flow_approvals tables |
migrations ran |
master + hitl.enabled |
the bridge is on |
- Keep HITL on
enforcein production — inmonitormode destructive calls execute (with a log). - Restrict
hitl.allowed_tool_classesto the destructive tool FQCNs to limit blast radius if the flow persistence layer is ever compromised.