<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Daniel Laskewitz — Blog</title>
        <link>https://laskewitz.io/</link>
        <description>Notes on Power Platform, Copilot Studio and building agents, from Daniel Laskewitz.</description>
        <lastBuildDate>Tue, 11 Aug 2026 07:52:01 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en-GB</language>
        <image>
            <title>Daniel Laskewitz — Blog</title>
            <url>https://laskewitz.io/images/logo-white.png</url>
            <link>https://laskewitz.io/</link>
        </image>
        <copyright>© 2026 Daniel Laskewitz</copyright>
        <atom:link href="https://laskewitz.io/feed.xml" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[A Microsoft Learn plugin for Copilot Cowork]]></title>
            <link>https://laskewitz.io/blog/posts/learn-for-cowork</link>
            <guid isPermaLink="false">https://laskewitz.io/blog/posts/learn-for-cowork</guid>
            <pubDate>Mon, 15 Jun 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[I needed a Cowork demo for CollabDays Netherlands that produced something real, so I built a plugin around the Microsoft Learn MCP server.]]></description>
            <content:encoded><![CDATA[<p>I gave <a href="/talks/cowork/">Copilot Cowork: Work Together with AI, Get Things Done</a> at
<a href="/events/">CollabDays Netherlands</a> on Saturday. Cowork isn't something you can
explain on a slide, so the demos carry the session. What I didn't want was another
demo where an agent tidies up a to-do list and everyone politely nods.</p>
<p>So I built <a href="https://github.com/Laskewitz/learn-for-cowork" target="_blank" rel="noreferrer">Microsoft Learn for Cowork</a>.</p>
<p>It's a plugin that points Cowork at the
<a href="https://learn.microsoft.com/en-us/training/support/mcp" target="_blank" rel="noreferrer">Microsoft Learn MCP server</a>,
which is the same knowledge service behind Ask Learn. It's remote, there's no
authentication, and it's free, which makes it about the easiest MCP server to demo
in front of a room on conference wifi.</p>
<p>On top of that I added two skills. One asks what you want a deck about and who it's
for, goes and reads the docs, and comes back with a PowerPoint that has speaker
notes and links to its sources. The other does the same research and writes a Word
one-pager instead.</p>
<p>The thing I care about is that both skills are written to search Learn several
times rather than once. One search gets you something that looks like an answer.
Several get you something you'd be willing to send to a colleague. It's a small
difference in the SKILL.md and a big difference in what comes out.</p>
<p>Watching that happen live, with links back to the real documentation in the output,
went over better than I expected. Nobody in the room had to take the agent's word
for anything, and that changes how people react to it.</p>
<p>The whole plugin is a manifest, two icons and two SKILL.md files zipped up. If you
have an MCP server you like, that's not a lot of work to copy.</p>
<p>Everything else from the session is on the <a href="/r/cowork/">resources page</a>.</p>
]]></content:encoded>
            <author>Daniel Laskewitz</author>
            <category>Copilot Cowork</category>
            <category>Plugins</category>
            <category>MCP</category>
        </item>
        <item>
            <title><![CDATA[The CoE dashboard, without the sync flows]]></title>
            <link>https://laskewitz.io/blog/posts/power-platform-control-hub</link>
            <guid isPermaLink="false">https://laskewitz.io/blog/posts/power-platform-control-hub</guid>
            <pubDate>Sat, 30 May 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[The Starter Kit dashboard is only as fresh as the last sync flow that didn't fail. So I rebuilt it as a Power Apps Code App that reads the tenant live.]]></description>
            <content:encoded><![CDATA[<p>Every tenant I've worked in that runs the
<a href="https://learn.microsoft.com/en-us/power-platform/guidance/coe/starter-kit" target="_blank" rel="noreferrer">CoE Starter Kit</a>
has the same story. Someone installed it, the sync flows ran for a while, then a flow
failed quietly and nobody noticed for two months. By the time you look at the dashboard
you're not sure whether you're looking at your tenant or a snapshot of it from last
quarter.</p>
<p>So I built <a href="https://github.com/Laskewitz/Power-Platform-Control-Hub" target="_blank" rel="noreferrer">Power Platform Control Hub</a>.</p>
<p>It's a <a href="https://learn.microsoft.com/en-us/power-apps/developer/code-apps/overview" target="_blank" rel="noreferrer">Power Apps Code App</a>
that reads from the
<a href="https://learn.microsoft.com/en-us/power-platform/admin/inventory-api" target="_blank" rel="noreferrer">Power Platform Inventory API</a>
and the admin connectors directly. Canvas apps, model-driven apps, cloud flows, agent
flows, code apps, Copilot Studio agents and environments, all of it live at the moment
you open the page. There is no solution to import, no Dataverse tables to populate and
no nightly sync to babysit. Authentication comes from the Power Apps host, so there's no
app registration and no MSAL configuration either.</p>
<figure><img src="https://laskewitz.io/images/posts/power-platform-control-hub/01-overview.png" alt="The Control Hub overview tab, with a metric card per resource type above a table of recently created resources." /><figcaption>One card per resource type, and whatever showed up in the tenant most recently.</figcaption></figure>
<h2 id="inventory-is-the-boring-half" tabindex="-1">Inventory is the boring half <a class="header-anchor" href="#inventory-is-the-boring-half" aria-label="Permalink to &quot;Inventory is the boring half&quot;">&ZeroWidthSpace;</a></h2>
<p>Listing resources is the part everyone expects. I wanted the part after that: click a
resource and get told something useful about it.</p>
<figure><img src="https://laskewitz.io/images/posts/power-platform-control-hub/02-resources.png" alt="The Resources tab showing a sortable, filterable table of every resource across all environments." /><figcaption>Every resource in the tenant in one sortable table. Every row opens a detail panel.</figcaption></figure>
<p>So every canvas app, flow and agent has a detail panel with a Best Practice Analysis
section. Flows get 26 checks: no error handling, HTTP actions without a timeout, nested
<code>Apply to each</code> loops, a <code>Do Until</code> with no meaningful iteration limit, Parse JSON
without a schema, an HTTP trigger with no Response action. Canvas apps get 11, mostly
around sharing and staleness. Copilot Studio agents get 13, including the ones that
matter for security: authentication set to None, access control open to anyone, group
membership access with no groups actually configured.</p>
<p>Those checks are the reason the thing exists. An inventory tells you what you have. The
analysis tells you what to do on Monday.</p>
<p>The flow panel also renders the full trigger and action tree, with conditions showing
their True and False branches side by side and loops and scopes as collapsible
containers. Once you can read a flow's shape without opening the designer, reviewing
someone else's flow stops being a chore.</p>
<figure><img src="https://laskewitz.io/images/posts/power-platform-control-hub/03-environments.png" alt="The Environments tab, a grid of environment cards showing type badge, managed indicator, region and resource count." /><figcaption>Type, region, managed state and resource count, before you click into anything.</figcaption></figure>
<h2 id="governance-you-can-edit-not-just-read" tabindex="-1">Governance you can edit, not just read <a class="header-anchor" href="#governance-you-can-edit-not-just-read" aria-label="Permalink to &quot;Governance you can edit, not just read&quot;">&ZeroWidthSpace;</a></h2>
<p>The other thing the Starter Kit dashboard never did for me was let me change anything.
Control Hub does DLP policies end to end: list them, create them through a two-stage
flow, open a detail page per policy. There's an Apply Best Practices action that
checks a policy against a set of advisory rules, HTTP to Blocked, SharePoint to
Confidential, and shows you what it proposes before anything is saved.</p>
<figure><img src="https://laskewitz.io/images/posts/power-platform-control-hub/04-tenant-policies.png" alt="The Tenant Policies tab listing DLP policies, billing policies and cross-tenant connection reports." /><figcaption>DLP policies, billing policies and cross-tenant connection reports, in one tab.</figcaption></figure>
<p>Environment groups, rule-based policies and rule sets are full CRUD. Environments can be
enabled, disabled, made managed, backed up, and moved in and out of groups from the
Actions menu. Quarantining an app, disabling a flow or adding yourself as an owner all
happen in place.</p>
<figure><img src="https://laskewitz.io/images/posts/power-platform-control-hub/07-recommendations.png" alt="The Recommendations tab showing advisor recommendations returned by the admin API." /><figcaption>What the admin API already thinks you should go and fix.</figcaption></figure>
<h2 id="why-a-code-app" tabindex="-1">Why a Code App <a class="header-anchor" href="#why-a-code-app" aria-label="Permalink to &quot;Why a Code App&quot;">&ZeroWidthSpace;</a></h2>
<p>Code Apps sit in a spot I like. It's a React and TypeScript app with Fluent UI v9, so I
get real components, real state and a real build, but it's still hosted by Power Apps
with Power Apps handling identity and connector authentication. I don't have to stand
up infrastructure to ship an admin tool to admins.</p>
<p>It also means the whole thing is a repository you can read, fork and change. If your
organisation's idea of a best practice differs from mine, the checks are a TypeScript
file, not a rule buried in a solution.</p>
<p>Because everything it does goes through a connector, it plays by the tenant's own rules.
It's subject to your
<a href="https://learn.microsoft.com/en-us/power-platform/admin/wp-data-loss-prevention" target="_blank" rel="noreferrer">DLP policies</a>
and your
<a href="https://learn.microsoft.com/en-us/power-platform/admin/advanced-connector-policies" target="_blank" rel="noreferrer">Advanced Connector Policies</a>
exactly like any other app. Block a connector it needs in the environment you put it in
and it stops working. That's the right outcome, not a bug. A tool for governing the
tenant shouldn't get to sit outside the tenant's governance.</p>
<p>Dark mode, keyboard navigation and a responsive layout are in there too. Not decoration.
People don't open admin tools they dread opening.</p>
<p>The repo is at
<a href="https://github.com/Laskewitz/Power-Platform-Control-Hub" target="_blank" rel="noreferrer">Laskewitz/Power-Platform-Control-Hub</a>.
Issues and pull requests are welcome, particularly around the analysis rules.</p>
]]></content:encoded>
            <author>Daniel Laskewitz</author>
            <category>Power Platform</category>
            <category>Governance</category>
            <category>Code Apps</category>
        </item>
    </channel>
</rss>