Control 3.6: Orphaned Agent Detection and Remediation
Overview
Control ID: 3.6 Control Name: Orphaned Agent Detection and Remediation Regulatory Reference: FINRA 4511, SOX 404, GLBA 501(b), OCC 2011-12 Setup Time: 2-3 hours
Purpose
Orphaned Agent Detection and Remediation ensures continuous visibility into agent ownership and operational status across the organization. An orphaned agent is one without an assigned owner (due to employee departure, role change, or oversight) or one that is no longer actively maintained. For financial services organizations, unmanaged agents represent significant security, compliance, and operational risks. This control establishes automated detection, notification, and remediation processes to maintain governance integrity.
Prerequisites
Primary Owner Admin Role: Power Platform Admin Supporting Roles: Dataverse System Admin
Licensing Requirements
| Component | License Required |
|---|---|
| Power Platform Admin Center | Included with Power Platform |
| Microsoft Entra ID | Microsoft 365 E3/E5 |
| Power Automate | Power Platform (included with M365) |
| SharePoint for Tracking | Microsoft 365 E3/E5 |
| Microsoft 365 Audit Logs | Microsoft 365 E3/E5 |
Permissions Required
| Task | Role/Permission |
|---|---|
| View Agent Inventory | Power Platform Administrator |
| Query User Status | User Administrator (Entra ID) |
| Reassign Agents | Environment Administrator |
| Delete/Archive Agents | System Administrator |
| Configure Detection Flows | Power Automate Administrator |
| Access HR Termination Data | HR Integration Service Account |
Dependencies
- [x] Control 3.1: Agent Inventory and Metadata Management
- [x] Control 2.3: ALM and Lifecycle Management
- [x] Control 2.8: Access Control and Segregation of Duties
- [ ] HR system integration (for termination events)
Pre-Setup Checklist
- [ ] Agent inventory complete and current
- [ ] Owner assignment documented for all agents
- [ ] HR termination feed configured (or manual process defined)
- [ ] Escalation matrix for unowned agents established
- [ ] Retention policy for decommissioned agents defined
Governance Levels
Baseline (Level 1)
Identify agents without assigned owner; document remediation plan.
Recommended (Level 2-3)
Automated detection; monthly review; email notifications to IT.
Regulated/High-Risk (Level 4)
Real-time detection; automatic suspension until owner assigned.
Setup & Configuration
Step 1: Define Orphaned Agent Criteria
Orphaned Agent Indicators:
| Indicator | Detection Method | Severity |
|---|---|---|
| Owner Departed | User disabled/deleted in Entra ID | Critical |
| Owner Role Changed | User no longer in authorized group | High |
| No Owner Assigned | Owner field null in inventory | Critical |
| Inactive Agent | No usage in 90+ days | Medium |
| Failed Health Check | Connector errors, timeouts | High |
| License Expired | Maker license no longer active | High |
| Environment Deleted | Parent environment removed | Critical |
Risk Classification:
| Category | Definition | Auto-Action |
|---|---|---|
| Critical | Immediate governance risk | Suspend agent access |
| High | Action required within 24 hours | Alert + suspend after 48h |
| Medium | Action required within 7 days | Alert only |
| Low | Review in next governance cycle | Include in monthly report |
Step 2: Configure Owner Status Monitoring
Portal Path: Microsoft Entra Admin Center → Users → User settings
Set up monitoring for user status changes:
- Navigate to Entra Admin Center
- Go to Monitoring → Workbooks → User Activity
- Create custom workbook to track:
- User account disable events
- User account delete events
- Group membership changes (Power Platform makers)
- Configure alerts for relevant changes
Step 3: Create Automated Detection Flow
Portal Path: Power Automate → Create → Scheduled cloud flow
Flow: Daily Orphaned Agent Check
Trigger: Recurrence (Daily at 6 AM)
Actions:
1. Get all agents from Agent Inventory list
2. For each agent:
├── Get owner user account from Entra ID
├── Check if account is:
│ ├── Disabled → Flag as Orphaned (Owner Departed)
│ ├── Deleted → Flag as Orphaned (Owner Departed)
│ ├── Not in Maker group → Flag as Orphaned (Role Changed)
│ └── Null → Flag as Orphaned (No Owner)
│
├── If orphaned:
│ ├── Update Agent Inventory status
│ ├── Log to Orphaned Agents list
│ ├── Determine severity
│ └── Trigger appropriate action
│
3. If Critical orphans found:
├── Email IT Operations immediately
├── Create incident ticket
└── Optionally suspend agent
4. Generate daily summary report
Step 4: Build Orphaned Agent Tracking List
Portal Path: SharePoint → AI Governance Site → Create List
Create SharePoint list with these columns:
| Column Name | Type | Required | Description |
|---|---|---|---|
| AgentId | Lookup | Yes | Link to Agent Inventory |
| AgentName | Text | Yes | Agent display name |
| OrphanedDate | DateTime | Yes | When detected |
| OrphanReason | Choice | Yes | Departed/Role Changed/No Owner/Inactive |
| PreviousOwner | Text | Yes | Last known owner |
| Severity | Choice | Yes | Critical/High/Medium/Low |
| Status | Choice | Yes | Detected/Under Review/Reassigned/Suspended/Decommissioned |
| AssignedTo | Person | No | IT staff responsible |
| NewOwner | Person | No | Reassigned owner |
| RemediationDate | DateTime | No | When resolved |
| Notes | MultiLine | No | Action notes |
Step 5: Configure Remediation Workflows
Workflow 1: Owner Reassignment
Trigger: User clicks "Reassign" button
Actions:
├── Prompt for new owner selection
├── Validate new owner:
│ ├── Has active account
│ ├── Has appropriate license
│ └── Is in authorized maker group
├── Update agent ownership in Power Platform
├── Update Agent Inventory
├── Update Orphaned Agents list (Status = Reassigned)
├── Notify new owner
└── Close remediation ticket
Workflow 2: Agent Suspension
Trigger: Severity = Critical AND no action in 24 hours
Actions:
├── Disable agent connections
├── Set agent sharing to "No access"
├── Update status to "Suspended"
├── Email escalation chain
├── Log suspension to audit
└── Create P2 incident
Workflow 3: Decommission
Trigger: IT Admin approves decommission
Actions:
├── Export agent configuration
├── Export agent conversation logs
├── Archive to long-term storage
├── Remove agent from environment
├── Update inventory (Status = Decommissioned)
├── Update cost tracking
└── Close all related tickets
Step 6: Set Up HR Integration
Option A: Direct HR System Integration
HR System (Workday/SAP) → Power Automate → Orphan Detection
Trigger: Employee termination event
Actions:
├── Query Agent Inventory for agents owned by terminated user
├── For each agent found:
│ ├── Update status to Orphaned
│ ├── Set severity to Critical
│ ├── Notify agent's supervisor for reassignment
│ └── Start remediation clock
Option B: Entra ID Change Detection
Microsoft Entra → Logic App → Power Automate
Trigger: User account disabled
Actions:
├── Same as above
Step 7: Configure Inactivity Monitoring
Portal Path: Power Platform Admin Center → Analytics → Usage
Set up usage-based orphan detection:
| Inactivity Period | Status | Action |
|---|---|---|
| 30 days | Warning | Email owner |
| 60 days | Review Required | Email owner + manager |
| 90 days | Orphan Candidate | Add to remediation queue |
| 180 days | Decommission Candidate | Initiate decommission review |
PowerShell Configuration
# ============================================================
# Control 3.6: Orphaned Agent Detection and Remediation
# PowerShell Configuration Script for FSI Organizations
# ============================================================
# Install required modules
Install-Module -Name Microsoft.Graph -Force -AllowClobber
Install-Module -Name Microsoft.PowerApps.Administration.PowerShell -Force -AllowClobber
Install-Module -Name PnP.PowerShell -Force -AllowClobber
# Connect to services
Connect-MgGraph -Scopes "User.Read.All", "AuditLog.Read.All"
Add-PowerAppsAccount
Connect-PnPOnline -Url "https://[tenant].sharepoint.com/sites/AI-Governance" -Interactive
# ============================================================
# SECTION 1: Orphaned Agent Detection
# ============================================================
function Find-OrphanedAgents {
param(
[string]$EnvironmentFilter = "*",
[switch]$IncludeInactive
)
Write-Host "Scanning for orphaned agents..." -ForegroundColor Cyan
# Get all environments
$environments = Get-AdminPowerAppEnvironment | Where-Object {
$_.DisplayName -like $EnvironmentFilter
}
$orphanedAgents = @()
$agentCount = 0
foreach ($env in $environments) {
Write-Host " Checking environment: $($env.DisplayName)" -ForegroundColor Gray
# Get all apps in environment
$apps = Get-AdminPowerApp -EnvironmentName $env.EnvironmentName
foreach ($app in $apps) {
$agentCount++
$ownerId = $app.Owner.id
# Check owner status in Entra ID
try {
$owner = Get-MgUser -UserId $ownerId -Property "accountEnabled,deletedDateTime" -ErrorAction Stop
if ($owner.deletedDateTime) {
# Owner deleted
$orphanedAgents += [PSCustomObject]@{
AgentName = $app.DisplayName
AgentId = $app.AppName
Environment = $env.DisplayName
PreviousOwner = $owner.UserPrincipalName
OrphanReason = "Owner Deleted"
Severity = "Critical"
DetectedDate = Get-Date
}
}
elseif (-not $owner.accountEnabled) {
# Owner disabled
$orphanedAgents += [PSCustomObject]@{
AgentName = $app.DisplayName
AgentId = $app.AppName
Environment = $env.DisplayName
PreviousOwner = $owner.UserPrincipalName
OrphanReason = "Owner Disabled"
Severity = "Critical"
DetectedDate = Get-Date
}
}
}
catch {
# Owner not found
$orphanedAgents += [PSCustomObject]@{
AgentName = $app.DisplayName
AgentId = $app.AppName
Environment = $env.DisplayName
PreviousOwner = $ownerId
OrphanReason = "Owner Not Found"
Severity = "Critical"
DetectedDate = Get-Date
}
}
}
}
Write-Host "`nScan Complete:" -ForegroundColor Green
Write-Host " Total agents scanned: $agentCount"
Write-Host " Orphaned agents found: $($orphanedAgents.Count)"
if ($orphanedAgents.Count -gt 0) {
Write-Host "`nOrphaned Agents:" -ForegroundColor Yellow
$orphanedAgents | Format-Table AgentName, OrphanReason, Severity, PreviousOwner -AutoSize
}
return $orphanedAgents
}
# ============================================================
# SECTION 2: Inactive Agent Detection
# ============================================================
function Find-InactiveAgents {
param(
[int]$InactiveDays = 90
)
Write-Host "Scanning for agents inactive for $InactiveDays+ days..." -ForegroundColor Cyan
$cutoffDate = (Get-Date).AddDays(-$InactiveDays)
$inactiveAgents = @()
$environments = Get-AdminPowerAppEnvironment
foreach ($env in $environments) {
$apps = Get-AdminPowerApp -EnvironmentName $env.EnvironmentName
foreach ($app in $apps) {
$lastModified = $app.LastModifiedTime
if ($lastModified -lt $cutoffDate) {
# Would need usage analytics API for actual last usage
# This uses last modified as proxy
$daysSinceActivity = ((Get-Date) - $lastModified).Days
$inactiveAgents += [PSCustomObject]@{
AgentName = $app.DisplayName
AgentId = $app.AppName
Environment = $env.DisplayName
Owner = $app.Owner.displayName
LastActivity = $lastModified
DaysInactive = $daysSinceActivity
Severity = if ($daysSinceActivity -gt 180) { "High" }
elseif ($daysSinceActivity -gt 120) { "Medium" }
else { "Low" }
}
}
}
}
Write-Host "Inactive agents found: $($inactiveAgents.Count)" -ForegroundColor Yellow
if ($inactiveAgents.Count -gt 0) {
$inactiveAgents | Sort-Object DaysInactive -Descending | Format-Table AgentName, DaysInactive, Severity, Owner -AutoSize
}
return $inactiveAgents
}
# ============================================================
# SECTION 3: Remediation Actions
# ============================================================
function Set-AgentOwner {
param(
[Parameter(Mandatory=$true)]
[string]$AppId,
[Parameter(Mandatory=$true)]
[string]$EnvironmentId,
[Parameter(Mandatory=$true)]
[string]$NewOwnerEmail
)
Write-Host "Reassigning agent ownership..." -ForegroundColor Cyan
# Validate new owner
try {
$newOwner = Get-MgUser -Filter "mail eq '$NewOwnerEmail'" -Property "accountEnabled,id"
if (-not $newOwner.accountEnabled) {
Write-Error "New owner account is disabled"
return $false
}
# Add new owner as co-owner first
Set-AdminPowerAppRoleAssignment `
-PrincipalType "User" `
-PrincipalObjectId $newOwner.Id `
-RoleName "CanEdit" `
-AppName $AppId `
-EnvironmentName $EnvironmentId
Write-Host "Agent ownership updated to: $NewOwnerEmail" -ForegroundColor Green
# Log the change
$auditEntry = @{
Action = "OwnerReassignment"
AgentId = $AppId
NewOwner = $NewOwnerEmail
ChangedBy = (Get-MgContext).Account
Timestamp = Get-Date
}
Write-Host "Audit logged: $($auditEntry | ConvertTo-Json -Compress)"
return $true
}
catch {
Write-Error "Failed to reassign ownership: $_"
return $false
}
}
function Suspend-Agent {
param(
[Parameter(Mandatory=$true)]
[string]$AppId,
[Parameter(Mandatory=$true)]
[string]$EnvironmentId,
[Parameter(Mandatory=$true)]
[string]$Reason
)
Write-Host "Suspending agent: $AppId" -ForegroundColor Yellow
try {
# Remove all role assignments except admin
$roleAssignments = Get-AdminPowerAppRoleAssignment -AppName $AppId -EnvironmentName $EnvironmentId
foreach ($role in $roleAssignments) {
if ($role.RoleName -ne "CanViewWithShare") { # Keep admin access
Remove-AdminPowerAppRoleAssignment `
-RoleId $role.RoleId `
-AppName $AppId `
-EnvironmentName $EnvironmentId
}
}
Write-Host "Agent suspended - all user access removed" -ForegroundColor Yellow
# Log suspension
$suspensionRecord = @{
AgentId = $AppId
SuspendedDate = Get-Date
Reason = $Reason
SuspendedBy = (Get-MgContext).Account
}
# Would log to SharePoint or tracking system
return $true
}
catch {
Write-Error "Failed to suspend agent: $_"
return $false
}
}
function Remove-OrphanedAgent {
param(
[Parameter(Mandatory=$true)]
[string]$AppId,
[Parameter(Mandatory=$true)]
[string]$EnvironmentId,
[switch]$ExportFirst,
[string]$ExportPath = ".\AgentExports"
)
Write-Host "Decommissioning agent: $AppId" -ForegroundColor Red
if ($ExportFirst) {
# Export agent package before deletion
if (-not (Test-Path $ExportPath)) {
New-Item -ItemType Directory -Path $ExportPath | Out-Null
}
Write-Host "Exporting agent configuration..." -ForegroundColor Cyan
# In production, use proper export cmdlets
$exportFile = Join-Path $ExportPath "$AppId-export.zip"
# Export-AdminPowerApp would be used here
Write-Host "Exported to: $exportFile" -ForegroundColor Green
}
# Remove the app
try {
Remove-AdminPowerApp -AppName $AppId -EnvironmentName $EnvironmentId
Write-Host "Agent successfully decommissioned" -ForegroundColor Green
# Update tracking
$decommissionRecord = @{
AgentId = $AppId
DecommissionedDate = Get-Date
DecommissionedBy = (Get-MgContext).Account
ExportLocation = if ($ExportFirst) { $exportFile } else { "Not exported" }
}
return $true
}
catch {
Write-Error "Failed to decommission agent: $_"
return $false
}
}
# ============================================================
# SECTION 4: Generate Orphan Report
# ============================================================
function New-OrphanedAgentReport {
param(
[string]$OutputPath = ".\OrphanedAgentReport.html"
)
Write-Host "Generating orphaned agent report..." -ForegroundColor Cyan
# Gather data
$orphaned = Find-OrphanedAgents
$inactive = Find-InactiveAgents -InactiveDays 90
$html = @"
<!DOCTYPE html>
<html>
<head>
<title>Orphaned Agent Detection Report</title>
<style>
body { font-family: 'Segoe UI', Arial, sans-serif; margin: 40px; background: #f8f9fa; }
.container { max-width: 1100px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
h1 { color: #C41E3A; border-bottom: 3px solid #C41E3A; padding-bottom: 15px; }
h2 { color: #333; margin-top: 30px; }
.alert-box { padding: 20px; border-radius: 8px; margin: 20px 0; }
.alert-critical { background: #F8D7DA; border-left: 4px solid #DC3545; }
.alert-warning { background: #FFF3CD; border-left: 4px solid #FFC107; }
.alert-info { background: #D1ECF1; border-left: 4px solid #17A2B8; }
.metric-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin: 20px 0; }
.metric-card { background: #f5f5f5; padding: 20px; border-radius: 8px; text-align: center; }
.metric-value { font-size: 36px; font-weight: bold; }
.critical { color: #DC3545; }
.warning { color: #FFC107; }
.success { color: #28A745; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th { background: #0078D4; color: white; padding: 12px; text-align: left; }
td { border: 1px solid #ddd; padding: 10px; }
tr:nth-child(even) { background: #f9f9f9; }
.severity-critical { background: #DC3545; color: white; padding: 4px 8px; border-radius: 4px; }
.severity-high { background: #FFC107; padding: 4px 8px; border-radius: 4px; }
.severity-medium { background: #17A2B8; color: white; padding: 4px 8px; border-radius: 4px; }
.footer { text-align: center; color: #666; margin-top: 40px; padding-top: 20px; border-top: 1px solid #ddd; }
</style>
</head>
<body>
<div class="container">
<h1>⚠️ Orphaned Agent Detection Report</h1>
<p><strong>Generated:</strong> $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")</p>
<div class="metric-row">
<div class="metric-card">
<div class="metric-value critical">$($orphaned.Count)</div>
<div>Orphaned Agents</div>
</div>
<div class="metric-card">
<div class="metric-value warning">$($inactive.Count)</div>
<div>Inactive Agents (90+ days)</div>
</div>
<div class="metric-card">
<div class="metric-value">$(($orphaned | Where-Object { $_.Severity -eq "Critical" }).Count)</div>
<div>Critical Priority</div>
</div>
<div class="metric-card">
<div class="metric-value success">0</div>
<div>Remediated This Week</div>
</div>
</div>
$(if ($orphaned.Count -gt 0) {
"<div class='alert-box alert-critical'>
<strong>⚠️ Immediate Action Required:</strong> $($orphaned.Count) agents detected without valid owners.
Critical agents should be reassigned or suspended within 24 hours.
</div>"
})
<h2>Orphaned Agents</h2>
$(if ($orphaned.Count -gt 0) {
"<table>
<tr><th>Agent Name</th><th>Environment</th><th>Reason</th><th>Severity</th><th>Previous Owner</th></tr>
$($orphaned | ForEach-Object {
$severityClass = "severity-$($_.Severity.ToLower())"
"<tr>
<td>$($_.AgentName)</td>
<td>$($_.Environment)</td>
<td>$($_.OrphanReason)</td>
<td><span class='$severityClass'>$($_.Severity)</span></td>
<td>$($_.PreviousOwner)</td>
</tr>"
})
</table>"
} else {
"<div class='alert-box alert-info'>✅ No orphaned agents detected</div>"
})
<h2>Inactive Agents (90+ days)</h2>
$(if ($inactive.Count -gt 0) {
"<table>
<tr><th>Agent Name</th><th>Environment</th><th>Days Inactive</th><th>Owner</th><th>Recommendation</th></tr>
$($inactive | Sort-Object DaysInactive -Descending | Select-Object -First 10 | ForEach-Object {
$recommendation = if ($_.DaysInactive -gt 180) { "Recommend Decommission" }
elseif ($_.DaysInactive -gt 120) { "Review with Owner" }
else { "Monitor" }
"<tr>
<td>$($_.AgentName)</td>
<td>$($_.Environment)</td>
<td>$($_.DaysInactive)</td>
<td>$($_.Owner)</td>
<td>$recommendation</td>
</tr>"
})
</table>"
} else {
"<div class='alert-box alert-info'>✅ No inactive agents detected</div>"
})
<h2>Remediation Actions</h2>
<ol>
<li><strong>Critical orphans:</strong> Reassign to appropriate owner or suspend within 24 hours</li>
<li><strong>High severity:</strong> Contact department manager for ownership decision within 48 hours</li>
<li><strong>Inactive agents:</strong> Verify with owners if agents are still needed</li>
<li><strong>Decommission candidates:</strong> Archive and remove after 180 days inactivity</li>
</ol>
<div class="footer">
<p>Generated by FSI-AgentGov Orphan Detection System</p>
<p>For assistance: ai-governance@company.com</p>
</div>
</div>
</body>
</html>
"@
$html | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "Report generated: $OutputPath" -ForegroundColor Green
return $OutputPath
}
# ============================================================
# SECTION 5: HR Termination Integration
# ============================================================
function Watch-EmployeeTerminations {
param(
[int]$DaysBack = 1
)
Write-Host "Checking for recent employee terminations..." -ForegroundColor Cyan
$cutoffDate = (Get-Date).AddDays(-$DaysBack)
# Query Entra ID for recently disabled users
$disabledUsers = Get-MgUser -Filter "accountEnabled eq false" -Property "id,displayName,userPrincipalName,signInActivity" |
Where-Object {
# Would need more sophisticated date checking in production
$true
}
Write-Host "Found $($disabledUsers.Count) disabled users to check" -ForegroundColor Yellow
foreach ($user in $disabledUsers) {
# Check if user owns any agents
$userApps = Get-AdminPowerApp | Where-Object { $_.Owner.id -eq $user.Id }
if ($userApps.Count -gt 0) {
Write-Host "⚠️ Terminated user $($user.DisplayName) owns $($userApps.Count) agents" -ForegroundColor Red
foreach ($app in $userApps) {
Write-Host " - $($app.DisplayName)" -ForegroundColor Yellow
}
}
}
}
# ============================================================
# EXAMPLE USAGE
# ============================================================
Write-Host "=== Control 3.6: Orphaned Agent Detection and Remediation ===" -ForegroundColor Magenta
# Find orphaned agents
# $orphans = Find-OrphanedAgents
# Find inactive agents
# $inactive = Find-InactiveAgents -InactiveDays 90
# Reassign agent ownership
# Set-AgentOwner -AppId "guid" -EnvironmentId "env-guid" -NewOwnerEmail "newowner@company.com"
# Suspend an agent
# Suspend-Agent -AppId "guid" -EnvironmentId "env-guid" -Reason "Owner departed - pending reassignment"
# Decommission an agent
# Remove-OrphanedAgent -AppId "guid" -EnvironmentId "env-guid" -ExportFirst
# Generate orphan report
# New-OrphanedAgentReport -OutputPath ".\WeeklyOrphanReport.html"
# Check for employee terminations
# Watch-EmployeeTerminations -DaysBack 1
Write-Host "`nConfiguration script ready. Uncomment and run desired functions." -ForegroundColor Green
Financial Sector Considerations
Regulatory Requirements
| Regulation | Requirement | Implementation |
|---|---|---|
| FINRA 4511 | Maintain books and records | Document all agent ownership changes |
| SOX 404 | IT access controls | Prevent unauthorized agent access |
| GLBA 501(b) | Safeguard customer data | Suspend agents accessing NPI immediately |
| OCC 2011-12 | Third-party oversight | Track vendor-built orphaned agents |
| SEC 17a-4 | Preserve records | Archive decommissioned agent data |
Zone-Specific Configuration
| Zone | Detection Frequency | Auto-Suspend | Grace Period |
|---|---|---|---|
| Zone 1 (Personal Productivity) | Weekly | No | 30 days |
| Zone 2 (Team Collaboration) | Daily | After 7 days | 7 days |
| Zone 3 (Enterprise Managed) | Real-time | Immediate | 24 hours |
FSI Example: Critical Orphan Remediation
SCENARIO: Account Manager terminated - owns 3 agents
Agent Portfolio:
├── Customer Portfolio Analyzer (Tier 3) - CRITICAL
│ └── Accesses customer account data
├── Trade Blotter Bot (Tier 3) - CRITICAL
│ └── Integrates with trading systems
└── Meeting Scheduler (Tier 1) - LOW
└── Calendar access only
Remediation Timeline:
├── T+0:00 - HR termination event received
├── T+0:05 - Automated orphan detection triggered
├── T+0:10 - Tier 3 agents auto-suspended
├── T+0:30 - Incident ticket created
├── T+1:00 - Manager contacted for reassignment
├── T+4:00 - New owners identified and assigned
├── T+8:00 - Agents restored with new ownership
├── T+24:00 - Audit review completed
└── T+48:00 - Compliance sign-off
Documentation Required:
├── Termination date/time
├── Agents affected
├── Suspension timestamp
├── New owner assignment
├── Testing verification
└── Compliance approval
Verification & Testing
Verification Steps
- Detection Accuracy
- Disable test user account
- Verify agent flagged as orphaned within SLA
-
Confirm severity classification correct
-
Automated Workflows
- Test notification flow triggers
-
Verify escalation timing
- Confirm auto-suspend (Tier 3) works
-
Remediation Process
- Test owner reassignment
- Verify permissions transfer correctly
-
Confirm audit trail created
-
Reporting
- Generate orphan report
- Verify counts match manual check
- Confirm all data fields populated
Compliance Checklist
| Item | Required For | Status |
|---|---|---|
| Daily orphan detection running | SOX 404 | ☐ |
| Auto-suspend for Tier 3 agents | GLBA 501(b) | ☐ |
| HR integration configured | Best practice | ☐ |
| Ownership change audit trail | FINRA 4511 | ☐ |
| Decommissioned agent archival | SEC 17a-4 | ☐ |
| Weekly orphan report generated | Internal governance | ☐ |
| Remediation SLAs defined | Operational efficiency | ☐ |
Troubleshooting & Validation
Issue: Detection Not Finding Orphans
Symptoms: Known orphaned agents not appearing in scan
Resolution:
- Verify Entra ID connection permissions
- Check user account truly disabled (not just expired)
- Confirm agent inventory is complete
- Review filter logic in detection script
Issue: Auto-Suspend Not Triggering
Symptoms: Critical orphans remain active
Resolution:
- Check Power Automate flow is enabled
- Verify severity classification correct
- Confirm flow has admin permissions
- Test with manual trigger first
Issue: HR Integration Lag
Symptoms: Terminations not detected for 24+ hours
Resolution:
- Check HR system sync frequency
- Verify Entra ID provisioning settings
- Consider real-time webhook from HR
- Implement scheduled gap checking
Issue: False Positives
Symptoms: Active users flagged as departed
Resolution:
- Check for account sync delays
- Verify filter logic accuracy
- Add grace period before flagging
- Implement manual review for edge cases
Issue: Reassignment Failures
Symptoms: New owner cannot access agent
Resolution:
- Verify new owner has appropriate license
- Check environment permissions
- Confirm security role assignment
- Test with different permission levels
Additional Resources
- Power Platform Admin APIs
- Microsoft Graph User Management
- Power Automate Scheduled Flows
- SharePoint List Management
- Microsoft Entra ID Monitoring
Related Controls
| Control | Relationship |
|---|---|
| 3.1 Agent Inventory | Source of agent ownership data |
| 3.5 Cost Allocation | Cost savings from decommissioning |
| 2.3 Change Management | Lifecycle state management |
| 2.8 Access Control | Permission management |
| 1.2 Agent Registry | Registry cleanup |
Support & Questions
For implementation support or questions about this control, contact:
- AI Governance Lead (governance direction)
- Compliance Officer (regulatory requirements)
- Technical Implementation Team (platform setup)
Updated: Dec 2025
Version: v1.0 Beta (Dec 2025)
UI Verification Status: ❌ Needs verification