Skip to content

Control 2.6: Model Risk Management - PowerShell Setup

This playbook provides PowerShell automation scripts for Control 2.6.


Model Performance Monitoring Script

# Model Performance Monitoring Script
param(
    [string]$AgentId,
    [int]$DaysToAnalyze = 30
)

# Connect to Dataverse (assumes connection established)
$startDate = (Get-Date).AddDays(-$DaysToAnalyze)

# Calculate metrics
$metrics = @{
    TotalConversations = 0
    SuccessfulResolutions = 0
    Escalations = 0
    AverageResponseTime = 0
    UserSatisfactionAvg = 0
}

# Query Copilot interaction audit logs for the past $DaysToAnalyze days
$auditResults = Search-UnifiedAuditLog -RecordType "CopilotInteraction" `
    -StartDate $startDate -EndDate (Get-Date) -ResultSize 5000
if ($auditResults) {
    $metrics.TotalConversations = $auditResults.Count
    $metrics.UniqueUsers = ($auditResults | Select-Object -ExpandProperty UserIds -Unique).Count
}
# For additional metrics (satisfaction, response time), query Dataverse conversation transcripts:
# GET /api/data/v9.2/conversationtranscripts?$filter=createdon ge {startDate}

# Calculate performance scores
$resolutionRate = $metrics.SuccessfulResolutions / $metrics.TotalConversations * 100
$escalationRate = $metrics.Escalations / $metrics.TotalConversations * 100

# Determine status
$status = "Green"
if ($resolutionRate -lt 90 -or $escalationRate -gt 15) {
    $status = "Yellow"
}
if ($resolutionRate -lt 80 -or $escalationRate -gt 25) {
    $status = "Red"
}

# Output report
Write-Host "=== Model Performance Report ===" -ForegroundColor Cyan
Write-Host "Agent: $AgentId"
Write-Host "Period: Last $DaysToAnalyze days"
Write-Host "Status: $status"
Write-Host ""
Write-Host "Metrics:"
Write-Host "  Resolution Rate: $([math]::Round($resolutionRate, 2))%"
Write-Host "  Escalation Rate: $([math]::Round($escalationRate, 2))%"
Write-Host "  Avg Response Time: $($metrics.AverageResponseTime)ms"
Write-Host "  User Satisfaction: $($metrics.UserSatisfactionAvg)/5.0"

# Alert if threshold breached
if ($status -ne "Green") {
    Write-Host "`nALERT: Performance threshold breached!" -ForegroundColor $status
    # Send notification (Teams, email, etc.)
}

Agent Manifest Export Script

# Export Agent Manifest for Version Control
param(
    [Parameter(Mandatory=$true)]
    [string]$AgentId,
    [string]$OutputPath = ".\manifests"
)

# Ensure output directory exists
New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null

$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$filename = "$OutputPath\$AgentId-manifest-$timestamp.json"

# Build manifest structure
$manifest = @{
    exportDate = Get-Date -Format "yyyy-MM-ddTHH:mm:ssZ"
    agentId = $AgentId
    version = "1.0.0"  # Update based on your versioning
    components = @{
        systemInstructions = "[Export from Copilot Studio]"
        topics = @()
        knowledgeSources = @()
        actions = @()
        settings = @{}
    }
}

# Export manifest
$manifest | ConvertTo-Json -Depth 10 | Out-File -FilePath $filename -Encoding UTF8

Write-Host "Manifest exported: $filename" -ForegroundColor Green
Write-Host "Commit this file to version control" -ForegroundColor Yellow

MRM Compliance Report Generator

# Model Risk Management Compliance Report
param(
    [string]$ModelInventoryPath,
    [string]$OutputPath = ".\MRM_Report_$(Get-Date -Format 'yyyyMMdd').html"
)

# Load model inventory
$models = Import-Csv -Path $ModelInventoryPath

# Calculate compliance metrics
$totalModels = $models.Count
$tier1 = ($models | Where-Object Tier -eq "1").Count
$tier2 = ($models | Where-Object Tier -eq "2").Count
$tier3 = ($models | Where-Object Tier -eq "3").Count

$currentDate = Get-Date
$validationCurrent = ($models | Where-Object {
    [datetime]$_.NextValidationDue -gt $currentDate
}).Count
$validationOverdue = ($models | Where-Object {
    [datetime]$_.NextValidationDue -le $currentDate
}).Count

$performanceGreen = ($models | Where-Object PerformanceStatus -eq "Green").Count
$performanceYellow = ($models | Where-Object PerformanceStatus -eq "Yellow").Count
$performanceRed = ($models | Where-Object PerformanceStatus -eq "Red").Count

# Generate HTML report
$html = @"
<!DOCTYPE html>
<html>
<head>
<title>Model Risk Management Report</title>
<style>
body { font-family: 'Segoe UI', sans-serif; margin: 20px; }
h1, h2 { color: #0078d4; }
.dashboard { display: flex; gap: 20px; flex-wrap: wrap; margin: 20px 0; }
.card { padding: 20px; background: #f3f2f1; border-radius: 8px; min-width: 150px; }
.card.green { background: #dff6dd; }
.card.yellow { background: #fff4ce; }
.card.red { background: #fed9cc; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { padding: 10px; text-align: left; border-bottom: 1px solid #ddd; }
th { background: #0078d4; color: white; }
.overdue { color: red; font-weight: bold; }
</style>
</head>
<body>
<h1>Model Risk Management Compliance Report</h1>
<p>Report Date: $(Get-Date -Format 'MMMM dd, yyyy')</p>

<h2>Model Inventory Summary</h2>
<div class="dashboard">
<div class="card"><h3>Total Models</h3><p style="font-size:28px;">$totalModels</p></div>
<div class="card"><h3>Tier 1 (High)</h3><p style="font-size:28px;">$tier1</p></div>
<div class="card"><h3>Tier 2 (Medium)</h3><p style="font-size:28px;">$tier2</p></div>
<div class="card"><h3>Tier 3 (Low)</h3><p style="font-size:28px;">$tier3</p></div>
</div>

<h2>Validation Status</h2>
<div class="dashboard">
<div class="card green"><h3>Current</h3><p style="font-size:28px;">$validationCurrent</p></div>
<div class="card red"><h3>Overdue</h3><p style="font-size:28px;">$validationOverdue</p></div>
</div>

<h2>Performance Status</h2>
<div class="dashboard">
<div class="card green"><h3>Green</h3><p style="font-size:28px;">$performanceGreen</p></div>
<div class="card yellow"><h3>Yellow</h3><p style="font-size:28px;">$performanceYellow</p></div>
<div class="card red"><h3>Red</h3><p style="font-size:28px;">$performanceRed</p></div>
</div>

<h2>Model Details</h2>
<table>
<tr><th>Model ID</th><th>Name</th><th>Tier</th><th>Owner</th><th>Last Validation</th><th>Next Due</th><th>Status</th></tr>
$(
$models | ForEach-Object {
    $overdueClass = if ([datetime]$_.NextValidationDue -le $currentDate) { "overdue" } else { "" }
    "<tr><td>$($_.ModelID)</td><td>$($_.ModelName)</td><td>$($_.Tier)</td><td>$($_.ModelOwner)</td><td>$($_.LastValidation)</td><td class='$overdueClass'>$($_.NextValidationDue)</td><td>$($_.PerformanceStatus)</td></tr>"
}
)
</table>
</body>
</html>
"@

$html | Out-File -FilePath $OutputPath -Encoding UTF8
Write-Host "MRM Report generated: $OutputPath" -ForegroundColor Green

Model Change Monitoring

# Model Change Monitoring Checklist
model_change:
  agent_id: "[Agent ID]"
  previous_model: "GPT-4o"
  new_model: "GPT-5"
  change_date: "[Date]"

  baseline_metrics:
    accuracy_before: "[%]"
    accuracy_after: "[%]"
    response_time_before: "[ms]"
    response_time_after: "[ms]"
    user_satisfaction_before: "[score]"
    user_satisfaction_after: "[score]"

  validation:
    - [ ] Performance meets or exceeds baseline
    - [ ] No regression in accuracy
    - [ ] Bias testing completed (if Tier 1/2 model)
    - [ ] User acceptance testing passed
    - [ ] MRM notification submitted (if material)

Complete Configuration Script

<#
.SYNOPSIS
    Complete MRM configuration and inventory setup for Control 2.6

.DESCRIPTION
    Executes end-to-end model risk management configuration including:
    - Model inventory creation/validation
    - Performance monitoring setup
    - Compliance report generation

.PARAMETER ModelInventoryPath
    Path to the model inventory CSV file

.PARAMETER OutputPath
    Path for output reports

.EXAMPLE
    .\Configure-Control-2.6.ps1 -ModelInventoryPath ".\ModelInventory.csv" -OutputPath ".\Reports"

.NOTES
    Last Updated: January 2026
    Related Control: Control 2.6 - Model Risk Management
#>

param(
    [string]$ModelInventoryPath = ".\ModelInventory.csv",
    [string]$OutputPath = ".\MRM_Reports"
)

try {
    Write-Host "=== Control 2.6: Model Risk Management Configuration ===" -ForegroundColor Cyan

    # Ensure output directory exists
    New-Item -ItemType Directory -Path $OutputPath -Force | Out-Null

    # Validate model inventory exists
    if (Test-Path $ModelInventoryPath) {
        $models = Import-Csv -Path $ModelInventoryPath
        Write-Host "[INFO] Loaded $($models.Count) models from inventory" -ForegroundColor Cyan
    } else {
        Write-Host "[WARN] Model inventory not found at $ModelInventoryPath - creating template" -ForegroundColor Yellow
        $template = @(
            [PSCustomObject]@{
                ModelID = "AGENT-001"
                ModelName = "Example Agent"
                Tier = "2"
                ModelOwner = "owner@company.com"
                LastValidation = (Get-Date).AddDays(-30).ToString("yyyy-MM-dd")
                NextValidationDue = (Get-Date).AddDays(60).ToString("yyyy-MM-dd")
                PerformanceStatus = "Green"
            }
        )
        $template | Export-Csv -Path $ModelInventoryPath -NoTypeInformation
        Write-Host "[INFO] Template created at $ModelInventoryPath" -ForegroundColor Green
        $models = $template
    }

    # Calculate compliance metrics
    $totalModels = $models.Count
    $tier1 = ($models | Where-Object Tier -eq "1").Count
    $tier2 = ($models | Where-Object Tier -eq "2").Count
    $tier3 = ($models | Where-Object Tier -eq "3").Count

    $currentDate = Get-Date
    $validationCurrent = ($models | Where-Object {
        [datetime]$_.NextValidationDue -gt $currentDate
    }).Count
    $validationOverdue = ($models | Where-Object {
        [datetime]$_.NextValidationDue -le $currentDate
    }).Count

    # Display summary
    Write-Host "`n=== Model Inventory Summary ===" -ForegroundColor Cyan
    Write-Host "Total Models: $totalModels"
    Write-Host "  Tier 1 (High Risk): $tier1"
    Write-Host "  Tier 2 (Medium Risk): $tier2"
    Write-Host "  Tier 3 (Low Risk): $tier3"
    Write-Host "`nValidation Status:"
    Write-Host "  Current: $validationCurrent" -ForegroundColor Green
    Write-Host "  Overdue: $validationOverdue" -ForegroundColor $(if ($validationOverdue -gt 0) { "Red" } else { "Green" })

    # Export summary report
    $summaryReport = [PSCustomObject]@{
        ReportDate = Get-Date -Format "yyyy-MM-dd HH:mm"
        TotalModels = $totalModels
        Tier1Count = $tier1
        Tier2Count = $tier2
        Tier3Count = $tier3
        ValidationCurrent = $validationCurrent
        ValidationOverdue = $validationOverdue
    }
    $summaryReport | Export-Csv -Path "$OutputPath\MRM-Summary-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
    Write-Host "`nSummary exported to: $OutputPath\MRM-Summary-$(Get-Date -Format 'yyyyMMdd').csv"

    Write-Host "`n[PASS] Control 2.6 configuration completed successfully" -ForegroundColor Green
}
catch {
    Write-Host "[FAIL] Error: $($_.Exception.Message)" -ForegroundColor Red
    Write-Host "[INFO] Stack trace: $($_.ScriptStackTrace)" -ForegroundColor Yellow
    exit 1
}
finally {
    # Cleanup connections if applicable
    # No persistent connections to close for this control
}


Updated: January 2026 | Version: v1.2