Skip to main content

Approval Workflows

FieldValue
Document IDASCEND-GOV-002
Version1.0.0
Last UpdatedDecember 19, 2025
AuthorAscend Engineering Team
PublisherOW-KAI Technologies Inc.
ClassificationEnterprise Client Documentation
ComplianceSOC 2 CC6.1/CC6.2, PCI-DSS 7.1/8.3, HIPAA 164.312, NIST 800-53 AC-2/SI-4

Reading Time: 10 minutes | Skill Level: Intermediate

Overview

Approval workflows ensure human oversight for AI agent actions. Based on risk assessment and policies, actions can be auto-approved, queued for approval, or escalated to security teams.

Workflow Types

┌─────────────────────────────────────────────────────────────────────────────────────┐
│ APPROVAL WORKFLOW TYPES │
├─────────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────────────┐ │
│ │ RISK-BASED WORKFLOW │ │
│ │ │ │
│ │ Risk 0-30 Risk 30-60 Risk 60-80 Risk 80+ │ │
│ │ ┌───────┐ ┌───────┐ ┌───────┐ ┌───────┐ │ │
│ │ │ AUTO │ │SINGLE │ │ MULTI │ │ESCALATE│ │ │
│ │ │APPROVE│ │APPROVE│ │APPROVE│ │ │ │ │
│ │ │ │ │ │ │ │ │Security│ │ │
│ │ │ ✓ │ │ ? → ✓ │ │??→ ✓ │ │ Team │ │ │
│ │ │ │ │ │ │ │ │ Review │ │ │
│ │ └───────┘ └───────┘ └───────┘ └───────┘ │ │
│ │ │ │
│ │ Immediate 1 Approver 2+ Approvers Security │ │
│ │ No wait ~Minutes ~Minutes-Hours ~Hours │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘

Workflow Configuration

Agent-Level Configuration

# Configure approval thresholds per agent
{
"agent_id": "finance-bot-001",
"auto_approve_below": 30, # Auto-approve if risk < 30
"max_risk_threshold": 80, # Escalate if risk > 80
"requires_mfa_above": 70 # MFA required for risk > 70
}

REST API Configuration

curl -X PUT "https://pilot.owkai.app/api/agents/registry/finance-bot-001" \
-H "Authorization: Bearer owkai_..." \
-H "Content-Type: application/json" \
-d '{
"auto_approve_below": 30,
"max_risk_threshold": 80,
"requires_mfa_above": 70,
"alert_on_high_risk": true,
"alert_recipients": ["security@company.com"],
"webhook_url": "https://hooks.company.com/approvals"
}'

Pending Actions

Action States

StateDescriptionNext States
pendingAwaiting approvalapproved, denied
approvedExecution allowedcompleted, failed
deniedExecution blocked(terminal)
completedAction succeeded(terminal)
failedAction failed(terminal)
expiredApproval timeout(terminal)

List Pending Actions

curl "https://pilot.owkai.app/api/v1/actions/pending" \
-H "Authorization: Bearer owkai_..."

Response:

{
"pending_actions": [
{
"action_id": 12345,
"agent_id": "data-processor-001",
"action_type": "database.delete",
"resource": "customers.inactive",
"risk_score": 65,
"risk_level": "high",
"submitted_at": "2025-12-15T10:25:00Z",
"waiting_since_minutes": 5,
"requires_approvers": 1,
"approvals_received": 0,
"approval_deadline": "2025-12-15T11:25:00Z"
}
],
"total_pending": 1
}

Get Action Details

curl "https://pilot.owkai.app/api/v1/actions/12345" \
-H "Authorization: Bearer owkai_..."

Response:

{
"action_id": 12345,
"agent_id": "data-processor-001",
"agent_name": "Data Processor",
"action_type": "database.delete",
"resource": "customers.inactive",
"status": "pending",
"risk_assessment": {
"risk_score": 65,
"risk_level": "high",
"factors": {
"environment": "production",
"action_type_weight": 25,
"resource_multiplier": 1.2,
"data_classification": "pii"
}
},
"context": {
"user_id": "system",
"session_id": "abc123",
"request_origin": "scheduled_job"
},
"workflow": {
"type": "single_approval",
"requires_mfa": true,
"approvers_required": 1,
"approvers_received": 0,
"deadline": "2025-12-15T11:25:00Z"
},
"submitted_at": "2025-12-15T10:25:00Z",
"history": []
}

Approving/Denying Actions

Approve Action

curl -X POST "https://pilot.owkai.app/api/v1/actions/12345/approve" \
-H "Authorization: Bearer owkai_..." \
-H "Content-Type: application/json" \
-d '{
"reason": "Reviewed and confirmed - scheduled maintenance task",
"mfa_token": "123456"
}'

Response:

{
"success": true,
"action_id": 12345,
"status": "approved",
"approved_by": "admin@company.com",
"approved_at": "2025-12-15T10:30:00Z",
"message": "Action approved. Agent can proceed with execution."
}

Deny Action

curl -X POST "https://pilot.owkai.app/api/v1/actions/12345/deny" \
-H "Authorization: Bearer owkai_..." \
-H "Content-Type: application/json" \
-d '{
"reason": "Not authorized for production deletion during business hours"
}'

Response:

{
"success": true,
"action_id": 12345,
"status": "denied",
"denied_by": "admin@company.com",
"denied_at": "2025-12-15T10:30:00Z",
"denial_reason": "Not authorized for production deletion during business hours"
}

Multi-Approval Workflows

Configuration

# High-risk actions require multiple approvers
{
"agent_id": "finance-bot-001",
"policies": [
{
"policy_name": "Multi-Approval for High-Value",
"conditions": {"amount_above": 50000},
"policy_action": "require_approval",
"action_params": {
"approvers_required": 2,
"approver_roles": ["finance_manager", "security"],
"timeout_hours": 4
}
}
]
}

Multi-Approval Status

{
"action_id": 12345,
"workflow": {
"type": "multi_approval",
"approvers_required": 2,
"approvals": [
{
"approver": "finance-manager@company.com",
"approved_at": "2025-12-15T10:30:00Z",
"role": "finance_manager"
}
],
"remaining_approvals": 1,
"waiting_for_roles": ["security"]
}
}

SDK Integration

Submit and Wait

from ascend import AscendClient

client = AscendClient(api_key="owkai_...")

# Submit action
result = client.evaluate_action(
action_type="financial.transfer",
resource="wire_transfer",
parameters={"amount": 75000, "destination": "ACME Corp"}
)

if result.is_pending():
print(f"Action {result.action_id} requires approval")
print(f"Risk Score: {result.risk_score}")
print(f"Risk Level: {result.risk_level}")

# Wait for approval (with timeout)
final = client.wait_for_decision(
result.action_id,
timeout_ms=300000 # 5 minutes
)

if final.is_approved():
print("Approved! Proceeding with transfer...")
execute_transfer()
client.log_action_completed(result.action_id)
else:
print(f"Denied: {final.reason}")

Polling Pattern

import time

result = client.evaluate_action(...)

if result.is_pending():
action_id = result.action_id

while True:
status = client.get_action_status(action_id)

if status.is_approved():
execute_action()
break
elif status.is_denied():
print(f"Denied: {status.reason}")
break
elif status.is_expired():
print("Approval timed out")
break

time.sleep(10) # Poll every 10 seconds

Webhook Notifications

Configure Webhooks

curl -X PUT "https://pilot.owkai.app/api/agents/registry/my-agent" \
-H "Authorization: Bearer owkai_..." \
-d '{
"webhook_url": "https://hooks.company.com/ascend/approvals",
"alert_on_high_risk": true
}'

Webhook Payload

{
"event_type": "action.pending_approval",
"timestamp": "2025-12-15T10:25:00Z",
"action": {
"action_id": 12345,
"agent_id": "finance-bot-001",
"action_type": "financial.transfer",
"resource": "wire_transfer",
"risk_score": 75,
"risk_level": "high"
},
"workflow": {
"type": "single_approval",
"approvers_required": 1,
"deadline": "2025-12-15T11:25:00Z"
},
"approval_url": "https://dashboard.owkai.app/approvals/12345"
}

Webhook Events

EventDescription
action.pending_approvalAction awaiting approval
action.approvedAction approved
action.deniedAction denied
action.expiredApproval timeout
action.escalatedAction escalated to security

Escalation

Automatic Escalation

Actions exceeding risk thresholds are automatically escalated:

# Agent configuration
{
"max_risk_threshold": 80,
"autonomous_escalation_webhook_url": "https://pagerduty.com/ascend",
"autonomous_escalation_email": "security@company.com"
}

Escalation Flow

Risk Score > max_risk_threshold


┌─────────────────────────┐
│ ESCALATION TRIGGERED │
│ │
│ 1. Webhook notification│
│ 2. Email notification │
│ 3. Dashboard alert │
│ 4. Audit log entry │
└───────────┬─────────────┘


┌─────────────────────────┐
│ SECURITY TEAM REVIEW │
│ │
│ • Full context review │
│ • Risk analysis │
│ • Approve or deny │
└─────────────────────────┘

Timeout Handling

Configure Timeouts

{
"policies": [
{
"policy_name": "Approval Timeout",
"conditions": {"risk_level": "high"},
"policy_action": "require_approval",
"action_params": {
"timeout_hours": 1,
"timeout_action": "deny" # or "escalate"
}
}
]
}

Timeout Actions

Timeout ActionDescription
denyAuto-deny after timeout (default)
escalateEscalate to security team
auto_approveAuto-approve (use with caution)

Approval Dashboard

Dashboard Features

  • Pending queue — All actions awaiting approval
  • Risk breakdown — Visual risk factor analysis
  • Context details — Full action context
  • Quick actions — One-click approve/deny
  • Bulk operations — Handle multiple actions
  • History — Past approval decisions

Filtering

GET /api/v1/actions/pending?
agent_id=finance-bot-001&
risk_level=high&
action_type=financial.transfer&
submitted_after=2025-12-15T00:00:00Z

Best Practices

1. Set Appropriate Thresholds

# Production: stricter thresholds
{
"auto_approve_below": 20, # Lower auto-approve
"max_risk_threshold": 60 # Lower escalation threshold
}

# Development: relaxed thresholds
{
"auto_approve_below": 50,
"max_risk_threshold": 90
}

2. Configure Notifications

# Always notify for high-risk
{
"alert_on_high_risk": True,
"alert_recipients": ["security@company.com", "oncall@company.com"],
"webhook_url": "https://slack.com/api/webhooks/..."
}

3. Set Reasonable Timeouts

# Critical actions: shorter timeout
{
"timeout_hours": 1,
"timeout_action": "escalate"
}

# Routine actions: longer timeout
{
"timeout_hours": 24,
"timeout_action": "deny"
}

4. Use Multi-Approval for Sensitive Actions

# Financial actions over threshold
{
"conditions": {"amount_above": 100000},
"action_params": {
"approvers_required": 3,
"approver_roles": ["finance", "legal", "security"]
}
}

Next Steps


Document Version: 1.0.0 | Last Updated: December 2025