Your First Governed Action
| Field | Value |
|---|---|
| Document ID | ASCEND-START-002 |
| Version | 1.0.0 |
| Last Updated | December 19, 2025 |
| Author | Ascend Engineering Team |
| Publisher | OW-KAI Technologies Inc. |
| Classification | Enterprise Client Documentation |
| Compliance | SOC 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: Beginner
Overview
This tutorial walks you through submitting your first governed action, understanding the response, and handling different decision outcomes. By the end, you'll have a complete working integration.
Prerequisites
Before you begin, ensure you have:
- Completed the Quick Start guide
- An API key configured
- Python 3.8+ with
ascend-sdkinstalled
Step 1: Set Up Your Environment
Create a new Python file for this tutorial:
# tutorial.py
import os
from ascend import AscendClient, AgentAction
# Load API key from environment (recommended)
API_KEY = os.environ.get("ASCEND_API_KEY", "owkai_your_key_here")
# Initialize the client
# Source: sdk/ascend-sdk-python/ascend/client.py:324
client = AscendClient(
api_key=API_KEY,
agent_id="tutorial-agent",
agent_name="Tutorial Agent",
environment="sandbox" # Use sandbox for testing
)
print("Client initialized successfully!")
Never hardcode API keys. Use environment variables:
export ASCEND_API_KEY="owkai_your_key_here"
Step 2: Create a Low-Risk Action
Let's start with a simple, low-risk action that will be auto-approved:
# Low-risk action: Reading public data
# Source: sdk/ascend-sdk-python/ascend/client.py:368
low_risk_action = AgentAction(
action_type="database_read",
description="Read list of public product categories",
parameters={
"table": "product_categories",
"operation": "SELECT",
"columns": ["id", "name", "description"],
"data_classification": "public"
}
)
# Submit the action
result = client.submit_action(low_risk_action)
print(f"""
LOW-RISK ACTION RESULT
======================
Action ID: {result.action_id}
Decision: {result.decision}
Risk Score: {result.risk_score}
Risk Level: {result.risk_level}
""")
Expected Output:
LOW-RISK ACTION RESULT
======================
Action ID: act_abc123xyz
Decision: APPROVED
Risk Score: 2.1
Risk Level: LOW
Understanding Low-Risk Response
For low-risk actions, ASCEND:
- Evaluates the risk (score 2.1 = LOW)
- Checks Smart Rules (none triggered)
- Auto-approves based on workflow config
- Logs to audit trail
- Returns immediately
Step 3: Create a Medium-Risk Action
Now let's try an action that requires more scrutiny:
# Medium-risk action: Accessing customer data
medium_risk_action = AgentAction(
action_type="database_read",
description="Read customer contact information for support ticket",
parameters={
"table": "customers",
"operation": "SELECT",
"columns": ["id", "name", "email", "phone"],
"data_classification": "pii",
"purpose": "customer_support"
},
context={
"ticket_id": "TICKET-12345",
"requester": "support-agent@company.com"
}
)
result = client.submit_action(medium_risk_action)
print(f"""
MEDIUM-RISK ACTION RESULT
=========================
Action ID: {result.action_id}
Decision: {result.decision}
Risk Score: {result.risk_score}
Risk Level: {result.risk_level}
CVSS Vector: {result.cvss_vector}
""")
# For medium risk, decision might be PENDING
if result.decision == "PENDING":
print(f"Pending Approvers: {result.pending_approvers}")
print(f"Approval URL: {result.approval_url}")
Expected Output:
MEDIUM-RISK ACTION RESULT
=========================
Action ID: act_def456xyz
Decision: APPROVED (or PENDING in strict mode)
Risk Score: 5.3
Risk Level: MEDIUM
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
Step 4: Create a High-Risk Action
High-risk actions typically require approval:
# High-risk action: Modifying customer data
high_risk_action = AgentAction(
action_type="database_write",
description="Update customer billing address",
parameters={
"table": "customers",
"operation": "UPDATE",
"affected_rows": 1,
"columns": ["billing_address", "billing_city", "billing_zip"],
"data_classification": "pii"
},
context={
"customer_id": "cust_789",
"change_reason": "Customer requested address update",
"verified_by": "phone_verification"
}
)
result = client.submit_action(high_risk_action)
print(f"""
HIGH-RISK ACTION RESULT
=======================
Action ID: {result.action_id}
Decision: {result.decision}
Risk Score: {result.risk_score}
Risk Level: {result.risk_level}
""")
Expected Output (Pending Approval):
HIGH-RISK ACTION RESULT
=======================
Action ID: act_ghi789xyz
Decision: PENDING
Risk Score: 7.2
Risk Level: HIGH
Step 5: Handle Pending Decisions
When an action requires approval, you have several options:
Option A: Wait for Decision
# Wait up to 5 minutes for approval
# Source: sdk/ascend-sdk-python/ascend/client.py:474
final_result = client.wait_for_decision(
action_id=result.action_id,
timeout_seconds=300, # 5 minutes
poll_interval=5 # Check every 5 seconds
)
if final_result.decision == "APPROVED":
print("Approval received - proceeding with action")
# Execute your action here
elif final_result.decision == "DENIED":
print(f"Action denied: {final_result.denial_reason}")
elif final_result.decision == "TIMEOUT":
print("Approval timed out - action not executed")
Option B: Check Status Later
# Store the action ID and check later
action_id = result.action_id
# ... later in your code or another process ...
# Source: sdk/ascend-sdk-python/ascend/client.py:451
status = client.get_action_status(action_id)
print(f"Current status: {status.decision}")
Option C: Use Webhooks
Configure a webhook to receive approval notifications:
# Configure webhook for your agent
# Source: sdk/python/owkai_sdk/client.py:984
client.configure_webhook(
url="https://your-app.com/webhooks/ascend",
events=["action.approved", "action.denied"],
secret="your_webhook_secret"
)
Step 6: Handle Denied Actions
Sometimes actions will be denied. Handle this gracefully:
# Example: Action denied by Smart Rule
denied_action = AgentAction(
action_type="database_delete",
description="Delete inactive user accounts",
parameters={
"table": "users",
"operation": "DELETE",
"affected_rows": 150
}
)
result = client.submit_action(denied_action)
if result.decision == "DENIED":
print(f"""
ACTION DENIED
=============
Reason: {result.denial_reason}
Rule ID: {result.rule_id}
Rule Name: {result.rule_name}
Suggested actions:
1. Review the triggering rule
2. Request an exception if appropriate
3. Modify the action to comply with policy
""")
Example Denial Response:
ACTION DENIED
=============
Reason: Bulk delete operations require manager approval
Rule ID: rule_no_bulk_delete
Rule Name: Block Bulk Deletions
Suggested actions:
1. Review the triggering rule
2. Request an exception if appropriate
3. Modify the action to comply with policy
Step 7: Complete Example
Here's a complete, production-ready example:
#!/usr/bin/env python3
"""
Complete ASCEND Integration Example
Demonstrates proper error handling and decision flow
"""
import os
import sys
from ascend import AscendClient, AgentAction
from ascend.exceptions import (
AscendConnectionError,
AscendAuthenticationError,
AscendRateLimitError
)
def main():
# Initialize client
try:
client = AscendClient(
api_key=os.environ["ASCEND_API_KEY"],
agent_id="production-agent",
agent_name="Production Data Agent",
environment="production"
)
except AscendAuthenticationError:
print("ERROR: Invalid API key")
sys.exit(1)
# Create action
action = AgentAction(
action_type="database_read",
description="Generate monthly sales report",
parameters={
"table": "orders",
"operation": "SELECT",
"date_range": "last_30_days"
}
)
# Submit and handle result
try:
result = client.submit_action(action)
if result.decision == "APPROVED":
print(f"✅ Approved (Risk: {result.risk_level})")
execute_report_generation()
elif result.decision == "PENDING":
print(f"⏳ Pending approval from: {result.pending_approvers}")
# Option 1: Wait
final = client.wait_for_decision(result.action_id, timeout_seconds=300)
if final.decision == "APPROVED":
execute_report_generation()
else:
print(f"❌ Not approved: {final.decision}")
elif result.decision == "DENIED":
print(f"❌ Denied: {result.denial_reason}")
except AscendConnectionError:
print("ERROR: Could not connect to ASCEND")
# Implement fallback behavior
except AscendRateLimitError:
print("ERROR: Rate limit exceeded, retry later")
def execute_report_generation():
"""Your actual business logic here"""
print("Executing report generation...")
# ... your code ...
if __name__ == "__main__":
main()
Verification
Run these commands to verify your integration:
# Set your API key
export ASCEND_API_KEY="owkai_your_key_here"
# Run the tutorial script
python tutorial.py
# Check the audit log via CLI
ascend actions list --agent-id tutorial-agent --limit 10
Expected output:
ID TYPE RISK DECISION TIME
act_abc123xyz database_read LOW APPROVED 2 min ago
act_def456xyz database_read MEDIUM APPROVED 1 min ago
act_ghi789xyz database_write HIGH PENDING just now
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
ASCEND_API_KEY not set | Missing environment variable | Run export ASCEND_API_KEY="..." |
| All actions DENIED | Overly strict rules | Check Smart Rules in dashboard |
| All actions PENDING | No auto-approve configured | Configure workflow for low-risk |
| Timeout errors | Network or rate limiting | Check connectivity, implement retry |
Next Steps
Congratulations! You've successfully integrated with ASCEND. Continue your journey:
- Python SDK — Full SDK reference
- Smart Rules — Create custom rules
- Agent Registry — Register and manage agents
Document Version: 1.0.0 | Last Updated: December 2025