When an AI agent calls a tool, one of two things happens: it runs immediately, or it pauses until a person signs off. The second shape — a pre-execution gate — is the only one that meets "a human saw this first," and it decides every call that moves money, sends a message, or exports data. This guide walks that gate as it ships on Devotel Orbit: how a tool becomes gated, what the supervisor sees in the queue, how approve and reject work, and what the audit trail records.
The pattern pools all approvals and denials in one queue: /agents on the dashboard, tab tool-approvals, and the same list is the API endpoint GET /api/v1/agents/tool-approvals. Everything below assumes you already run at least one agent that has tools.
Two gates, one queue: pre-execution vs post-hoc
An agent has one guardrail discipline or the other, never both on the same call:
- Post-hoc review — a
warn-severity rule in the custom guardrail DSL or a coach-note flag raises a record for a supervisor after the call runs. Cheap and forgiving. Fits text reply quality, tone, help-topic drift — anything reversible. If the guardrail is wrong, the reply can be edited or doubled. - Pre-execution gate — the tool call is written to a pending row and the conversation pauses. Nothing runs until a person with owner or admin role moves it. Fits anything irreversible: refund, payment capture, SMS fan-out, PII export, subscription cancel.
Choose post-hoc for the whole reply surface; choose pre-execution for the calls that hurt. The escape hatch — an egress a reviewer reads after the fact — is not available on irrecoverable actions because by the time you read it the carrier has the message or the card has the charge.
Mark the tool as gated
Two flags, two scopes — both write the same queue:
- Per tool: set
confirmation: "always"on the tool definition in Agent Studio. The gate fires on that tool only. - Per agent: set
safety_config.approval_required: trueon the agent. Every tool call pauses, including the read-only look-ups.
Prefer per-tool. The approval_required blanket quickly buries the queue in lookup_order_status trivia; a supervisor stops trusting the badge count. Gate the few calls that move money or leak data; let everything else run.
Check the tool id before you rely on the gate. A typo does not error — it silently produces an ungated call, the worst failure mode for a control this one person relies on.
The supervisor decision loop
The pending queue on /agents → tool-approvals lists each row with the tool the agent wanted (tool_id), the arguments the model proposed (tool_args), the agent and conversation refs, and requested_at. When the tool prices the call in advance, the row carries a cost_estimate field so an SMS fan-out or a payment capture shows its projected spend directly on the pause card. Reject the obviously-wrong fan-out before the carrier touches it.
Filter by status (pending, approved, rejected). The badge on the dashboard tab polls the same GET your own alerting can call, so an aged pending row is visible both ways.
Approve fires the deferred call. The response returns resumed: true when the resume job accepted; if the queue was briefly unavailable the decision still saves (resumed: false plus a warning string) and the platform retries — the approval record, not the enqueue, is the source of truth.
Reject blocks the call. reason is required on reject so a denial is never anonymous.
The decide side runs behind owner or admin role. Read-only list access works for supervisor; the write calls refuse anything below owner/admin.
Timeout policy: the queue ages, the row never resolves itself
There is no auto-approve timeout by design: pending rows never resolve themselves. A stalled turn pauses the conversation and escalates the queue — an alarm, not an inbox. If your risk posture genuinely wants an auto-approve-after-N-minutes sweep, that sweep lives in your operator tooling on the same GET + decide endpoints, never inside the agent, and its decisions carry a named reason so the audit trail stays honest.
Audit trail: the decider is on the record
Every approve and every reject appends an audit row with the deciding user id, the tool id, and whether a reason was attached — written after the status update commits so the trail never claims a decision the database rejected. Rejections log the reason's length only, never the free text, so operator phrasing doesn't spill to warn-path logs. Read the trail on the audit log guide.
Worked pattern: gate high-risk, leave low-risk unguarded
The shape that holds in production:
- Gate —
payment_capture,issue_refund,pii_egress,send_smsfan-out,cancel_subscription. Per-toolconfirmation: "always". - Unguarded —
lookup_order_status,search_knowledge_base,get_weather. Run directly. - Post-hoc — tone, length, topic-drift
warnrules in the guardrail DSL.
When one gated tool exists, the pause card shows its projected spend; when ten are blanked-gated, the queue hides behind trivial look-ups. Pick the gate on the high-risk tools, not the agent as a whole.
Frequently asked questions
What does the pause actually block?
The tool call itself. The conversation sits at a pending row; the deferred turn resumes when an owner or admin approves. Nothing in the call was executed at pause time, so rejecting before approval leaves a clean no-op.
Who can approve or reject?
The decide calls accept owner or admin role only. Supervisor and below can read the queue but not move it. An API key inherits the role of the user who issued it.
Why does reject require a reason?
So the denial is documented — a month later an auditor or the customer's own dispute process can read why. The audit record stores the length of the reason, not the verbatim text.
The queue shows resumed: false on approval — did my decision stick?
Yes. The approval row is the source of truth; the resume-enqueue is a separate step. resumed: false plus the warning string means the platform will retry the resume and the FE should show "Decision saved — auto-resume pending," not a success toast.
Does this replace guardrail DSL rules?
No — they answer at different times. DSL warn rules are post-hoc; the approval gate is pre-execution. Use the DSL on the text surface, the gate on irreversible tool calls, and the audit log as the shared evidence for both.
Resources
- Operator walkthrough: Supervise pending tool approvals — the full queue lifecycle with curl examples.
- Post-hoc rules in the same loop: Custom guardrail DSL.
- Decision evidence: Audit log.
- The queue sits beside the OTP four-eyes gate: Four-eyes OTP approvals.
- Gate the outbound fan-out before the carrier sees it, with the same discipline an ambient send applies: Proactive outreach with ambient agents.