Cloud Engineer Lab
Cloud Engineer Lab
Cloud Engineer Lab
Cloud Engineer Lab
© 2026
AI for Intune Administrators: Turn Device Data Into Actionable Insights
Endpoint & CloudIntermediate

AI for Intune Administrators: Turn Device Data Into Actionable Insights

We gave an AI a 627-device sample with five planted problems. Raw device rows found none; letting code find the facts and the AI explain them found all five, with fixes kept behind approval.

14 min read
Share

Every Intune admin knows the view on this post's cover: hundreds of devices, a column of green ticks and red crosses, and the question nobody's dashboard answers directly: what is actually going wrong, why, and what should I do about it?

It's tempting to export the device list, paste it into an AI and ask. We tried exactly that, with a sample dataset where we knew the right answers in advance. It didn't work. What did work was splitting the job: code finds the facts, the AI explains them, and every proposed change waits for a person. This post shows both, with the numbers.

How we tested

  • The dataset: a sample of 627 Windows devices for a fictional company, Contoso, shaped like Microsoft Graph managedDevice records (name, user, model, OS build, update ring, last sync, BitLocker, real-time protection, firewall, password policy, compliance state), plus 30 days of daily compliance counts.

  • Five planted problems, so we could measure what each approach finds:

    #Planted problem
    P1BitLocker failing on many Contoso Book 14 laptops from day 18 (as if a firmware update had reset the TPM)
    P241 devices stuck on Windows 11 23H2 build 22631.4169, below the minimum OS version
    P317 devices that haven't synced for over 30 days but still show as compliant
    P4One user who enrolled 7 devices in a few days
    P5Real-time protection off on 9 build agents named ENG-BLD-*
  • The model: Qwen2.5-Coder-7B-Instruct, running locally at temperature 0. It's licensed Apache-2.0, so it's usable commercially (see the model supply chain post).

  • Privacy: user names were replaced with pseudonyms before the AI saw anything.

No real tenant was touched, and no Graph request was ever sent.

First, Get the Data Read-Only

In a real tenant, this data comes from Microsoft Graph. The device list is GET /deviceManagement/managedDevices; per-setting compliance and the Intune reports export API add detail. Two rules from the start:

  • The analysis identity can only read. Give the app that collects data read-only device management permissions, such as DeviceManagementManagedDevices.Read.All. Any change goes through a different identity, after approval (see the approval gate below). The Graph automation tasks post shows the collection side.
  • Pseudonymise people before the AI sees them. The AI doesn't need real names to spot that one account enrolled seven devices:
python
def pseudonym(upn):
    return "user-" + hashlib.sha256(("contoso-salt:" + upn).encode()).hexdigest()[:6]

In production, keep the salt secret and outside the code, so pseudonyms can't be reversed by guessing user names. Your team can still map a pseudonym back when it needs to act.

Attempt 1: Paste the Device Rows Into the AI

We gave the model as many device rows as fit in its context window: 140 of the 627 devices, plus the 30 daily compliance counts, about 9,900 tokens. We asked for a summary, the anomalies, and remediation steps. We repeated it with three different random samples.

Result: 0 of 5 planted problems found, in all three runs. Worse, the answers were confidently wrong:

  • It got the trend wrong. Two runs said non-compliance was falling ("The overall trend shows a decrease in noncompliance"); the third said it had "fluctuated" with a peak on "the 15th day". In fact it more than doubled, from 56 to 125, with the jump on day 18.
  • It mixed up the sample with the fleet. Two runs wrote "140 noncompliant devices out of 627". 140 was the number of rows it was shown; the real count was 123.
  • One run invented a statistic: "The compliance rate is currently at 78.3%". That number appears nowhere in the data.
  • It highlighted random single devices with a few failed settings, while missing the 73 failing laptops of one model.
  • It invented Graph endpoints, such as deviceCompliancePolicyAssignments and .../remediateNonCompliantDevices, which don't exist. To "notify users", it proposed assigning a compliance policy.

None of this is surprising once you think about it. A language model reading rows of CSV isn't counting, grouping or comparing rates; it's guessing from what it happens to notice. And a fleet of thousands of devices doesn't fit in the context window anyway.

Attempt 2: Let Code Compute the Facts

Counting, grouping and comparing is what code is for. A 73-line Python script (standard library only) computed:

  • The trend, flagging any day-over-day jump much larger than normal day-to-day noise.
  • Which settings are failing, among devices with recent data.
  • Concentrations: any group (by model, OS build, update ring, department or device name prefix) where a failure is at least three times more common than across the fleet.
  • Stale devices, analysed separately, because their compliance state is weeks old.
  • Enrolment spikes: users with three or more new devices in a week.

The concentration check is the most useful part:

python
    # cohorts where a failure is at least 3x more common than overall (and at least 5 devices)
    out["concentrations"] = []
    checks = {**{s: (lambda r, s=s: not r[s]) for s in SETTINGS}, "osVersion below minimum": lambda r: not r["osOk"]}
    for setting, failed in checks.items():
        overall = sum(failed(r) for r in fresh) / len(fresh)
        for field in ("model", "osVersion", "updateRing", "department", "prefix"):
            groups = defaultdict(list)
            for r in fresh:
                groups[r[field]].append(r)
            for value, members in groups.items():
                n = sum(failed(r) for r in members)
                if n >= 5 and overall and n / len(members) >= 3 * overall:
                    out["concentrations"].append({"setting": setting, "field": field, "value": value, "failing": n,
                                                  "of": len(members), "rate": round(n / len(members), 2),
                                                  "overall_rate": round(overall, 3)})

It found every planted problem:

FindingNumbers
Trend56 non-compliant on day 1, 125 now, with a jump of +71 on 9 October
BitLocker by modelContoso Book 14: 73 of 126 failing (58%, against 12% overall)
OS build10.0.22631.4169: 41 of 41 below the minimum
Real-time protection by name prefixENG-BLD: 9 of 9 off (against 1.5% overall)
Stale devices17 not synced for over 30 days (up to 71), all 17 still marked compliant
Enrolment spikeuser-7a15c5: 7 devices in the last 7 days

That isn't AI; it's ordinary analysis, and it's the part that has to be right. We wrote the data and the checks ourselves, so finding all five here proves the method works, not that every problem in a real tenant will be this clear.

Notice also that the Ring 3 update ring wasn't flagged on its own: 41 of its 219 devices were below the minimum, 2.79 times the fleet rate, just under the 3x threshold, while the OS build itself was 100%. The narrower group is the better explanation, and thresholds matter.

Attempt 3: Give the AI the Facts

Next we gave the model those facts, 668 tokens instead of 9,900, with the same open request: summarise, list anomalies, propose remediation.

It did much better on accuracy. It correctly said 123 of 627 devices were non-compliant and described the +71 jump on 9 October. But scored strictly, it covered only 1 of the 5 problems: the old OS build.

  • It mentioned BitLocker failures on "specific device models" without saying which, so an admin couldn't act on it.
  • It ignored the stale devices, the build agents and the enrolment spike completely, though all three were in the facts it received.
  • One proposed request contained an OS build, 10.0.19041.0, that appears nowhere in the data.
  • It proposed fixing a minimum OS version by editing a configuration profile, which isn't where that requirement lives or how a stuck update is fixed.

We had to fix our own scorer first

Our first scoring script gave this answer 3 of 5. It counted "Contoso Book 14" because the model had put the name inside the JSON body of a proposed Graph request, not in anything an admin would read. And our pattern for "7 devices" matched inside "627 devices". We changed the scorer to read only the summary and the anomaly descriptions, with whole-word matching, and re-scored every answer. Check your evaluation's matches by hand before believing its numbers.

Attempt 4: Code Finds, AI Explains, Actions From a Catalog

The pattern behind the failures: when the AI decides what matters, it drops things. When it writes API requests, it invents them. So we took both decisions away from it:

  1. Code turns the facts into a numbered list of findings. The AI must explain every finding, in order: what it means in plain language, the likely cause, the risk of ignoring it, and one or two next steps.
  2. Next steps come from a fixed catalog. The AI picks an action ID and a target. Code builds the Graph request, and each action carries its own approval tier.
python
CATALOG = {   # id: (what it does, tier, method, url template)
    "report_devices":        ("Export a filtered device list for review", "auto", "GET", G + "/v1.0/deviceManagement/managedDevices"),
    "sync_devices":          ("Ask the devices to check in now", "auto", "POST", G + "/v1.0/deviceManagement/managedDevices/{id}/syncDevice"),
    "run_remediation":       ("Run an existing, approved remediation script on the devices", "approve", "POST",
                              G + "/beta/deviceManagement/managedDevices/{id}/initiateOnDemandProactiveRemediation"),
    "rotate_bitlocker_keys": ("Rotate BitLocker recovery keys on the devices", "approve", "POST",
                              G + "/beta/deviceManagement/managedDevices/{id}/rotateBitLockerKeys"),
    "change_update_ring":    ("Change an update ring's settings or deadlines", "two", "PATCH", G + "/v1.0/deviceManagement/deviceConfigurations/{id}"),
    "change_policy_assignment": ("Change which groups a compliance policy applies to", "two", "POST",
                                 G + "/v1.0/deviceManagement/deviceCompliancePolicies/{id}/assign"),
    "retire_devices":        ("Retire devices (removes company data)", "two", "POST", G + "/v1.0/deviceManagement/managedDevices/{id}/retire"),
    "investigate":           ("Open a ticket for a person to investigate; no change", "auto", None, None),
}
python
def build_requests(answer):
    """Turn the AI's catalog choices into draft requests with their approval tier. Unknown ids are rejected."""
    drafts = []
    for item in answer.get("findings", []):
        for a in item.get("actions", []):
            entry = CATALOG.get(a.get("action"))
            if not entry:
                drafts.append({"finding": item.get("id"), "action": a.get("action"), "tier": "reject", "reason": "not in the catalog"})
                continue
            what, tier, method, url = entry
            drafts.append({"finding": item.get("id"), "action": a.get("action"), "tier": tier, "method": method, "url": url,
                           "target": a.get("target"), "why": a.get("why")})
    return drafts

Result: all 5 planted problems explained, plus the trend jump, from a 508-token prompt. The explanations named the group and the numbers an admin needs:

  • "BitLocker is failing on 73 out of 126 Contoso Book 14 devices (58% of these devices)."
  • "Real-time protection is failing on all 9 devices with the prefix ENG-BLD (100% of these devices)."
  • "17 devices have not synced for more than 30 days but are still marked compliant based on old data."
  • "User user-7a15c5 enrolled 7 devices in the last 7 days."

Every proposed action was a valid catalog entry, so no endpoints were invented.

It still wasn't perfect, and the post would be dishonest if it said otherwise:

  • One explanation garbled the numbers. It said non-compliance "increased by 71 from the start of the month to 125 on 2026-10-09". The +71 jump was on 9 October, and 125 is today's figure.
  • The "likely causes" were generic guesses, such as "There might be a software issue or a problem with the BitLocker recovery keys". It didn't connect the 9 October jump with the Book 14 BitLocker failures, and with no firmware data it couldn't have known the planted cause.
  • Some targets were too broad. For the trend jump it proposed changing a compliance policy's assignment for "All devices".

Keep Every Change Behind an Approval Gate

The twelve draft actions from Attempt 4 split like this:

TierCountExamplesWhat happens
Auto8Export a device list, ask devices to sync, open an investigation ticketRuns without asking; logged
Approve2Run an existing remediation script on the ENG-BLD devices; rotate BitLocker keys on the Book 14 devicesA named Intune admin approves the exact request
Two people2Change the update ring for the 22631 devices; change a compliance policy's assignment for "All devices"Two admins approve; normally with a change ticket

The "All devices" assignment change landed in the two-person tier, exactly where a reviewer should reject it. That's the gate working as intended: the AI is allowed to be wrong, because nothing it proposes changes a policy until people agree.

In practice:

  • Use separate identities. The analysis app can only read. The account that applies changes is separate, scoped to the actions in the catalog, and used only after approval.
  • The approver sees the actual request, not the AI's summary: the method, the URL, the target devices, and the finding that triggered it.
  • Re-check before applying. Device state changes; a device that was failing yesterday may be fine today.
  • Log everything: the finding, the AI's explanation, the proposal, who approved it, and the result.

Human-in-the-loop AI and AI agent permissions cover how to build that gate and the identities behind it.

What the Admin Still Does

The AI turned facts into a readable briefing in seconds. The investigation is still yours:

FindingWhat a person checks next
Book 14 BitLocker failures from 9 OctoberWhat changed that day: firmware, BIOS or TPM updates, driver rollouts; the BitLocker event logs on one affected device
41 devices on build 22631The update ring and feature update policies for those devices; safeguard holds; whether they're actually checking in
17 stale devices still "compliant"Whether they still exist; your device cleanup rules; Conditional Access treatment of stale devices (what happens when a device stops checking in)
7 enrolments by one userWhether it's legitimate (a lab, a team lead setting up kit) or a risk; your enrolment device limits
Real-time protection off on ENG-BLDWhether these build agents have an approved exclusion, or a policy gap; what compensating controls exist

Checklist

  • Device data comes from Graph through a read-only identity.
  • Users are pseudonymised before the AI sees anything; the salt is kept secret.
  • Code computes trends, failure rates, concentrations, stale devices and spikes; the AI never counts.
  • The AI explains every finding code gives it; it doesn't choose which ones matter.
  • Remediations come from a fixed catalog of real Graph actions; the AI never writes a URL.
  • Each catalog action has a tier: auto, approve, or two-person.
  • Policy, assignment and retire actions always need approval; changes run under a separate identity.
  • The scoring and the planted-problem tests are re-run whenever the prompt, model or thresholds change.

For monthly trends rather than device lists, AI + Power BI: Explain IT Trends in Plain English applies the same pattern to a semantic model, with every sentence checked and linked back to the report.

The Short Version

ApproachPlanted problems found (of 5)Prompt sizeWhat went wrong
AI reads raw device rows0, in all 3 samplesabout 9,900 tokensTrend backwards, sample confused with fleet, a made-up percentage, invented Graph endpoints
AI reads computed facts, free-form1668 tokensSkipped three findings it was given; an invented OS build
Code finds, AI explains, actions from a catalog5508 tokensOne garbled sentence, generic causes, one over-broad target, caught by the two-person gate

AI is useful to an Intune admin, but not as an analyst. Let code find the facts, let the AI explain them in plain language, and let people approve anything that changes a device or a policy.

CChetan Yamger

Written by

Chetan Yamger

Cloud Engineer · AI Automation Architect · Modern Workplace Consultant

Cloud Engineer, AI Automation Architect, and Modern Workplace Consultant based in Amsterdam, Netherlands. Specializing in scalable, secure enterprise solutions with Microsoft Azure, Intune, PowerShell, and AI-driven automation using ChatGPT, Gemini, and modern LLM technologies.

Cloud & Modern WorkplaceMicrosoft Intune & MDMAzure & Microsoft 365AI AutomationPrompt EngineeringPowerShell & Graph APIWindows AutopilotConditional Access & Zero TrustSCCM / MECM & MSIXVDI / WVDPower BINode.js & Next.js
Newsletter

Stay in the loop.
New articles, straight to you.

Deep-dive technical articles on Intune, PowerShell, and AI — no noise, no spam.

New article notifications
No spam, ever
Free forever

Discussion

Share your thoughts — your email stays private

Leave a comment

0/2000

Your email is used to prevent spam and will never be displayed.