Skip to main content

Your First Governed Action

This guide walks through the complete governance lifecycle for an AI agent action.

Overview​

Every action an AI agent takes flows through five stages:

  1. Submit — Agent calls evaluate_action()
  2. Score — ASCEND calculates risk using CVSS v3.1, NIST 800-30, and MITRE ATT&CK
  3. Decide — Auto-approve, queue for review, or deny based on your policies
  4. Review — Human approver acts on pending actions in the dashboard
  5. Execute — Agent proceeds only on approval

1. Submit an Action​

Agent must be registered

Before submitting governed actions, your agent must be registered and activated in the Agent Registry. See Register Your Agent.

from ascend import AscendClient, FailMode, Decision

client = AscendClient(
api_key="owkai_your_key_here",
api_url="https://pilot.owkai.app",
agent_id="finance-bot",
agent_name="Finance Bot",
fail_mode=FailMode.CLOSED,
)

result = client.evaluate_action(
action_type="database_write",
resource="customer_financial_records",
resource_id="acct-12345",
context={
"environment": "production",
"data_sensitivity": "high_sensitivity",
"business_justification": "Customer requested account update",
},
wait_for_decision=False,
)

print(f"Decision: {result.decision}")
print(f"Risk Score: {result.risk_score}/100")
print(f"CVSS Score: {result.cvss_score}")
print(f"MITRE Tactic: {result.mitre_tactic}")
print(f"NIST Control: {result.nist_control}")

2. Understand the Risk Score​

ASCEND scores every action using three industry frameworks:

FrameworkWhat It Evaluates
CVSS v3.1Attack vector, complexity, impact
NIST 800-30Threat likelihood, business impact
MITRE ATT&CKTactic and technique classification

The composite score (0-100) determines the decision:

Score RangeDecisionMeaning
Below auto-approve thresholdALLOWEDProceeds automatically
Between thresholdsPENDINGHuman review required
Above max thresholdDENIEDBlocked by policy

Thresholds are configured per agent in the Agent Registry.

3. Handle Each Decision​

from ascend import Decision

if result.decision == Decision.ALLOWED:
# Proceed immediately
execute_database_write()

elif result.decision == Decision.PENDING:
# Wait for human approval
print(f"Queued for review. Action ID: {result.action_id}")

final = client.wait_for_decision(
action_id=result.action_id,
timeout=300,
poll_interval=5.0,
)

if final.decision == Decision.ALLOWED:
execute_database_write()
else:
print(f"Not approved: {final.reason}")

elif result.decision == Decision.DENIED:
# Blocked — do not proceed
print(f"Action denied: {result.reason}")
log_denial(result.action_id, result.reason)

4. Check Action Status​

Poll the status of any action by its ID:

status = client.get_action_status(
action_id=result.action_id,
)
print(f"Current decision: {status.decision}")

5. MCP Server Governance​

For agents using MCP servers, pass the server name to trigger Layer 13 enforcement:

result = client.evaluate_action(
action_type="tool_call",
resource="market_data",
mcp_server_name="bloomberg-mcp",
wait_for_decision=False,
)

print(result.mcp_governance["server_registered"])

Unregistered or deactivated MCP servers are denied with HTTP 403.

6. Model Registry Enforcement​

For actions involving AI models, pass the model identifier to enforce compliance:

result = client.evaluate_action(
action_type="model_inference",
resource="underwriting_pipeline",
model_id="llama-3-fine-tuned",
wait_for_decision=False,
)

governance = result.model_governance
print(governance["compliance_status"])
# approved | partially_approved | denied

7. Error Handling​

import time
from ascend.exceptions import (
AuthenticationError,
ConnectionError,
RateLimitError,
ValidationError,
TimeoutError,
)

try:
result = client.evaluate_action(
action_type="database_write",
resource="customer_db",
)
except AuthenticationError:
# Invalid or expired API key
raise
except ConnectionError:
# ASCEND unreachable — fail_mode applies
raise
except RateLimitError:
# Back off and retry
time.sleep(60)
except TimeoutError:
# Decision not reached within timeout
log_timeout(action_id)
except ValidationError as e:
# Invalid request parameters
print(f"Fix request: {e}")

8. Webhook Configuration​

Receive real-time notifications instead of polling:

webhook = client.configure_webhook(
url="https://your-system.com/ascend/events",
events=["action.pending", "action.approved", "action.denied", "agent.blocked"],
secret="your_webhook_secret",
)
print(f"Webhook ID: {webhook.webhook_id}")

Next Steps​