> ## Documentation Index
> Fetch the complete documentation index at: https://docs.caged.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Human-in-the-Loop Approvals

> Pause agents and require human approval before risky actions

# Human-in-the-Loop Approvals

When a policy rule triggers with action `pause`, the sandbox is frozen and an approval request is created. A human must approve or reject before the agent can continue.

## How It Works

```mermaid theme={null}
sequenceDiagram
    Agent->>Policy Engine: Attempt risky action
    Policy Engine->>Approval Gate: Rule triggers "pause"
    Approval Gate->>Sandbox: Pause execution
    Approval Gate->>Human: Send notification
    Human->>Approval Gate: Approve / Reject
    alt Approved
        Approval Gate->>Sandbox: Resume
    else Rejected
        Approval Gate->>Sandbox: Keep paused
    end
```

## Notification Channels

Approval requests are delivered through multiple channels:

| Channel       | Description                                     |
| ------------- | ----------------------------------------------- |
| **Dashboard** | In-app approval queue at `/dashboard/approvals` |
| **Slack**     | Interactive message with Approve/Reject buttons |
| **Email**     | Email with one-click approve/reject links       |
| **Webhook**   | Custom HTTP callback for external systems       |

## Slack Integration

When configured, approval requests appear as Slack messages with interactive buttons:

* **Approve** — resumes the sandbox immediately
* **Reject** — keeps the sandbox paused
* **View Details** — opens the dashboard approval page

To set up: add your Slack webhook URL in Dashboard → Settings → Integrations.

## SLA Timers & Escalation

Every approval has an SLA deadline (default: 30 minutes). If no decision is made:

1. **Escalation rules** fire based on timeout
2. Additional channels are notified
3. Auto-decisions can be configured (auto-approve, auto-reject, or destroy sandbox)

### Escalation Rule Example

```yaml theme={null}
escalation_rules:
  - name: "Auto-reject after 1h"
    timeout: 1h
    action: auto_reject
  - name: "Kill sandbox after 2h"
    timeout: 2h
    action: kill
```

## API

```bash theme={null}
# List pending approvals
curl -H "Authorization: Bearer $TOKEN" https://api.caged.dev/v1/approvals/pending

# Approve a request
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -d '{"decided_by":"josh@example.com","note":"Looks safe"}' \
  https://api.caged.dev/v1/approvals/{id}/approve

# Reject a request
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -d '{"decided_by":"josh@example.com","note":"Too risky"}' \
  https://api.caged.dev/v1/approvals/{id}/reject

# Get SLA report
curl -H "Authorization: Bearer $TOKEN" \
  https://api.caged.dev/v1/approvals/sla-report?period=7d
```

## Dashboard

The approvals page at `/dashboard/approvals` shows:

* Pending requests with SLA countdown timers
* Approve/Reject buttons for each request
* Full history of past decisions
* Policy name, rule, scope, and action details
