Approvals
Approvals are the human-in-the-loop gate for autonomous agents. When an agent needs human sign-off before taking a non-reversible action — a payment, an external send, a destructive operation — it calls the built-in request_approval tool. The run pauses, an approval request appears in the Approvals page, and an authorized reviewer approves or rejects. The run then resumes (on approve) or terminates (on reject).

How it works
-
Agent requests approval. While running, the agent invokes the built-in tool:
request_approval(reason="Send a $500 wire to ACME Corp", payload={...})The runtime creates an
ApprovalRequestrow, flips the run towaiting_approval, and emits an event. -
Reviewer is notified. The Approvals page polls every 10 seconds. Org admins and
team_admins of the requesting agent’s team see the pending request in their queue. -
Reviewer decides. They click Approve or Reject in the UI, optionally adding a decision reason. The decision is recorded with
decidedBy,decidedAt,decisionReason. -
Run resumes or terminates. On approve, the run goes back to
runningand continues from where it paused, with the approval result available as the tool call’s return value. On reject (or expiry), the run is cancelled with the rejection reason recorded as the cancellation reason.
Authorization
Who can approve depends on the resource’s team scoping:
- Org-wide agents (
visibility='org') → orgowneroradmincan approve. - Team-scoped agents (
visibility='team') → orgowner/adminOR the team’steam_admin(TeamRole.LEAD) can approve. Plain team members can see the pending request but not act on it.
This is enforced server-side via AccessPolicyService.canAccess(user, approvalRequest, 'manage').
Expiration
By default a pending approval times out after 24 hours (configurable up to 7 days when creating it via the API). A scheduled sweep flips expired requests to 'expired' and the corresponding run is cancelled with reason "approval expired".
Via the API
List pending approvals
curl /approvals \
-H "Authorization: Bearer $TOKEN"Returns only approvals the caller can see, filtered by AccessPolicyService.applyListFilter (org-wide ∪ caller’s teams).
Approve
curl -X POST /approvals/{id}/approve \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"decisionReason": "Looked at the line items, matches PO #4221, approved."
}'Reject
curl -X POST /approvals/{id}/reject \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"decisionReason": "Amount exceeds the per-vendor cap for the quarter."
}'Agent-side usage
Inside an autonomous agent’s instructions, instruct the model to gate sensitive actions:
You are a billing assistant. Before issuing any refund, transfer, or other
non-reversible action, call request_approval with a clear reason summarizing
what you intend to do and the relevant amounts/parties.The tool returns when the human decides. Treat the returned value as the authorization to proceed.