Human-in-the-Loop Approvals
Scarab-Runtime supports human-in-the-loop (HITL) gating for sensitive tool invocations. When an agent invokes a tool that requires approval, the request is queued and the agent blocks until the operator approves or denies it.
How it Works
- Agent calls a tool marked
requires_approval: true(e.g.sensitive-op) agentdqueues the request and returns aRequiresApprovalresponse to the agent- The agent waits (blocking on IPC)
- The operator sees the pending request with
ash pending - The operator approves or denies it
- The agent's blocked call returns with the result or a denial error
Viewing Pending Requests
ash pending
Output:
REQUEST-ID AGENT TOOL CREATED
a1b2c3d4-... my-agent sensitive-op 2026-02-22T12:34:56Z
Approving a Request
ash approve <request-id>
# With an operator token (for audit trail)
ash approve <request-id> --operator "alice"
Denying a Request
ash deny <request-id>
# With an operator token
ash deny <request-id> --operator "alice"
When denied, the agent receives a ToolFailed("denied by operator") error from invoke_tool().
Configuring Approval Timeouts
Each tool can declare an approval_timeout_secs. If the operator does not respond within the timeout:
- The request is automatically denied
- The agent receives a timeout error
- An audit entry is written
The sensitive-op built-in tool has a 300-second (5 minute) timeout.
Custom Approval-Required Tools
When registering a dynamic tool (or in a future tool plugin), set requires_approval: true in the ToolInfo:
#![allow(unused)] fn main() { ToolInfo { name: "deploy-to-production".to_string(), requires_approval: true, approval_timeout_secs: Some(600), // 10 minutes // ... } }
Escalation Hierarchy
HITL approvals that are not handled by an operator escalate up the agent hierarchy. A parent agent may be configured to auto-approve or auto-deny certain request types, filtering the interrupt load before it reaches the human.
See Hierarchy and Escalations for details.