Approval Workflows
When a policy returns require_approval, the action enters the approval workflow where a human must explicitly approve or deny it before it can execute.
How Approvals Work
Approval Properties
Each approval request includes:
| Property | Description |
|---|---|
id | Unique approval identifier |
action_request_id | The action awaiting approval |
status | pending, approved, denied, expired |
expires_at | When the approval request expires |
created_at | When the request was created |
decided_by | Who approved/denied (if decided) |
decision_reason | Reason provided for the decision |
Configuring Approval Timeouts
Set default expiration in organization settings:
// Default: 24 hours
// Range: 1 hour to 7 days
await api.put('/org/settings', {
approval_timeout_hours: 48
});
Or per-action in your policy:
decision = "require_approval" {
input.action.tool == "http_proxy"
contains(input.action.params.url, "production")
}
approval_config = {
"timeout_hours": 4,
"notify_channels": ["#ops-approvals"],
"required_approvers": 2
} {
decision == "require_approval"
}
Notification Channels
Configure how approvers are notified:
Default notification method. Includes:
- Action summary
- Risk level
- Approve/Deny links
- Context from the agent
Slack
Real-time notifications with interactive buttons:
// Configure Slack integration
await api.post('/integrations/slack', {
webhook_url: 'https://hooks.slack.com/...',
channels: {
approvals: '#agent-approvals',
high_risk: '#security-alerts'
}
});
Dashboard
All pending approvals visible in the web dashboard at Approvals → Pending.
Approval Templates
Create reusable approval configurations:
// Create a template
await api.post('/approval-templates', {
name: 'Financial Review',
required_approvers: 2,
timeout_hours: 4,
notify_channels: ['email', 'slack'],
escalation: {
after_hours: 2,
escalate_to: ['finance-team']
},
auto_deny_conditions: [
{ field: 'risk_level', equals: 'critical' }
]
});
Apply templates in policies:
approval_template = "financial-review" {
decision == "require_approval"
input.action.context.department == "finance"
}
Bulk Approvals
Approve multiple related actions at once:
// Approve all actions from a specific batch
await api.post('/approvals/bulk', {
filter: {
agent_id: 'batch-processor',
created_after: '2024-01-15T00:00:00Z'
},
decision: 'approved',
reason: 'Batch approved after security review'
});
Delegated Approvals
Allow agents to auto-approve under certain conditions:
# Auto-approve if action matches a pre-approved template
decision = "allow" {
input.action.context.template_id
approved_template := data.approved_templates[input.action.context.template_id]
matches_template(input.action, approved_template)
}
Escalation
Configure automatic escalation for unhandled approvals:
await api.put('/approval-settings', {
escalation: {
enabled: true,
initial_timeout_hours: 2,
escalation_chain: [
{ role: 'team_lead', timeout_hours: 2 },
{ role: 'manager', timeout_hours: 4 },
{ role: 'admin', timeout_hours: 24 }
],
final_action: 'deny' // or 'allow'
}
});
Approval API
List Pending Approvals
GET /api/v1/approvals?status=pending
Get Approval Details
GET /api/v1/approvals/{id}
Approve or Deny
POST /api/v1/approvals/{id}/decide
{
"decision": "approved",
"reason": "Reviewed and confirmed safe"
}
Audit Trail
Every approval decision is logged:
{
"event_type": "approval.decision",
"approval_id": "apr-123",
"action_request_id": "act-456",
"decided_by": "user@example.com",
"decision": "approved",
"reason": "Reviewed and confirmed safe",
"timestamp": "2024-01-15T10:35:00Z"
}
Best Practices
Tip: Set appropriate timeouts. Critical actions should expire quickly (1-4 hours) while batch operations can have longer windows (24-48 hours).
Tip: Use escalation. Never let approvals expire without action—escalate to ensure someone reviews them.
Tip: Provide context. Include
purposeanduser_idin action context so approvers understand what they're approving.
Next Steps
- Slack Integration — Set up real-time Slack notifications
- Approval Templates — Create reusable approval workflows