Microsoft setup commands
Every command to run in your Microsoft tenant for Agent 365, Microsoft 365 grounding, Purview and Sentinel, in order, with the role ids filled in.
Every command an organisation runs in its own Microsoft tenant for AIOE's Microsoft features, in
order: Agent 365 (Microsoft Agent 365), Microsoft 365 grounding through Work IQ (Memory),
Purview (Microsoft Purview) and Sentinel. Run them as a Global Administrator, in a shell signed in to
the organisation's tenant (az login --tenant <tenant id>; check with az account show).
Enterprise edition only.
Two rules Microsoft enforces shape what follows:
- A blueprint is barred from some calls whatever it holds. Graph answers it
403 UnknownErroron the Agent 365 registry and Purview's labels, refuses it file permissions outright, and refuses it app-only observability tokens (AADSTS82001). AIOE makes those calls as the AIOE API application (the registration people sign in to AIOE with) or as an agent identity, so some roles go on more than one principal. - Assign roles straight to service principals. The blueprint's registration declares no
permissions, so its admin-consent page fails with
AADSTS1003031. An assignment needs no consent step. A new role only reaches tokens minted after it: allow a few minutes, then use the panel's Try again or Connect, which ask for fresh tokens.
0. The ids
TENANT=$(az account show --query tenantId -o tsv)
GRAPH_SP=$(az ad sp show --id 00000003-0000-0000-c000-000000000000 --query id -o tsv) # Microsoft Graph in this tenant
# The AIOE API application: the console shows it as "API scope" under Settings (api://<id>/...).
API_APP=<AIOE API application (client) id>
API_SP=$(az ad sp show --id $API_APP --query id -o tsv)
# The deployment's managed identity (Azure): its principal (object) id.
MI_PRINCIPAL=$(az identity show -g <resource group> -n <identity name> --query principalId -o tsv)
# The person accountable for the agents (sponsor and owner).
SPONSOR=$(az ad user show --id <their UPN> --query id -o tsv)
# One helper for every application role below.
grant() { # grant <principal sp id> <resource sp id> <app role id>
az rest --method POST \
--url "https://graph.microsoft.com/v1.0/servicePrincipals/$1/appRoleAssignments" \
--body "{\"principalId\":\"$1\",\"resourceId\":\"$2\",\"appRoleId\":\"$3\"}" \
--query appRoleId -o tsv
}The application role ids are Microsoft's and the same in every tenant:
| Role | Resource | Id |
|---|---|---|
AgentRegistration.ReadWrite.All | Microsoft Graph | 39fb8c64-7bd3-4107-8515-14d6e55ddda4 |
InformationProtectionPolicy.Read.All | Microsoft Graph | 19da66cb-0fb0-4390-b071-ebc76a349482 |
ProtectionScopes.Compute.User | Microsoft Graph | fe696d63-5e1f-4515-8232-cccc316903c6 |
Content.Process.User | Microsoft Graph | 24ceb246-ad29-4680-90b4-3e91ffad15eb |
ContentActivity.Write | Microsoft Graph | 2932e07a-3c29-44e4-bb36-6d0fc176387f |
Files.ReadWrite.All | Microsoft Graph | 75359482-378d-4052-8f01-80520e7db3cd |
Agent365.Observability.OtelWrite | Agent 365 observability (app 9b975845-388f-4429-889e-eab1ef63949c, shown as "maven-prod") | 8f71190c-00c8-461d-a63b-f74abde9ba52 |
1. Agent 365: the blueprint
Create it in the Entra admin centre (Entra ID, Agents, Agent blueprints, New agent blueprint), or:
BLUEPRINT_APP=$(az rest --method POST --url "https://graph.microsoft.com/v1.0/applications/microsoft.graph.agentIdentityBlueprint" \
--headers "OData-Version=4.0" \
--body "{\"displayName\":\"AIOE agents\",\"sponsors@odata.bind\":[\"https://graph.microsoft.com/v1.0/users/$SPONSOR\"],\"owners@odata.bind\":[\"https://graph.microsoft.com/v1.0/users/$SPONSOR\"]}" \
--query appId -o tsv)
az rest --method POST --url "https://graph.microsoft.com/v1.0/serviceprincipals/microsoft.graph.agentIdentityBlueprintPrincipal" \
--headers "OData-Version=4.0" --body "{\"appId\":\"$BLUEPRINT_APP\"}"
BLUEPRINT_SP=$(az ad sp show --id $BLUEPRINT_APP --query id -o tsv)Give it the deployment's managed identity as its credential (no secret anywhere):
az rest --method POST \
--url "https://graph.microsoft.com/v1.0/applications(appId='$BLUEPRINT_APP')/federatedIdentityCredentials" \
--headers "OData-Version=4.0" \
--body "{\"name\":\"aioe-prod\",\"issuer\":\"https://login.microsoftonline.com/$TENANT/v2.0\",\"subject\":\"$MI_PRINCIPAL\",\"audiences\":[\"api://AzureADTokenExchange\"]}"Outside Azure, add a client secret instead (Entra admin centre, the blueprint, Certificates and secrets; needs the Agent ID Administrator role) and paste it into the panel.
2. Agent 365: the registry
Cards go as the AIOE API application, which the registry then records as their manager:
grant $API_SP $GRAPH_SP 39fb8c64-7bd3-4107-8515-14d6e55ddda4 # AgentRegistration.ReadWrite.All
grant $BLUEPRINT_SP $GRAPH_SP 39fb8c64-7bd3-4107-8515-14d6e55ddda4 # the same, for the blueprint's first tryThen in the console: Settings, Microsoft Agent 365, the blueprint's application id, This deployment's managed identity, Connect. Create an enterprise team on the Portfolio page; each agent member gets an identity and a card.
3. Agent 365: the licence row (optional)
A registered agent exports its runs without a further role. Only the panel's licence question needs the observability role, on each agent identity (the ids are shown on each member in the panel):
OBS_SP=$(az ad sp show --id 9b975845-388f-4429-889e-eab1ef63949c --query id -o tsv)
for AGENT in <agent identity id> <agent identity id>; do
grant $AGENT $OBS_SP 8f71190c-00c8-461d-a63b-f74abde9ba52
done4. Microsoft 365 grounding (Work IQ)
az ad sp create --id fdcc1f02-fc51-4226-8753-f668596af7f7 # Work IQ's service principal, once per tenant
az ad app permission add --id $API_APP --api fdcc1f02-fc51-4226-8753-f668596af7f7 \
--api-permissions 0b1715fd-f4bf-4c63-b16d-5be31f9847c2=Scope # WorkIQAgent.Ask (delegated)
az ad app permission admin-consent --id $API_APPSet a Copilot Credits spending policy in the Microsoft 365 admin centre, then Settings, Microsoft 365 Grounding, Switch on.
5. Purview: labels, verdicts and activity
The four on both principals; the platform tries the blueprint and falls back to the API application:
for ROLE in 19da66cb-0fb0-4390-b071-ebc76a349482 fe696d63-5e1f-4515-8232-cccc316903c6 \
24ceb246-ad29-4680-90b4-3e91ffad15eb 2932e07a-3c29-44e4-bb36-6d0fc176387f; do
grant $BLUEPRINT_SP $GRAPH_SP $ROLE
grant $API_SP $GRAPH_SP $ROLE
doneThen Settings, Microsoft Purview, Connect, and map the labels.
6. Purview: encrypting labels through SharePoint (optional)
grant $API_SP $GRAPH_SP 75359482-378d-4052-8f01-80520e7db3cd # Files.ReadWrite.All (the blueprint is refused it)
# Microsoft meters assignSensitivityLabel: link the API application to a subscription in the same tenant.
az provider register --namespace Microsoft.GraphServices
az provider show -n Microsoft.GraphServices --query registrationState -o tsv # repeat until "Registered"
az rest --method PUT \
--url "https://management.azure.com/subscriptions/$(az account show --query id -o tsv)/resourceGroups/<resource group>/providers/Microsoft.GraphServices/accounts/aioe-api-graph-billing?api-version=2023-04-13" \
--body "{\"location\":\"global\",\"properties\":{\"appId\":\"$API_APP\"}}"Authorization_IdentityNotFound on the last call means the provider is still registering: wait and
repeat it. Then tick Offer the SharePoint route in the panel and set a site.
7. Purview: Ask Purview itself (optional)
Turn on Purview pay-as-you-go once: the Purview portal, the rocket icon at the top right (or Settings, Account details), Get Started, a subscription and resource group in the same tenant. It takes a few hours.
The DLP policy is PowerShell only (the portal's policies cover Microsoft 365, not an app like this).
Windows PowerShell, or PowerShell 7 (pwsh) anywhere; not bash:
Install-Module ExchangeOnlineManagement -Scope CurrentUser
Connect-IPPSSession -UserPrincipalName <admin UPN> # in WSL or a terminal without a browser: Connect-IPPSSession -Device
$appId = "<blueprint application id>"
$locations = "[{`"Workload`":`"Applications`",`"Location`":`"$appId`",`"LocationDisplayName`":`"Mojo Up AI Workbench`",`"LocationSource`":`"Entra`",`"LocationType`":`"Individual`",`"Inclusions`":[{`"Type`":`"Tenant`",`"Identity`":`"All`"}]}]"
New-DlpCompliancePolicy -Name "AI Workbench prompts" -Mode Enable -Locations $locations -EnforcementPlanes @("Application")
New-DlpComplianceRule -Name "Block credentials in prompts" -Policy "AI Workbench prompts" `
-ContentContainsSensitiveInformation @{Name = "All Credential Types"} `
-RestrictAccess @(@{setting = "UploadText"; value = "Block"}) -GenerateAlert $true
Get-DlpCompliancePolicy "AI Workbench prompts" | Format-List Name, Mode, Locations # checkAllow an hour, then check it with Try a prompt in the panel (under Ask Purview itself): paste a fake credential and expect "In scope of a DLP policy" and "Blocked", naming the policy. Then set Ask Purview itself to "Prompts to hosted models". Optionally, in DSPM for AI (classic), Recommendations, Secure interactions from enterprise apps.
8. Sentinel (optional)
Deploy the table, data collection rule and detections from AI Workbench's
docs/integrations/microsoft-sentinel, then let the blueprint write to the rule:
DCR_ID=$(az monitor data-collection rule show -g <resource group> -n <rule name> --query id -o tsv)
az role assignment create --assignee-object-id $BLUEPRINT_SP --assignee-principal-type ServicePrincipal \
--role "Monitoring Metrics Publisher" --scope $DCR_IDThen Settings, Microsoft Sentinel: the logs ingestion endpoint and the rule's immutable id.
Check what is granted
for SP in $BLUEPRINT_SP $API_SP; do
echo "== $SP"
az rest --method GET --url "https://graph.microsoft.com/v1.0/servicePrincipals/$SP/appRoleAssignments" \
--query "value[].{role:appRoleId,resource:resourceDisplayName}" -o table
doneWhen something is refused
| Message | Meaning | What to do |
|---|---|---|
AADSTS1003031 on the consent page | The blueprint's registration declares no permissions | Use the grant commands; no consent page is needed |
cannot be granted to agent identity blueprint principals | A role Entra never gives a blueprint (files) | Grant it to the AIOE API application |
UnknownError (Graph answered 403) as the blueprint | Graph bars the blueprint from that endpoint | Expected: AIOE retries as the API application; grant the role there |
| The same 403 as the API application, minutes after a grant | The token predates the grant | Wait a few minutes, then Try again |
You do not have permission to create an agent registration managed by another AppId | A card naming another app as its manager | Fixed in AIOE 0.5.2: update |
AADSTS82001 | An agentic application asked for an app-only observability token | Expected: AIOE asks as an agent identity |
| Licence row: Microsoft did not answer (403) | The agent identities lack the observability role | Optional: step 3 |
Install-Module: command not found | PowerShell commands run in bash | Run them in PowerShell |
Authorization_IdentityNotFound on the billing account | Microsoft.GraphServices is still registering | Wait for "Registered", repeat |