<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Microsoft Graph on DR.365</title><link>https://blog.dr365.io/tags/microsoft-graph/</link><description>Recent content in Microsoft Graph on DR.365</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Wed, 14 Oct 2026 07:00:00 +0200</lastBuildDate><atom:link href="https://blog.dr365.io/tags/microsoft-graph/index.xml" rel="self" type="application/rss+xml"/><item><title>Built for human pace: what Anthropic's source control rewrite means for enterprise IT strategy</title><link>https://blog.dr365.io/p/agent-scale-enterprise-it-strategy/</link><pubDate>Wed, 14 Oct 2026 07:00:00 +0200</pubDate><guid>https://blog.dr365.io/p/agent-scale-enterprise-it-strategy/</guid><description>&lt;img src="https://blog.dr365.io/p/agent-scale-enterprise-it-strategy/cover.png" alt="Featured image of post Built for human pace: what Anthropic's source control rewrite means for enterprise IT strategy" /&gt;&lt;p&gt;In May 2026, Anthropic merged about 2,500 code changes per day into its monorepo. By September it was more than 30,000. Git and the mirror infrastructure around it could not keep up, so a team of seven built its own version control system and moved the entire monorepo onto it in five months (&lt;a class="link" href="https://www.anthropic.com/engineering/redesigning-source-control" target="_blank" rel="noopener"
 &gt;Anthropic Engineering&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Almost nobody reading this will build a version control system. That isn&amp;rsquo;t the point of the story. Every organization runs processes that were sized for the speed of people: change advisory boards, four-eyes approvals, access reviews, CI pipelines, budgets calculated in person-days. Once agents do a large share of the work, those processes become the bottleneck, and the question is which of them you redesign before they break.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agents are becoming the main consumers of your systems. Architecture decisions should assume machine clients that are always online and call APIs at high volume.&lt;/li&gt;
&lt;li&gt;Review and approval have to move from &amp;ldquo;a human looked at everything&amp;rdquo; to rules that decide where a human must look.&lt;/li&gt;
&lt;li&gt;Every agent needs an identity, an accountable person and a cost center. Without those three you can neither govern nor budget agent work.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="what-anthropic-actually-changed"&gt;What Anthropic actually changed
&lt;/h2&gt;&lt;p&gt;The headlines say &amp;ldquo;Anthropic threw out Git&amp;rdquo;. The engineering post is more careful. The new system is called Scion, the review tool Antique. Anthropic explicitly says Scion is not a general replacement for git, because that would mean replacing the whole development toolchain. They published the design so that git platforms can adopt parts of it.&lt;/p&gt;
&lt;p&gt;The numbers explain why they did it anyway. The main branch history is almost 100 GB, a compressed working copy more than 25 GB, and CI runs roughly 25 million checkouts per day. Git is designed for distributed clients that work offline. Anthropic&amp;rsquo;s clients are almost entirely agents and jobs that are always online. Scion moves the expensive work to the server: commits, merges, rebases, history and blame happen there, clients get sparse, virtualized checkouts that load files on demand, and much of the functionality is available through an API without any local repository. According to the post, the new infrastructure uses about 200 times less CPU and memory than the old git mirrors, and CI checkouts take seconds instead of minutes.&lt;/p&gt;
&lt;p&gt;Three decisions in the post matter beyond source control:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There is no merge queue with a global lock. Anthropic invested in post-merge and pre-deploy testing instead. Conflicts between concurrent changes happen, and Claude usually fixes them faster than a human would notice them.&lt;/li&gt;
&lt;li&gt;Antique can express semantic rules for approvals. A comment-only change gets treated differently from a change to sensitive logic, so human reviewers spend their time where it counts.&lt;/li&gt;
&lt;li&gt;Access control at repository and directory level was built in from the start, not added later.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="agents-are-the-new-primary-client"&gt;Agents are the new primary client
&lt;/h2&gt;&lt;p&gt;The first lesson is about architecture. Most enterprise systems assume a person in front of a screen. Agents behave differently: they poll, they run in parallel, and they don&amp;rsquo;t take lunch breaks.&lt;/p&gt;
&lt;p&gt;In Microsoft 365 you can see this today in Microsoft Graph throttling. Microsoft lists two typical causes: many requests across all applications in a tenant, and many requests from one application across tenants. Polling a resource and repeatedly scanning collections are named as patterns that lead to throttling. The recommended alternatives are delta queries and change notifications, and for bulk extraction Microsoft points to Graph Data Connect instead of the REST APIs (&lt;a class="link" href="https://learn.microsoft.com/graph/throttling" target="_blank" rel="noopener"
 &gt;Microsoft Learn&lt;/a&gt;). SharePoint Online goes one step further: an application that keeps exceeding limits can be blocked entirely (&lt;a class="link" href="https://learn.microsoft.com/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online" target="_blank" rel="noopener"
 &gt;Microsoft Learn&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;That guidance was written for integration developers. It now applies to every agent that reads mailboxes, sites or Teams channels on someone&amp;rsquo;s behalf. When I evaluate an agent scenario, I now ask how it detects changes before I ask what it does. An agent that rescans a document library every ten minutes works fine in the pilot and becomes a problem when 40 departments copy it.&lt;/p&gt;
&lt;p&gt;For your own systems the same principle applies in the other direction. If agents are going to be the main consumers of an internal platform, give it a proper API, change feeds and per-client limits. A web UI with a scraping agent in front of it is the git mirror of your organization: it works until the volume grows tenfold.&lt;/p&gt;
&lt;h2 id="review-by-intent-instead-of-line-by-line"&gt;Review by intent instead of line by line
&lt;/h2&gt;&lt;p&gt;The second lesson concerns control processes. The Anthropic team still reviews every change, but they review the intent, not every line. Their main job, as they describe it, is telling Claude &amp;ldquo;no&amp;rdquo;: when it violates system constraints, or when it over-engineers in response to hypothetical concerns.&lt;/p&gt;
&lt;p&gt;In regulated environments this is the uncomfortable part. Many change processes implicitly promise that a qualified person checked everything. At 30,000 changes per day that promise can&amp;rsquo;t be kept, and honestly it often wasn&amp;rsquo;t kept at 30 per week either. The CAB that approves a stack of changes in 45 minutes is mostly checking that the form is complete.&lt;/p&gt;
&lt;p&gt;In my experience, auditors want evidence that changes are controlled and traceable. NIS2 asks for risk management measures that include security in development and maintenance; it does not prescribe that a human reads every line. That leaves room for a model that ITIL already knows as standard changes, applied to agent output:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Low risk&lt;/strong&gt; (documentation, tests, formatting, configuration within defined guardrails): automated checks, no mandatory human review, full logging.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Medium risk&lt;/strong&gt; (business logic, integrations): human review of intent and test evidence, with the agent&amp;rsquo;s summary as input.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High risk&lt;/strong&gt; (authentication, permissions, data flows across trust boundaries, anything regulated): line-level review by a named person, the way it has always been.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What decides the tier has to be a rule, not a gut feeling. Anthropic models this in the review tool, and you can model it in branch protection rules, CODEOWNERS files or a Power Automate approval flow. The rule itself is the control that an auditor will want to see.&lt;/p&gt;
&lt;p&gt;I would be careful with one part of the Anthropic approach: moving checks after the merge. For an internal developer platform that is a reasonable trade. For a system in a KRITIS environment where a faulty change can reach production directly, I wouldn&amp;rsquo;t do it. The safeguard has to sit before deployment, even if it no longer sits before the merge.&lt;/p&gt;
&lt;h2 id="every-agent-needs-an-identity-and-an-owner"&gt;Every agent needs an identity and an owner
&lt;/h2&gt;&lt;p&gt;Anthropic built access control into Scion from day one, down to the directory level. In Microsoft 365 the equivalent is the identity layer for agents. Microsoft Entra Agent ID gives agents their own identities in the directory, created from agent identity blueprints. Every agent identity requires a human sponsor who is accountable for purpose, lifecycle and access reviews. If the sponsor leaves, sponsorship transfers to their manager. Conditional Access and access packages from entitlement management apply to agents as well (&lt;a class="link" href="https://learn.microsoft.com/entra/id-governance/agent-id-governance-overview" target="_blank" rel="noopener"
 &gt;Microsoft Learn&lt;/a&gt;). As of October 2026, identity governance for agents is labeled preview, and the licensing depends on Microsoft 365 E7 or Agent 365 licenses; check the current terms before you plan with it.&lt;/p&gt;
&lt;p&gt;On top of that, Microsoft Agent 365 provides the registry as one inventory of Microsoft and non-Microsoft agents, including counts of agents without owners (&lt;a class="link" href="https://learn.microsoft.com/microsoft-365/admin/manage/agent-registry" target="_blank" rel="noopener"
 &gt;Microsoft Learn&lt;/a&gt;). I described the governance side in more detail in &lt;a class="link" href="https://blog.dr365.io/p/agent-lifecycle-agent-builder-copilot-studio/" &gt;the post on the agent lifecycle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The strategic point: an agent that runs under a shared service account or a person&amp;rsquo;s delegated credentials cannot be distinguished in the audit log, cannot be throttled separately and cannot be billed separately. Fixing that later for hundreds of agents is the kind of project nobody wants to fund.&lt;/p&gt;
&lt;h2 id="measuring-agent-work"&gt;Measuring agent work
&lt;/h2&gt;&lt;p&gt;The budget side breaks in the same way. Controlling in most IT organizations still calculates in person-days, and that model has no line for agent work. A practical way to close the gap is to route agent sessions through an AI gateway, so that every token and every hour of runtime can be assigned to a project and a repository and priced at real cost.&lt;/p&gt;
&lt;p&gt;A feature that needed 20 days last year and 3 days of review plus agent runtime this year doesn&amp;rsquo;t fit that model. Counting agent hours is a start, but hours are an input metric. What you want to know is the cost per accepted change: tokens and runtime plus the human time for review, rework and the cases where someone had to say &amp;ldquo;no&amp;rdquo;. Without the human share, agent work looks cheaper than it is.&lt;/p&gt;
&lt;p&gt;For Microsoft agents, Agent 365 observability collects activity data and is meant to support business metrics like usage and time savings (&lt;a class="link" href="https://learn.microsoft.com/microsoft-agent-365/admin/monitor-agents" target="_blank" rel="noopener"
 &gt;Microsoft Learn&lt;/a&gt;). That covers part of the picture. Coding agents outside Microsoft 365 need their own attribution, and that is where the gateway approach comes in.&lt;/p&gt;
&lt;!-- TODO Daniel: Optional eigene Beobachtung ergänzen, wie Agentenkosten bei euch heute verbucht werden (verallgemeinert, ohne Kundennamen). --&gt;
&lt;h2 id="decisions-for-the-next-twelve-months"&gt;Decisions for the next twelve months
&lt;/h2&gt;&lt;p&gt;Anthropic expects other organizations to run into this class of problem within the next six to twelve months. Even if your timeline is longer, these are the decisions I would make now:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Inventory human-paced controls.&lt;/strong&gt; List every approval, review and pipeline step that assumes a person and a working day. Mark which ones would break at ten times the volume.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Introduce risk tiers for changes.&lt;/strong&gt; Write down which changes need a human, which need a human for intent only and which need logging only. Make the rule machine-readable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Give agents their own identities.&lt;/strong&gt; No shared service accounts, every agent with a sponsor, permissions through access packages with an expiry date.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Design integrations for machine clients.&lt;/strong&gt; Delta queries, change notifications and API budgets instead of polling and scraping.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Attribute agent cost.&lt;/strong&gt; Tokens and runtime per project, plus the human review time, from the first productive agent onward.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;What I wouldn&amp;rsquo;t do is copy Anthropic&amp;rsquo;s tooling. Their problem was 25 million checkouts a day. Yours is more likely a change process that takes two weeks for a configuration change an agent prepared in ten minutes. That is the place to start.&lt;/p&gt;
&lt;h2 id="references"&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Anthropic Engineering: &lt;a class="link" href="https://www.anthropic.com/engineering/redesigning-source-control" target="_blank" rel="noopener"
 &gt;Redesigning source control at Anthropic&lt;/a&gt; (October 13, 2026)&lt;/li&gt;
&lt;li&gt;Microsoft Learn: &lt;a class="link" href="https://learn.microsoft.com/graph/throttling" target="_blank" rel="noopener"
 &gt;Microsoft Graph throttling guidance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microsoft Learn: &lt;a class="link" href="https://learn.microsoft.com/sharepoint/dev/general-development/how-to-avoid-getting-throttled-or-blocked-in-sharepoint-online" target="_blank" rel="noopener"
 &gt;Avoid getting throttled or blocked in SharePoint Online&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microsoft Learn: &lt;a class="link" href="https://learn.microsoft.com/entra/id-governance/agent-id-governance-overview" target="_blank" rel="noopener"
 &gt;Governing agent identities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microsoft Learn: &lt;a class="link" href="https://learn.microsoft.com/microsoft-365/admin/manage/agent-registry" target="_blank" rel="noopener"
 &gt;Manage agent registry in Microsoft 365 admin center&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Microsoft Learn: &lt;a class="link" href="https://learn.microsoft.com/microsoft-agent-365/admin/monitor-agents" target="_blank" rel="noopener"
 &gt;Agent 365 observability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;EUR-Lex: &lt;a class="link" href="https://eur-lex.europa.eu/eli/dir/2022/2555/oj" target="_blank" rel="noopener"
 &gt;Directive (EU) 2022/2555 (NIS2)&lt;/a&gt;, Article 21&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>PowerShell or Microsoft Graph? Choosing the Right Interface and Fixing Module Conflicts</title><link>https://blog.dr365.io/p/powershell-vs-microsoft-graph-module-conflicts/</link><pubDate>Sun, 11 Oct 2026 07:00:00 +0200</pubDate><guid>https://blog.dr365.io/p/powershell-vs-microsoft-graph-module-conflicts/</guid><description>&lt;img src="https://blog.dr365.io/p/powershell-vs-microsoft-graph-module-conflicts/cover.png" alt="Featured image of post PowerShell or Microsoft Graph? Choosing the Right Interface and Fixing Module Conflicts" /&gt;&lt;p&gt;&amp;ldquo;Should I do this with PowerShell or with Graph?&amp;rdquo; breaks down into two questions: &lt;em&gt;which interface actually exposes what I need&lt;/em&gt;, and &lt;em&gt;how will this thing run in six months when nobody is watching it&lt;/em&gt;. If you&amp;rsquo;ve ever mixed the Graph PowerShell SDK with PnP.PowerShell or the Exchange Online module in one script, you know the third question, the one nobody asks until it bites: &lt;em&gt;will these modules even load together?&lt;/em&gt;&lt;/p&gt;

 &lt;blockquote&gt;
 &lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;Exchange Online PowerShell&lt;/strong&gt; for Exchange administration (mailbox permissions, transport rules, org config). Graph doesn&amp;rsquo;t cover most of it.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Microsoft Graph&lt;/strong&gt; for identity, cross-service data and anything an &lt;em&gt;application&lt;/em&gt; does: integrations, mail sending, reporting. For application access to mailboxes, Graph is the interface to build on.&lt;/li&gt;
&lt;li&gt;The classic trap when combining them: &lt;strong&gt;assembly conflicts&lt;/strong&gt; (&lt;code&gt;Microsoft.Identity.Client&lt;/code&gt;, &lt;code&gt;Microsoft.Graph.Core&lt;/code&gt;, &lt;code&gt;Azure.Core&lt;/code&gt; …) between Microsoft.Graph, PnP.PowerShell, ExchangeOnlineManagement and Az. Connection order is a lottery; &lt;strong&gt;process isolation and fewer modules&lt;/strong&gt; are the real fix.&lt;/li&gt;
&lt;/ul&gt;

 &lt;/blockquote&gt;
&lt;h2 id="what-youre-actually-choosing-between"&gt;What you&amp;rsquo;re actually choosing between
&lt;/h2&gt;&lt;p&gt;The Microsoft Graph PowerShell SDK &lt;em&gt;is&lt;/em&gt; PowerShell, and it calls Graph under the hood. So the choice is between two kinds of interface:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Service-specific admin modules:&lt;/strong&gt; ExchangeOnlineManagement, MicrosoftTeams, PnP.PowerShell for SharePoint. They talk to the admin surfaces of a workload and expose things that simply don&amp;rsquo;t exist in Graph.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Microsoft Graph:&lt;/strong&gt; one REST API for Entra ID, mail, calendars, files, Teams, Planner and much more, callable from anything: the Graph PowerShell SDK, &lt;code&gt;Invoke-RestMethod&lt;/code&gt;, C#, Python, Logic Apps or a ticketing system.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Which one to use depends first on &lt;em&gt;which surface has the capability at all&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="where-each-one-wins"&gt;Where each one wins
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;Task&lt;/th&gt;
					&lt;th&gt;My pick&lt;/th&gt;
					&lt;th&gt;Why&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;Full Access / Send As permissions, transport rules, org-wide Exchange settings&lt;/td&gt;
					&lt;td&gt;Exchange Online PowerShell&lt;/td&gt;
					&lt;td&gt;Graph has no endpoints for these. The new Exchange Online Admin API (preview) only covers a small subset like folder permissions and Send on Behalf.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Users, groups, licences, app registrations in Entra ID&lt;/td&gt;
					&lt;td&gt;Graph (SDK or REST)&lt;/td&gt;
					&lt;td&gt;This is Graph&amp;rsquo;s home turf.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;An application sends or reads mail (ticketing, workflows)&lt;/td&gt;
					&lt;td&gt;Graph&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;sendMail&lt;/code&gt; / message endpoints with OAuth, scoped via RBAC for Applications.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Site provisioning, templates, SharePoint permissions&lt;/td&gt;
					&lt;td&gt;PnP.PowerShell&lt;/td&gt;
					&lt;td&gt;Far richer than Graph&amp;rsquo;s SharePoint surface for admin tasks.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Teams policies (meeting, calling, messaging)&lt;/td&gt;
					&lt;td&gt;MicrosoftTeams module&lt;/td&gt;
					&lt;td&gt;Policy management lives in the Teams admin surface, not in Graph.&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;Cross-service reporting (users + licences + sign-ins + groups)&lt;/td&gt;
					&lt;td&gt;Graph&lt;/td&gt;
					&lt;td&gt;One API, one auth model, paging and &lt;code&gt;$select&lt;/code&gt; built in.&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;My rule of thumb: &lt;strong&gt;if a person runs it, use the module that&amp;rsquo;s closest to the workload. If an application runs it, use Graph&lt;/strong&gt; – and give that application exactly the permissions it needs, nothing more.&lt;/p&gt;
&lt;h2 id="a-practical-example-mail-integrations"&gt;A practical example: mail integrations
&lt;/h2&gt;&lt;p&gt;The LinkedIn post that inspired this article describes modernising a ServiceNow mail integration so that it sends and receives mail through Microsoft Graph. Here an application, not a person, works with mailboxes, and that&amp;rsquo;s where Graph fits: OAuth, granular permissions and a clean audit trail. Sending a message is a single call:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Microsoft Graph v1.0 – send mail as the service mailbox (app-only)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Required application permission: Mail.Send (scoped via RBAC for Applications, see below)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Ticket INC0012345 updated&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;contentType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Text&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Your ticket has been updated.&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;toRecipients&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;emailAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;adele.vance@contoso.com&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;saveToSentItems&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="vm"&gt;$true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Invoke-MgGraphRequest&lt;/span&gt; &lt;span class="n"&gt;-Method&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;-Uri&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://graph.microsoft.com/v1.0/users/servicedesk@contoso.com/sendMail&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;-Body&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;ConvertTo-Json&lt;/span&gt; &lt;span class="n"&gt;-Depth&lt;/span&gt; &lt;span class="mf"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;-ContentType&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;application/json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;What I&amp;rsquo;d add from a regulated-environment perspective: an app with the application permission &lt;code&gt;Mail.Send&lt;/code&gt; can, by default, send as &lt;em&gt;any&lt;/em&gt; mailbox in the tenant. That&amp;rsquo;s not something you want to explain to an auditor. Use &lt;strong&gt;RBAC for Applications in Exchange Online&lt;/strong&gt; to scope the service principal to the mailboxes it actually needs:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Exchange Online PowerShell – scope a ticketing app to its service mailboxes only&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Prerequisite: the Entra app has NO tenant-wide Mail.Send consent (otherwise permissions add up)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# IDs from &amp;#34;Enterprise applications&amp;#34; in Entra, not from &amp;#34;App registrations&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;New-ServicePrincipal&lt;/span&gt; &lt;span class="n"&gt;-AppId&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;app-id&amp;gt;&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;-ObjectId&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;service-principal-object-id&amp;gt;&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;-DisplayName&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Ticketing&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;New-ManagementScope&lt;/span&gt; &lt;span class="n"&gt;-Name&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Ticketing-Mailboxes&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;-RecipientRestrictionFilter&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;CustomAttribute10 -eq &amp;#39;Ticketing&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;New-ManagementRoleAssignment&lt;/span&gt; &lt;span class="n"&gt;-App&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;service-principal-object-id&amp;gt;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;-Role&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Application Mail.Send&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;-CustomResourceScope&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Ticketing-Mailboxes&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Verify before you go live&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Test-ServicePrincipalAuthorization&lt;/span&gt; &lt;span class="n"&gt;-Identity&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;service-principal-object-id&amp;gt;&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;-Resource&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;servicedesk@contoso.com&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Note the irony: you configure Graph permissions with Exchange PowerShell. That&amp;rsquo;s exactly what the original post means by &amp;ldquo;use both&amp;rdquo;.&lt;/p&gt;
&lt;h2 id="module-conflicts-between-graph-pnp-and-exo"&gt;Module conflicts between Graph, PnP and EXO
&lt;/h2&gt;&lt;p&gt;Say you write a perfectly reasonable script: Graph for user data, PnP for SharePoint, EXO for mailboxes. It works on your machine. Then it fails in the next session with something like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Could not load type &amp;#39;Microsoft.Identity.Client.BaseAbstractApplicationBuilder`1&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from assembly &amp;#39;Microsoft.Identity.Client, Version=4.50.0.0&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;or&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Method not found: &amp;#39;!0 Microsoft.Identity.Client.BaseAbstractApplicationBuilder`1.WithLogging(...)&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="why-it-happens"&gt;Why it happens
&lt;/h3&gt;&lt;p&gt;Every one of these modules is a binary module that ships its own copies of shared .NET libraries – most notably &lt;strong&gt;MSAL&lt;/strong&gt; (&lt;code&gt;Microsoft.Identity.Client.dll&lt;/code&gt;), but also &lt;code&gt;Azure.Core&lt;/code&gt;, &lt;code&gt;Azure.Identity&lt;/code&gt;, &lt;code&gt;Microsoft.Graph.Core&lt;/code&gt; or &lt;code&gt;System.Text.Json&lt;/code&gt;. PowerShell loads assemblies into one shared context per process, and &lt;strong&gt;only one version of an assembly with a given name can be loaded there&lt;/strong&gt;. Whichever module loads it first wins; the other module then runs against a version it was never built for.&lt;/p&gt;
&lt;p&gt;Microsoft&amp;rsquo;s own PowerShell documentation describes exactly this: the outcome depends on which module was loaded first, which code path ran, and whether the dependency is loaded at import or only on first use. That&amp;rsquo;s why the same script works, fails, and works again depending on what you did earlier in the session.&lt;/p&gt;
&lt;p&gt;Known combinations that have caused trouble:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;PnP.PowerShell + Microsoft.Graph&lt;/strong&gt;: older PnP builds bundled an outdated &lt;code&gt;Microsoft.Graph.Core&lt;/code&gt; (1.25.x) and older MSAL versions, which broke &lt;code&gt;Connect-MgGraph&lt;/code&gt; and &lt;code&gt;Invoke-MgGraphRequest&lt;/code&gt; once PnP was loaded.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ExchangeOnlineManagement + Microsoft.Graph&lt;/strong&gt;: a long-running story. EXO 3.5.1 introduced a &lt;code&gt;System.Text.Json&lt;/code&gt; clash; in June 2026 Tony Redmond reported that with Graph SDK 2.38 and EXO 3.10, &lt;em&gt;neither&lt;/em&gt; connection order worked reliably in PowerShell 7: one order fails with the &lt;code&gt;Method not found&lt;/code&gt; error above, the other with a &lt;code&gt;NullReferenceException&lt;/code&gt; while acquiring a token.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Az.Accounts + Microsoft.Graph&lt;/strong&gt;: same pattern with &lt;code&gt;Azure.Core&lt;/code&gt; / &lt;code&gt;Azure.Identity&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="how-to-recognise-it"&gt;How to recognise it
&lt;/h3&gt;&lt;p&gt;First check: what is actually loaded in the current session?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Which version of the usual suspects is loaded in this session – and from which module folder?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$suspects&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Microsoft.Identity.Client&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Microsoft.Graph.Core&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Azure.Core&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Azure.Identity&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;System.Text.Json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;System.AppDomain&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;CurrentDomain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;GetAssemblies&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Where-Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="py"&gt;Name&lt;/span&gt; &lt;span class="n"&gt;-in&lt;/span&gt; &lt;span class="nv"&gt;$suspects&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Select-Object&lt;/span&gt; &lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Assembly&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="py"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Version&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="py"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Location&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If &lt;code&gt;Location&lt;/code&gt; points into the PnP folder while you&amp;rsquo;re calling &lt;code&gt;Connect-MgGraph&lt;/code&gt;, you&amp;rsquo;ve found your culprit.&lt;/p&gt;
&lt;p&gt;Second check: which versions do your installed modules ship? This inventory makes conflicts visible &lt;em&gt;before&lt;/em&gt; they hit production:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$modules&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Microsoft.Graph.Authentication&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;PnP.PowerShell&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ExchangeOnlineManagement&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Az.Accounts&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;MicrosoftTeams&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$dlls&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Microsoft.Identity.Client.dll&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Microsoft.Graph.Core.dll&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Azure.Core.dll&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Azure.Identity.dll&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Get-Module&lt;/span&gt; &lt;span class="n"&gt;-ListAvailable&lt;/span&gt; &lt;span class="n"&gt;-Name&lt;/span&gt; &lt;span class="nv"&gt;$modules&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;ForEach-Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$module&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Get-ChildItem&lt;/span&gt; &lt;span class="n"&gt;-Path&lt;/span&gt; &lt;span class="nv"&gt;$module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ModuleBase&lt;/span&gt; &lt;span class="n"&gt;-Recurse&lt;/span&gt; &lt;span class="n"&gt;-Include&lt;/span&gt; &lt;span class="nv"&gt;$dlls&lt;/span&gt; &lt;span class="o"&gt;-File&lt;/span&gt; &lt;span class="n"&gt;-ErrorAction&lt;/span&gt; &lt;span class="n"&gt;SilentlyContinue&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;ForEach-Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;pscustomobject&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Assembly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;BaseName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;System.Reflection.AssemblyName&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;GetAssemblyName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="py"&gt;Version&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;FullName&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Sort-Object&lt;/span&gt; &lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Version&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Format-Table&lt;/span&gt; &lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Module&lt;/span&gt; &lt;span class="n"&gt;-AutoSize&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Some modules ship separate builds for .NET Framework and .NET, so you may see two entries per module. What matters is when the &lt;em&gt;same&lt;/em&gt; assembly shows up with different versions across modules.&lt;/p&gt;
&lt;h3 id="how-to-solve-it"&gt;How to solve it
&lt;/h3&gt;&lt;p&gt;In order of preference:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Don&amp;rsquo;t load what you don&amp;rsquo;t need.&lt;/strong&gt; If PnP.PowerShell is already connected, you often don&amp;rsquo;t need the Graph SDK at all. &lt;code&gt;Invoke-PnPGraphMethod&lt;/code&gt; calls Graph with PnP&amp;rsquo;s connection (provided your PnP app registration has the required Graph permissions). And if you do need the SDK, install &lt;code&gt;Microsoft.Graph.Authentication&lt;/code&gt; plus the one or two submodules you use (or just &lt;code&gt;Invoke-MgGraphRequest&lt;/code&gt;) instead of the full &lt;code&gt;Microsoft.Graph&lt;/code&gt; meta-module.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Isolate per process.&lt;/strong&gt; Assemblies are per process, so separate processes can&amp;rsquo;t conflict. In PowerShell 7, &lt;code&gt;Start-Job&lt;/code&gt; runs in a child process:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Graph work in its own process – app-only auth with a certificate&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Required application permission: User.Read.All&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$auth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;ClientId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;app-id&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;TenantId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;contoso.onmicrosoft.com&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;Thumbprint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;lt;cert-thumbprint&amp;gt;&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$users&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Start-Job&lt;/span&gt; &lt;span class="n"&gt;-ArgumentList&lt;/span&gt; &lt;span class="nv"&gt;$auth&lt;/span&gt; &lt;span class="n"&gt;-ScriptBlock&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Connect-MgGraph&lt;/span&gt; &lt;span class="n"&gt;-ClientId&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ClientId&lt;/span&gt; &lt;span class="n"&gt;-TenantId&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;TenantId&lt;/span&gt; &lt;span class="n"&gt;-CertificateThumbprint&lt;/span&gt; &lt;span class="nv"&gt;$a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Thumbprint&lt;/span&gt; &lt;span class="n"&gt;-NoWelcome&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Get-MgUser&lt;/span&gt; &lt;span class="n"&gt;-Filter&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;accountEnabled eq true&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;-All&lt;/span&gt; &lt;span class="n"&gt;-Property&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userPrincipalName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;department&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Select-Object&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UserPrincipalName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Department&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Receive-Job&lt;/span&gt; &lt;span class="n"&gt;-Wait&lt;/span&gt; &lt;span class="n"&gt;-AutoRemoveJob&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# Main session: PnP only – Graph&amp;#39;s assemblies were never loaded here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Connect-PnPOnline&lt;/span&gt; &lt;span class="n"&gt;-Url&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;https://contoso.sharepoint.com/sites/hr&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;-ClientId&lt;/span&gt; &lt;span class="nv"&gt;$auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ClientId&lt;/span&gt; &lt;span class="n"&gt;-Tenant&lt;/span&gt; &lt;span class="nv"&gt;$auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;TenantId&lt;/span&gt; &lt;span class="n"&gt;-Thumbprint&lt;/span&gt; &lt;span class="nv"&gt;$auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Thumbprint&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The job returns deserialised objects (properties yes, methods no), which is exactly what you want for passing data between steps. Important: &lt;strong&gt;&lt;code&gt;Start-ThreadJob&lt;/code&gt; and &lt;code&gt;ForEach-Object -Parallel&lt;/code&gt; do &lt;em&gt;not&lt;/em&gt; isolate&lt;/strong&gt;. They run in the same process and share the loaded assemblies.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Split runbooks and pipelines.&lt;/strong&gt; In Azure Automation, use separate runtime environments (PowerShell 7.4) per module set rather than one &amp;ldquo;everything&amp;rdquo; environment. In CI/CD, one job per workload. This also gives you cleaner permissions per identity, which helps with least privilege.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Pin versions deliberately.&lt;/strong&gt; &lt;code&gt;#Requires -Modules @{ ModuleName = 'ExchangeOnlineManagement'; RequiredVersion = '&amp;lt;tested-version&amp;gt;' }&lt;/code&gt; at the top of a script turns &amp;ldquo;it broke after an update&amp;rdquo; into &amp;ldquo;it refused to start&amp;rdquo;, which is a much better failure mode. Update modules on purpose, after a smoke test that imports and connects every module combination you use.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. Last resort: connection order and DLL swapping.&lt;/strong&gt; Connecting in a particular order, or copying a newer &lt;code&gt;Microsoft.Identity.Client.dll&lt;/code&gt; into another module&amp;rsquo;s folder, is circulated widely in the community. It can get you through a day, but it&amp;rsquo;s unsupported, it&amp;rsquo;s overwritten by the next &lt;code&gt;Update-Module&lt;/code&gt;, and, as the 2026 EXO/Graph case shows, it stops working without warning. I wouldn&amp;rsquo;t build production automation on it.&lt;/p&gt;
&lt;h2 id="other-pitfalls"&gt;Other pitfalls
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Windows PowerShell 5.1 and PowerShell 7 behave differently. Assembly loading differs between .NET Framework and .NET, so a combination that fails in 7 can work in 5.1 and vice versa. PnP.PowerShell 3.x requires PowerShell 7.4 or later anyway, so &amp;ldquo;just use 5.1&amp;rdquo; isn&amp;rsquo;t an option for SharePoint.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-DisableWAM&lt;/code&gt; is not a fix. Since EXO 3.7.0, Web Account Manager is the default broker for interactive sign-in. Disabling it with &lt;code&gt;Connect-ExchangeOnline -DisableWAM&lt;/code&gt; sometimes sidesteps conflicts, but Microsoft explicitly describes it as a temporary measure.&lt;/li&gt;
&lt;li&gt;App-only beats interactive for automation. Certificate-based auth avoids most WAM/broker issues and is what scheduled automation should use anyway.&lt;/li&gt;
&lt;li&gt;Permissions add up. With RBAC for Applications, Entra consent and Exchange role assignments are additive. A tenant-wide &lt;code&gt;Mail.Send&lt;/code&gt; consent in Entra ID silently defeats your scoped assignment.&lt;/li&gt;
&lt;li&gt;The Exchange Online Admin API is &lt;strong&gt;preview&lt;/strong&gt; and deliberately narrow. It complements EXO PowerShell; it doesn&amp;rsquo;t replace it.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="wrap-up"&gt;Wrap-up
&lt;/h2&gt;&lt;p&gt;Admin modules give you the depth of each workload; Graph gives applications a single, auditable way in, which makes it the natural home for every mailbox integration. When you combine modules, treat them like components with dependencies: load less, isolate per process, pin versions and test updates before your runbooks do it for you.&lt;/p&gt;
&lt;h2 id="references"&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/powershell/scripting/dev-cross-plat/resolving-dependency-conflicts" target="_blank" rel="noopener"
 &gt;Resolving PowerShell module assembly dependency conflicts – Microsoft Learn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/powershell/microsoftgraph/troubleshooting" target="_blank" rel="noopener"
 &gt;Troubleshooting common errors in Microsoft Graph PowerShell – Microsoft Learn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/graph/api/user-sendmail" target="_blank" rel="noopener"
 &gt;user: sendMail – Microsoft Graph v1.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/exchange/permissions-exo/application-rbac" target="_blank" rel="noopener"
 &gt;Role Based Access Control for Applications in Exchange Online – Microsoft Learn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/exchange/reference/admin-api-overview" target="_blank" rel="noopener"
 &gt;Overview of the Exchange Online Admin API (preview) – Microsoft Learn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/troubleshoot/exchange/administration/wam-integration-issues" target="_blank" rel="noopener"
 &gt;Resolve issues in the Exchange Online PowerShell module after WAM integration – Microsoft Learn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://pnp.github.io/powershell/articles/installation.html" target="_blank" rel="noopener"
 &gt;PnP PowerShell installation – PnP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://office365itpros.com/2026/06/22/powershell-woes-and-cmdlets/" target="_blank" rel="noopener"
 &gt;The Grief and Joys of New PowerShell Releases – Office 365 for IT Pros (Tony Redmond)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://blog-en.topedia.com/2024/04/fix-conflicts-between-pnppowershell-and-microsoftgraphauthentication-module/" target="_blank" rel="noopener"
 &gt;Fix conflicts between PnP.PowerShell and Microsoft.Graph.Authentication – topedia&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Inspired by a LinkedIn post by &lt;a class="link" href="https://www.linkedin.com/posts/anthony-samuel-m365-iam_powershell-vs-microsoft-graph-which-share-7514768232751243264-hjWG" target="_blank" rel="noopener"
 &gt;Anthony Samuel&lt;/a&gt;.&lt;/p&gt;</description></item></channel></rss>