Skip to main content

Overview

The Approvals API enables human oversight of AI agent actions. When an agent attempts a sensitive operation, it creates an approval request that humans review via the web console or API before the action executes.

Core workflow

  1. SDK creates request: Agent calls @guarded_action with requires_human_approval=True
  2. Request submitted: SDK posts to /api/v1/approvals
  3. Human reviews: Approver sees request in web console or via API
  4. Decision made: Approve, reject, or request more info
  5. SDK polls: Agent receives decision via polling endpoint
  6. Action executes: If approved, action proceeds; if rejected, raises error

Endpoints

Create approval request (SDK)

POST /api/v1/approvals
Request body:
{
  "action_name": "transfer_funds",
  "description": "Transfer $10,000 from account A to account B",
  "agent_id": "payment-agent",
  "run_id": "run_123",
  "estimated_cost_usd": 0.10,
  "priority": "high",
  "risk_level": "high",
  "timeout_seconds": 600,
  "action_inputs": {
    "from_account": "acct_123",
    "to_account": "acct_456",
    "amount_usd": 10000.0
  },
  "context": {
    "user_id": "user_789",
    "requested_at": "2024-12-28T14:30:00Z"
  }
}
Response:
{
  "approval_id": "approval_abc123",
  "status": "pending",
  "created_at": "2024-12-28T14:30:00Z",
  "expires_at": "2024-12-28T14:40:00Z"
}

List approval requests

GET /api/v1/approvals
Query parameters:
  • status (optional): Filter by status
    • pending, approved, rejected, expired, cancelled, info_requested
  • priority (optional): Filter by priority
    • critical, high, medium, low
  • risk_level (optional): Filter by risk level
    • critical, high, medium, low, minimal
  • agent_id (optional): Filter by agent
  • include_expired (optional): Include expired approvals (default: false)
  • skip (optional): Pagination offset
  • limit (optional): Page size (max: 1000)
Example:
curl -H "Authorization: Bearer $TOKEN" \
  "https://platform.agentsentinel.dev/api/v1/approvals?status=pending&priority=critical"

Get pending approvals

Convenience endpoint for pending approvals only:
GET /api/v1/approvals/pending
Response:
{
  "approvals": [
    {
      "id": "approval_abc123",
      "action_name": "transfer_funds",
      "description": "Transfer $10,000 from account A to account B",
      "agent_id": "payment-agent",
      "run_id": "run_123",
      "status": "pending",
      "priority": "high",
      "risk_level": "high",
      "estimated_cost_usd": 0.10,
      "action_inputs": {
        "from_account": "acct_123",
        "to_account": "acct_456",
        "amount_usd": 10000.0
      },
      "context": {},
      "timeout_seconds": 600,
      "created_at": "2024-12-28T14:30:00Z",
      "expires_at": "2024-12-28T14:40:00Z",
      "time_remaining_seconds": 480
    }
  ],
  "total": 3
}

Get approval details

GET /api/v1/approvals/{id}
Returns full approval details including decision history.

Approve action

POST /api/v1/approvals/{id}/approve
Request body:
{
  "approver_email": "manager@company.com",
  "approver_name": "Jane Manager",
  "notes": "Verified with customer - approved"
}
Response:
{
  "id": "approval_abc123",
  "status": "approved",
  "decision": {
    "status": "approved",
    "approver_email": "manager@company.com",
    "approver_name": "Jane Manager",
    "notes": "Verified with customer - approved",
    "decided_at": "2024-12-28T14:35:00Z",
    "decision_time_seconds": 300
  },
  "updated_at": "2024-12-28T14:35:00Z"
}

Reject action

POST /api/v1/approvals/{id}/reject
Request body:
{
  "approver_email": "security@company.com",
  "approver_name": "John Security",
  "notes": "Transfer amount exceeds daily limit - rejected"
}

Request more information

POST /api/v1/approvals/{id}/request-info
Request body:
{
  "approver_email": "compliance@company.com",
  "message": "Please provide customer authorization document"
}
Status changes to info_requested. SDK must respond with additional context.

Respond to info request (SDK)

POST /api/v1/approvals/{id}/respond
Request body:
{
  "response_text": "Customer authorization document uploaded to case #12345"
}
Status returns to pending for approver to review again.

Poll approval status (SDK)

GET /api/v1/approvals/{id}/poll
SDK polls this endpoint to check if decision has been made: Response:
{
  "id": "approval_abc123",
  "status": "approved",
  "decision": {
    "status": "approved",
    "approver_email": "manager@company.com",
    "notes": "Approved",
    "decided_at": "2024-12-28T14:35:00Z"
  }
}

Cancel approval (SDK)

POST /api/v1/approvals/{id}/cancel
SDK can cancel pending approvals if circumstances change:
curl -X POST \
  -H "Authorization: Bearer $TOKEN" \
  "https://platform.agentsentinel.dev/api/v1/approvals/approval_abc123/cancel"

Check if action requires approval

POST /api/v1/approvals/check
Pre-flight check to determine if an action would require approval: Request body:
{
  "action_name": "delete_user_data",
  "agent_id": "cleanup-agent",
  "estimated_cost_usd": 0.0
}
Response:
{
  "requires_approval": true,
  "reason": "Action 'delete_user_data' is in the approval_required_actions list",
  "policy_id": "policy_123",
  "policy_name": "Data Safety"
}

Approval statistics

GET /api/v1/approvals/stats
Returns aggregate approval metrics:
{
  "total_approvals": 456,
  "by_status": {
    "pending": 12,
    "approved": 234,
    "rejected": 45,
    "expired": 23,
    "cancelled": 5,
    "info_requested": 3
  },
  "by_priority": {
    "critical": 34,
    "high": 123,
    "medium": 234,
    "low": 65
  },
  "by_risk_level": {
    "critical": 23,
    "high": 145,
    "medium": 234,
    "low": 54,
    "minimal": 0
  },
  "avg_decision_time_seconds": 287.5,
  "approval_rate": 0.84,
  "rejection_rate": 0.16
}

Priority levels

PriorityDescriptionUse case
criticalRequires immediate attentionProduction incidents, high-value transactions
highShould be reviewed within hoursImportant operations, customer requests
mediumNormal priorityRoutine operations
lowCan waitNon-urgent actions, batch operations

Risk levels

RiskDescription
criticalCatastrophic impact if approved incorrectly
highSevere impact (financial, security, compliance)
mediumModerate impact
lowMinor impact
minimalNegligible impact

Approval statuses

StatusDescription
pendingAwaiting human decision
approvedHuman approved - action can proceed
rejectedHuman rejected - action blocked
expiredTimeout exceeded with no decision
cancelledSDK cancelled the request
info_requestedApprover needs more context

Timeout behavior

When an approval expires:
  • Status changes to expired
  • SDK receives TimeoutError
  • Action is not executed
  • Intervention is created with type APPROVAL_REQUIRED, outcome BLOCKED

Real-time updates

Approvals support WebSocket real-time updates:
// Web console subscribes to approval events
ws.send(JSON.stringify({
  type: 'subscribe',
  channel: 'approvals'
}));

// Receive updates
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  if (data.event_type === 'approval_created') {
    // Show new approval notification
  }
  if (data.event_type === 'approval_expired') {
    // Mark approval as expired
  }
};

Web console workflow

Approvers use the web console to:
  1. Navigate to Approvals page
  2. See pending approvals with expiration countdown
  3. Click “Review” to see full details:
    • Action description and context
    • Risk and priority levels
    • Estimated cost
    • Input parameters
    • Agent information
  4. Take action:
    • Approve with optional notes
    • Reject with reason
    • Request Info to ask agent for more context
  5. View decision history in “Decision History” tab

Best practices

Set appropriate timeouts: Critical actions should have short timeouts (5-10 min), routine actions can have longer timeouts (1-24 hours).
Use priority and risk levels: Help approvers triage - critical/high priority items should notify immediately (email, Slack, etc.).
Provide detailed descriptions: Include enough context so approvers can make informed decisions without requesting more info.
Handle expired approvals: SDKs must handle TimeoutError gracefully - don’t assume approvals will be granted within timeout.
Monitor approval rates: Low approval rates (< 70%) may indicate agents attempting inappropriate actions - review agent logic.

Example: Full workflow

# SDK side
from agent_sentinel import guarded_action, ApprovalClient, ApprovalStatus, TimeoutError

client = ApprovalClient(
    platform_url="https://platform.agentsentinel.dev",
    api_token="as_your_api_key"
)

@guarded_action(
    name="transfer_funds",
    cost_usd=0.10,
    requires_human_approval=True
)
def transfer_funds(from_acct, to_acct, amount):
    # This triggers approval workflow automatically
    response = client.request_approval_sync(
        action_name="transfer_funds",
        description=f"Transfer ${amount} from {from_acct} to {to_acct}",
        priority="high",
        risk_level="high",
        timeout_seconds=600,
        action_inputs={"from_acct": from_acct, "to_acct": to_acct, "amount": amount}
    )

    if response.status == ApprovalStatus.APPROVED:
        # Execute transfer
        return execute_transfer(from_acct, to_acct, amount)
    elif response.status == ApprovalStatus.REJECTED:
        raise Exception(f"Transfer rejected: {response.notes}")
    elif response.status == ApprovalStatus.EXPIRED:
        raise TimeoutError("Approval timed out")

# Human side (web console or API)
# GET /api/v1/approvals/pending → see request
# POST /api/v1/approvals/approval_abc123/approve → approve it
# SDK polls and receives approval → transfer executes

See also