Managing Microsoft 365 Copilot licenses across your organization can become costly when assigned licenses sit unused. Without an automated process, inactive users retain licenses that could be reassigned to active employees. This article explains how to build a license reclaim workflow using Microsoft Entra ID, Microsoft Graph PowerShell, and Azure Automation. You will learn to identify inactive Copilot users, automatically remove their licenses, and set up a scheduled runbook to keep your license pool clean.
Key Takeaways: Automating Copilot License Reclamation
- Microsoft Entra ID sign-in logs: Source of user inactivity data used to identify unused Copilot licenses.
- Microsoft Graph PowerShell SDK: Tool to query user activity and remove Copilot licenses programmatically.
- Azure Automation runbook: Scheduled job that runs the reclaim script daily or weekly without manual intervention.
Understanding the Copilot License Reclaim Workflow
A license reclaim workflow automatically detects users who have not used Copilot for a defined period, removes their Copilot license, and optionally notifies the user or their manager. The workflow relies on three components: Entra ID sign-in logs to measure inactivity, a PowerShell script to process license removal, and Azure Automation to run the script on a schedule. The goal is to reduce license waste while ensuring active users retain access. The workflow does not delete user accounts or other Microsoft 365 services; it only removes the Copilot SKU from the user’s license assignment.
Prerequisites for Building the Workflow
Before you begin, confirm you have the following in your Microsoft 365 tenant:
- Global Administrator role or at least User Administrator plus License Administrator roles in Entra ID.
- Azure subscription with access to create an Automation account.
- Microsoft Graph PowerShell SDK installed on a local machine for initial script testing.
- Copilot for Microsoft 365 licenses assigned to at least one test user in your tenant.
Steps to Build the Copilot License Reclaim Workflow
Follow these steps to create an automated reclaim workflow. Test each step in a non-production environment first.
Step 1: Identify the Copilot License SKU ID
- Open Microsoft Entra admin center
Sign in to entra.microsoft.com with your Global Administrator account. Go to Identity > Billing > Licenses > All products. - Locate the Copilot for Microsoft 365 product
Find the product named Microsoft 365 Copilot or Copilot for Microsoft 365. Click on it to open the product details page. - Copy the SKU ID
In the product details, look for Product ID or SKU ID. The value looks likeCFQ7TTC0LHBS:0001for most tenants. Write down this ID. You need it in the PowerShell script.
Step 2: Create an Azure Automation Account
- Sign in to Azure portal
Go to portal.azure.com. Search for Automation Accounts in the top search bar and select it. - Create a new Automation account
Click Create. Choose an existing resource group or create a new one. Enter a name likeCopilotLicenseReclaim. Select the same region as your Microsoft 365 tenant. Click Review + Create, then Create. - Enable managed identity
After deployment, go to the Automation account. Under Account Settings, select Identity. Set the System assigned status to On. Click Save. Copy the Object (principal) ID shown on the same page.
Step 3: Grant the Automation Account Permissions in Entra ID
- Open Entra ID admin center
Return to entra.microsoft.com. Go to Identity > Applications > Enterprise applications. - Find the automation service principal
Search for the name of your Automation account, for exampleCopilotLicenseReclaim. Click on it to open the service principal. - Assign API permissions for Microsoft Graph
Under Manage, select API permissions. Click Add a permission. Choose Microsoft Graph > Application permissions. Add these permissions:User.Read.All,Organization.Read.All, andUserLicense.ReadWrite.All. Click Grant admin consent for your tenant.
Step 4: Write the PowerShell Reclaim Script
- Open the Automation account Runbooks page
In the Azure portal, go to your Automation account. Under Process Automation, select Runbooks. Click Create a runbook. - Create a new PowerShell runbook
Enter a name such asReclaim-CopilotLicenses. Set Runbook type to PowerShell. Set Runtime version to 7.2 or later. Click Create. - Insert the reclaim script
Copy the script below into the runbook editor. ReplaceYOUR_SKU_IDwith the SKU ID from Step 1. Replace30with your desired inactivity threshold in days.
# Connect using managed identity
Connect-MgGraph -Identity
# Set parameters
$skuId = "YOUR_SKU_ID"
$inactiveDays = 30
$cutoffDate = (Get-Date).AddDays(-$inactiveDays)
# Get all users with Copilot license
$users = Get-MgUser -All -Property Id,UserPrincipalName,DisplayName,SignInActivity,AssignedLicenses | Where-Object {
$_.AssignedLicenses.SkuId -contains $skuId
}
$reclaimed = @()
foreach ($user in $users) {
$lastSignIn = $user.SignInActivity.LastSignInDateTime
if (-not $lastSignIn -or $lastSignIn -lt $cutoffDate) {
# Remove Copilot license
$licenseToRemove = @{ SkuId = $skuId }
try {
Set-MgUserLicense -UserId $user.Id -AddLicenses @() -RemoveLicenses @($skuId)
$reclaimed += $user.UserPrincipalName
Write-Output "Removed Copilot license from $($user.UserPrincipalName)"
} catch {
Write-Error "Failed to remove license from $($user.UserPrincipalName): $_"
}
}
}
Write-Output "License reclaim complete. Total reclaimed: $($reclaimed.Count)"
Step 5: Publish and Schedule the Runbook
- Test the runbook
Click Test pane in the runbook editor. Start the test. Verify that the script runs without errors and that a test user’s Copilot license is removed. Check the output log for details. - Publish the runbook
After testing, click Publish to make the runbook available for scheduling. - Create a schedule
Go to the runbook page. Under Resources, select Schedules. Click Add a schedule. Choose a frequency like Weekly and set a day and time that avoids peak usage. Link the schedule to the runbook.
Common Issues and Limitations
Runbook Fails with Insufficient Permissions
If the runbook returns an access denied error, verify that the managed identity has the correct Microsoft Graph API permissions. Go to the enterprise application for the Automation account and confirm that UserLicense.ReadWrite.All is granted with admin consent. Also confirm that the user running the schedule has a license to assign.
Sign-in Log Data Is Missing for Some Users
Entra ID stores sign-in logs only for users who have signed in at least once. If a user never signed in, the LastSignInDateTime property is null. The script above treats null as inactive and removes the license. To exclude never-signed-in users, add a condition to skip users with a null value.
Copilot License Reappears After Reclamation
If a user is part of a group-based license assignment in Entra ID, removing the license directly may be overridden by the group policy. In that case, remove the user from the group instead of removing the license. Modify the script to use Remove-MgGroupMember after identifying the group that assigns Copilot licenses.
Manual License Reclaim vs Automated Workflow
| Item | Manual Reclaim | Automated Workflow |
|---|---|---|
| Effort required | High: admin reviews each user manually | Low: runs on schedule without admin action |
| Consistency | Prone to human error and missed users | Identical logic applied every run |
| Notification to users | Requires separate email or manual message | Can be added to script via Send-MgUserMail |
| License recovery time | Days or weeks after inactivity detected | Within 24 hours of threshold being reached |
| Cost | No infrastructure cost | Azure Automation execution cost (low) |
You can now build and deploy a Copilot license reclaim workflow that runs automatically. Start with a small test group of users to validate the inactivity threshold and script behavior. Extend the workflow by adding email notifications using the Send-MgUserMail cmdlet so users are warned before their license is removed. For tighter control, consider integrating the script with your existing IT service management tool to create a ticket before license removal.