Supervise pending tool approvals
A tool your agent calls is either unguarded (it runs as soon as the model seeks it) or approval-gated (it pauses until a human signs off). This guide walks the full supervisor loop for gated tools: declare which tools require approval, watch the pending queue, decide approve or deny, and read the audit trail. The decision recurs hourly in production, so the loop is what matters — not the one-time setup. The endpoint paths below are relative. Send them againsthttps://api.orbit.devotel.io/api/v1. The concepts behind the queue are in
Human-in-the-loop oversight; this guide
is the operational walk.
1. When gate tracking acts: pre-execution vs post-hoc
The approval gate is synchronous pre-execution: when the model emits a gated tool call, the executor writes apending approval row and returns a
blocked stub to the model instead of running the tool. Nothing touches
the action until a human approves it. After approval the resume worker runs
the deferred call and the conversation continues. That is the only safe
timing that meets “a human saw this first”.
Async post-hoc review is the opposite shape and is cheaper: let the tool
run now and review the record after. Text-only guardrail violations
(warn-severity) work like that, because a wrong reply is recoverable. For
a gated tool call, post-hoc is wrong — a payment capture or a PII egress has
already happened by the time you review it.
Choose pre-execution approval for the calls that hurt; choose post-hoc
warning for the rest. The worked pattern in section 8 shows both in one
agent.
2. Prerequisites
- A supervisor identity. Approve and reject calls run behind the
owneroradminrole — reading the list or the dashboard view is fine for asupervisorrole, but the decide step requiresowner/admin. Authenticate every call with an API key (X-API-Key: dv_live_sk_...) or a dashboard session. - Tool policy in Agent Studio. The agent’s tools are declared in Agent
Studio with a per-tool confirmation flag, or
through the agent API’s
safety_config. Either path marks a tool as gated; both feed the same queue. - Your tools exist. The gate fires on a tool the agent actually has. A typo in the tool id silently produces an unguarded call — verify the id before you rely on the gate.
3. Declare which tools require approval
Gate a tool per-call by setting itsconfirmation to "always" in the
tool definition. Gate every tool on the agent by setting
safety_config.approval_required: true. The two flags are additive; either
one firing puts the call in the queue.
approval_required: true stops every tool call
and quickly buries the queue under harmless lookups — see the worked pattern
in section 8.
4. Surface pending approvals to a supervisor
The pending queue lives on the dashboard at/agents → the
tool-approvals tab, and programmatically at
GET /api/v1/agents/tool-approvals?status=pending&limit=50:
tool_id), the arguments the
model proposed (tool_args), the agent and conversation refs, requested_at,
and a cost_estimate when the tool priced the call in advance — an SMS
fan-out or a payment capture shows the projected spend right on the pause
card. Filter by status (pending, approved, rejected) and age the
queue by requested_at.
Wire the same GET into your own alerting path (an oncall webhook or a
polling supervisor screen) — the JSON shape above is the contract. The
badge-count on the tool-approvals tab in the dashboard reads the same
pending list, so the queue is visible without manual polling.
A row that stays pending is the failure mode to watch: the turn is
blocked and the customer experience hangs while no one decides. Treat an
aged pending queue as an alarm, not an inbox.
5. Resolve with approve or deny
Approve lets the deferred call run.reason is optional on approve:
resumed: true confirms the deferred-turn resume job was accepted. If the
resume queue is briefly unavailable the decision still saves
(resumed: false + a warning string) and the platform retries — the
approval record is the source of truth, no decision is lost.
Reject blocks the call. reason is required so the refusal is
documented:
6. Timeout policy: what an unresolved pending row means
There is no auto-approve timeout by design: apending row never
resolves itself, and an aged pending row simply pauses the conversation
until someone decides. That is the deliberate, safe default — an
auto-approve after N minutes would defeat the point of the gate.
So the timeout you actually operate is on the queue, not the row: a
pending approval that sits past a few minutes is a stalled turn, and the
correct action is to escalate the queue to a supervisor, not to let it
auto-resolve. The warning string on resumed: false is your signal to
route a hard-deny or a manual callback.
If your risk posture truly wants an auto-approve-after-N-minutes rule, the
fall-back lives outside the gate: add a scheduled sweep that reads the
pending list (step 4), rejects or approves with a named reason (step 5), and
is explicit in the audit trail (step 7). Run that sweep from your own
operator tooling — never inside the agent.
7. Audit — every decision writes the supervisor identity
Both decide endpoints append an audit record with the deciding user, the tool id, and whether a reason was attached. The audit entry is written after the status update persists, so the trail never claims a decision that didn’t commit. Approvals carryapproved with an optional-reason flag;
rejections carry rejected with the reason length recorded (never the free
text verbatim, which shouldn’t spill to a warn-path log). Read the trail in
the audit log.
8. Common pattern — gate high-risk, leave low-risk unguarded
The single most useful shape: gate the few calls that move money or leak data; let everything else run.- Gate:
payment_capture,issue_refund,pii_egress(export / send),cancel_subscription— anything irreversible or paid. - Unguarded:
lookup_order_status,search_knowledge_base,get_weather— read-only or recoverable.
confirmation: "always" (step 3). If you
set approval_required: true on the agent instead, every safe lookup goes
to the queue too and a supervisor spends the shift on trivia. Pick the gate
on the high-risk tools, not the agent as a whole.
Where a cost_estimate exists on the gated tool, the pause card shows the
projected spend — use it to reject the obviously-wrong fan-out before the
carrier touches it.
Related reading
- Human-in-the-loop oversight — the concept page: whisper, approve, take-over.
- Audit log — read the decision trail.
- Custom guardrail DSL — declare
warn/block/redactrules (post-hoc tracking) alongside this gate.