Skip to main content

Agent Lifecycle Management

FieldValue
Document IDASCEND-AGENT-003
Version2026.04
Last UpdatedApril 2026
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: 8 minutes | Skill Level: Intermediate

Overview

Every agent progresses through defined lifecycle states. Understanding these states is critical for proper agent governance and compliance.

warning

Transitioning an agent to the suspended or retired state immediately blocks all pending and future actions. Ensure in-flight operations are accounted for before changing lifecycle state.

Lifecycle States

                            ┌─────────────────────────────────────────────────────────┐
│ AGENT LIFECYCLE STATES │
└─────────────────────────────────────────────────────────┘

┌─────────┐ ┌──────────────────┐ ┌─────────┐
│ DRAFT │───────▶│ PENDING_APPROVAL │───────▶│ ACTIVE │
└─────────┘ └──────────────────┘ └────┬────┘
│ │
│ ┌──────────┼──────────┐
│ │ │ │
│ ▼ │ ▼
│ ┌───────────┐ │ ┌─────────────┐
│ │ SUSPENDED │◀────┘ │ DEPRECATED │
│ └─────┬─────┘ └──────┬──────┘
│ │ │
│ │ │
│ ▼ ▼
│ ┌───────────┐ ┌───────────┐
└────────────────────────────▶│ RETIRED │◀─────────│ RETIRED │
└───────────┘ └───────────┘

State Definitions

# Source: models_agent_registry.py:38
class AgentStatus(str, enum.Enum):
"""Lifecycle status of registered agents."""
DRAFT = "draft" # Being configured
PENDING_APPROVAL = "pending_approval" # Awaiting admin approval
ACTIVE = "active" # Operational
SUSPENDED = "suspended" # Temporarily disabled
DEPRECATED = "deprecated" # Scheduled for removal
RETIRED = "retired" # No longer operational

State Details

StateActions AllowedTransitions ToDescription
draftNonepending_approval, retiredInitial configuration state
pending_approvalNoneactive, draft, retiredAwaiting admin review
activeFullsuspended, deprecatedFully operational
suspendedNoneactive, retiredTemporarily disabled
deprecatedRead-onlyretiredScheduled for removal
retiredNoneNone (terminal)Decommissioned

State Transitions

Draft to Pending Approval

Submit agent for review:

curl -X POST "https://pilot.owkai.app/api/agents/registry/my-agent-001/submit" \
-H "Authorization: Bearer owkai_..."

Pending Approval to Active

Admin approves agent:

curl -X POST "https://pilot.owkai.app/api/agents/registry/my-agent-001/activate" \
-H "Authorization: Bearer owkai_..."
# Source: services/agent_registry_service.py:936
def activate_agent(db, organization_id, agent_id, approved_by):
"""Activate an agent for production use."""
agent = get_agent(db, organization_id, agent_id=agent_id)

if agent.status not in [
AgentStatus.DRAFT.value,
AgentStatus.PENDING_APPROVAL.value,
AgentStatus.SUSPENDED.value
]:
raise ValueError(f"Cannot activate agent in status: {agent.status}")

previous_status = agent.status
agent.status = AgentStatus.ACTIVE.value
agent.approved_at = datetime.now(UTC)
agent.approved_by = approved_by

# Log activation for compliance
log_activity(agent, "activated", approved_by)

return agent

Active to Suspended

Manual suspension:

curl -X POST "https://pilot.owkai.app/api/agents/registry/my-agent-001/suspend" \
-H "Authorization: Bearer owkai_..." \
-H "Content-Type: application/json" \
-d '{
"reason": "Security review required"
}'
# Source: services/agent_registry_service.py:984
def suspend_agent(db, organization_id, agent_id, suspended_by, reason=None):
"""Suspend an agent (emergency disable)."""
agent = get_agent(db, organization_id, agent_id=agent_id)

previous_status = agent.status
agent.status = AgentStatus.SUSPENDED.value
agent.updated_at = datetime.now(UTC)
agent.updated_by = suspended_by

# Log suspension with reason for compliance
log_activity(
agent, "suspended", suspended_by,
previous_state={"status": previous_status},
new_state={"status": "suspended", "reason": reason}
)

logger.warning(f"Agent SUSPENDED: {agent_id} - Reason: {reason}")
return agent

Auto-Suspension

Agents can be automatically suspended when triggers are met:

# Source: services/agent_registry_service.py:522
def check_auto_suspend_triggers(db, agent):
"""Check if any auto-suspend conditions are met."""

if not agent.auto_suspend_enabled:
return {"should_suspend": False}

# Check error rate trigger
if agent.auto_suspend_on_error_rate is not None:
if agent.error_rate_percent >= agent.auto_suspend_on_error_rate * 100:
return {
"should_suspend": True,
"reason": f"Error rate {agent.error_rate_percent:.1f}% exceeds threshold",
"trigger": "error_rate"
}

# Check offline duration trigger
if agent.auto_suspend_on_offline_minutes is not None:
if agent.last_heartbeat:
minutes_offline = (now - agent.last_heartbeat).total_seconds() / 60
if minutes_offline > agent.auto_suspend_on_offline_minutes:
return {
"should_suspend": True,
"reason": f"Agent offline for {minutes_offline:.0f} minutes",
"trigger": "offline_duration"
}

# Check budget exceeded trigger
if agent.auto_suspend_on_budget_exceeded:
if agent.current_daily_spend_usd >= agent.max_daily_budget_usd:
return {
"should_suspend": True,
"reason": f"Budget exceeded: ${agent.current_daily_spend_usd:.2f}",
"trigger": "budget_exceeded"
}

return {"should_suspend": False}

Suspended to Active

Reactivate after suspension:

curl -X POST "https://pilot.owkai.app/api/agents/registry/my-agent-001/activate" \
-H "Authorization: Bearer owkai_..." \
-H "Content-Type: application/json" \
-d '{
"reason": "Security review completed, cleared for operation"
}'

Active to Deprecated

Schedule for removal:

curl -X POST "https://pilot.owkai.app/api/agents/registry/my-agent-001/deprecate" \
-H "Authorization: Bearer owkai_..." \
-H "Content-Type: application/json" \
-d '{
"reason": "Replaced by v2 agent",
"retirement_date": "2025-12-31"
}'

Any State to Retired

Permanent decommission:

curl -X DELETE "https://pilot.owkai.app/api/agents/registry/my-agent-001" \
-H "Authorization: Bearer owkai_..." \
-H "Content-Type: application/json" \
-d '{
"reason": "Agent decommissioned"
}'

State Enforcement

Action Execution Check

# Source: services/agent_registry_service.py:1177
def evaluate_policies(db, organization_id, agent_id, action_context):
"""Evaluate policies including lifecycle state check."""

agent = get_agent(db, organization_id, agent_id=agent_id)

if not agent:
return {"decision": "deny", "reason": "Agent not registered"}

# Check agent status FIRST
if agent.status != AgentStatus.ACTIVE.value:
return {
"decision": "deny",
"reason": f"Agent not active (status: {agent.status})",
"policies": []
}

# Continue with policy evaluation...

Status Check Response

When an inactive agent attempts an action:

{
"decision": "deny",
"reason": "Agent not active (status: suspended)",
"action_id": null,
"risk_score": null,
"policies": [],
"agent_status": "suspended",
"reactivation_required": true
}

Approval Workflow

Require Approval for Activation

For organizations requiring approval before activation:

# Registration creates agent in DRAFT state
registration = client.register(
agent_id="new-agent",
agent_type="autonomous"
)
# Status: draft

# Submit for approval (moves to PENDING_APPROVAL)
client.submit_for_approval("new-agent")
# Status: pending_approval

# Admin reviews and activates
# Status: active (after admin approval)

Approval Requirements

Agent TypeAuto-ActivateApproval Required
advisoryYesNo
supervisedNoAdmin
autonomousNoAdmin + Security
mcp_serverNoAdmin

Approval Audit Trail

{
"agent_id": "autonomous-agent-001",
"activity_type": "activated",
"activity_description": "Agent 'autonomous-agent-001' activated (previous: pending_approval)",
"performed_by": "security-admin@company.com",
"performed_via": "dashboard",
"timestamp": "2025-12-15T10:30:00Z",
"previous_state": {
"status": "pending_approval"
},
"new_state": {
"status": "active"
}
}

Bulk Operations

Suspend All Agents

Emergency: Suspend all agents in organization:

curl -X POST "https://pilot.owkai.app/api/agents/control/suspend-all" \
-H "Authorization: Bearer owkai_..." \
-H "Content-Type: application/json" \
-d '{
"reason": "Security incident - suspending all agents"
}'

Reactivate All Agents

Resume operations:

curl -X POST "https://pilot.owkai.app/api/agents/control/resume-all" \
-H "Authorization: Bearer owkai_..." \
-H "Content-Type: application/json" \
-d '{
"reason": "Security incident resolved - resuming operations"
}'

Compliance Requirements

State Changes Require Audit

All state changes are logged:

# Source: services/agent_registry_service.py:963
# Every state change creates an audit entry
activity = AgentActivityLog(
agent_id=agent.id,
organization_id=organization_id,
activity_type="activated",
activity_description=f"Agent '{agent_id}' activated (previous: {previous_status})",
performed_by=approved_by,
performed_via="api",
previous_state={"status": previous_status},
new_state={"status": AgentStatus.ACTIVE.value},
timestamp=datetime.now(UTC)
)

Compliance Mapping

StandardRequirementImplementation
SOC 2 CC6.1Access provisioningDraft → Pending → Active
SOC 2 CC6.2Access authorizationApproval workflow
NIST AC-2Account managementLifecycle states
NIST AC-2(3)Disable inactiveAuto-suspend
PCI-DSS 8.1.4Remove inactive usersDeprecated → Retired

Best Practices

1. Use Proper Transitions

# Good - proper state transition
agent.submit_for_approval() # draft → pending_approval
admin.activate(agent) # pending_approval → active

# Bad - skipping states
agent.force_activate() # draft → active (bypasses approval)

2. Document State Changes

# Always include reason for state changes
curl -X POST ".../suspend" \
-d '{
"reason": "JIRA-5678: Security audit findings require review"
}'

3. Monitor Auto-Suspensions

# Set up alerts for auto-suspensions
{
"alert_type": "agent_auto_suspended",
"channels": ["slack", "email"],
"recipients": ["security-team@company.com"]
}

4. Plan for Retirement

# Deprecate before retiring
# 1. Mark as deprecated with future retirement date
deprecate(agent, retirement_date="2025-12-31")

# 2. Monitor for any remaining usage
# 3. Retire when confirmed safe
retire(agent, reason="Deprecated period complete, no active usage")

Next Steps


Document Version: 2026.04 | Last Updated: April 2026