Flow Studio Blog

Codex Agent Builds Power Automate Flow for Distribution List Owners

Written by Catherine Han | Apr 28, 2026 9:17:02 AM

Can we fetch the owner of a distribution list in Power Automate? A question on the Power Platform community forum this week. The kind that sounds like it should be a one-step connector call, until you realise classic Exchange distribution lists do not show up cleanly through the standard Power Automate or Microsoft Graph paths.

So I handed it to my Codex agent in VS Code.

What follows is the field note the agent wrote about the build, lightly edited for length. Most of the work happened inside an Azure Automation runbook, and I am going to be honest: that is not my home turf. I am not going to pretend I read every PowerShell line it wrote. What I did do is:

1. create a test distribution list and assign myself and a test account as owners
2. grant the Entra role when prompted by the agent
3. check the finished flow run triggered by the agent, and confirm the JSON came back with both owners correctly resolved.

That is enough for me to say the solution is solid. Great work to the agent.

Though, this is not a no-permission maker workaround. It is an IT-approved pattern for cases where Power Automate needs Exchange Online PowerShell to get the data reliably.

Codex Agent: Field Note

[01] Triage

Forum input: fetch DL owners in Power Automate. Connector audit before writing any code:

Office 365 Outlook no ManagedBy action
Office 365 Groups M365 groups only
Microsoft Graph (HTTP) M365 + Entra groups; classic Exchange DLs not first-class
Exchange Online PowerShell Get-DistributionGroup returns ManagedBy

Decision:  For an automated Power Automate solution, Exchange Online PowerShell was the reliable path. Follow-up question: PowerShell does not run inline in a Power Automate action. Choice: Azure Automation runbook, called via the ARM connector. I also checked the native Power Automate paths before building: Office 365 Groups covers Microsoft 365 group scenarios, not classic Exchange distribution list ownership; its HTTP action is scoped around /groups; and the Office 365 Groups connector docs point distribution-list management back to Exchange admin surfaces. Microsoft Graph was useful for identity and permission plumbing, but the DL owner property I needed lives cleanly in Exchange Online PowerShell through Get-DistributionGroup / ManagedBy.

[02] Tooling I had

▌ Flow Studio MCP
list/get/update flows, run history, action-level inputs and outputs
 
▌ Temporary helper flows
  resource-group lookup, Automation Account discovery/provisioning/cleanup, generic Graph calls
▌ Azure CLI (az)
available enough to confirm account context, but token-bearing calls hung in this environment. I started there, then moved the operational work into Flow Studio MCP plus temporary helper flows.
▌ Microsoft Graph
Exchange.ManageAsApp grant on the EXO service principal, Entra role assignment
▌ VS Code workspace
runbook PowerShell source, flow JSON, deploy scripts, this field note

I accessed Power Automate via Flow Studio MCP, not the designer or the Azure portal during the build. Azure CLI was useful for confirming account context, but token-bearing calls hung in this environment, so the resource-side work moved into helper flows.

The helper flows were temporary agent infrastructure: one listed resource groups, one found Automation Accounts, one provisioned the Automation Account and runbook, one cleaned up the wrongly placed Automation Account, and one acted as a generic Microsoft Graph request runner for permission checks and app-role assignment. The final user-facing flow is the DL owner lookup; the helper flows were scaffolding.

[03] Architecture

HTTP request  ─▶  Power Automate flow
   ─▶  Azure Resource Manager connector
      ─▶  Azure Automation runbook (PowerShell 5.1)
         ─▶  Connect-ExchangeOnline -ManagedIdentity
            ─▶  Get-DistributionGroup + owner resolution
               ─▶  JSON back to caller

No stored username, password, or certificate secret in the flow.

Subscription b4db10ab-...-d12726870f73
Resource group rg-dl-owner-automation
Automation account dlownerautomation
Runbook Get-DistributionListOwners · PowerShell 5.1 · ExchangeOnlineManagement
Flow Get Distribution List Owners · Flow Studio Demo env · HTTP-triggered

Actions on the flow side: normalize the DL identity, compose the runbook + job ids, start the Automation job, poll, fetch status, fetch output, parse JSON, return.

Run 08584242581324959217439134163CU44 in the Power Automate designer. Left: Get Job Output action body returning ownerCount: 2. Right: the eight-action graph the agent built.

[04] Auth model

App-only, NOT delegated. Both halves required:

[a] Exchange.ManageAsApp application permission
    granted on: Office 365 Exchange Online service principal
[b] Entra directory role from Exchange's allow-list
    assigned: Exchange Recipient Administrator
    reason: smallest scope that worked

Exchange.ManageAsApp was granted through the Graph helper flow. The Exchange Recipient Administrator role was completed in the Entra portal by the user because my Graph call lacked sufficient directory-role privileges. First call:

▌ runbook output · status: error
The role assigned to application <app-id> isn't supported in this scenario. Please check online documentation for assigning correct Directory Roles to Azure AD Application for EXO App-Only Authentication.

Re-test at T+10min: status: success. Diagnosis: Exchange honours directory role assignments after a propagation delay. The Entra portal shows the assignment immediately; Exchange's authorisation cache catches up later. No code change. Microsoft's reference: Connect-ExchangeOnline managed identity.

[05] Where I went wrong

Initial deploy: Automation Account placed in a production-tagged resource group.

▌ user · in chat
You created them under wrong resources group that is meant for production.

Fix sequence:

$ az automation account delete \
    --resource-group <prod-rg> --name dlownerautomation
$ az group create --name rg-dl-owner-automation --location <region>
$ az automation account create \
    --resource-group rg-dl-owner-automation --name dlownerautomation

Lesson: when a human flags a resource group as production, that is a hard boundary. Confirm subscription + RG before any az ... create.

[06] Why action-level debugging mattered

Power Automate run status: Succeeded. Runbook output (inside the Get_Job_Output action body):

▌ action body · failure inside a 200
{
  "status": "error",
  "message": "The role assigned to application ... isn't supported in this scenario."
}

Top-level run status was misleading: the flow succeeded as a flow. The runbook returned a structured failure inside the response body. Tool I reached for:

tool: Flow Studio MCP get_live_flow_run_action_outputs
effect: read the action body without opening the Power Automate portal

After role propagation, same flow, no code change:

▌ action body · status: success
{
  "status": "success",
  "ownerCount": 2,
  "owners": [
    { "displayName": "Catherine Han",      "email": "catherine.han@flowstudio.app" },
    { "displayName": "FlowStudio Support", "email": "support@flowstudio.app"      }
  ]
}

Run id 08584242581324959217439134163CU44.

[07] Hardening backlog

☐ Surface runbook status: error as non-200 from the flow
☐ Replace fixed polling delay with timeout + backoff 
☐ Preflight check: Exchange.ManageAsApp + Entra role assignment
☐ Accept group object id in addition to SMTP address
☐ Test whether Global Reader or a custom Exchange RBAC setup is enough for this read-only query 

The hard part of this build was not writing PowerShell. It was crossing system boundaries: connector behaviour, Automation job lifecycle, managed identity service principals, app-only auth, role propagation, action-level diagnostics. Each boundary was inspectable, and that is what made the work tractable.

Catherine: What I actually validated

I created a test distribution list, TestDLOwner@flowstudio.app, and added myself plus our support account as owners. Then I checked the run history triggered by the agent of the finished flow, and checked the response: both owners came back, resolved with display name and email. That is the validation I am willing to put my name behind. Everything in between, the runbook script, the role plumbing, the JSON shape, was the agent's work and it stands on its own merits.

If you have the same forum question, the architecture above is the one I would copy: HTTP flow as the API surface, Azure Automation as the PowerShell boundary, managed identity for auth, Flow Studio MCP plus temporary helper flows as the agent’s operational surface. If you want your agent to inspect action-level inputs and outputs the way mine did, Flow Studio MCP is the tool. Starter plan is free.

What I'd love to hear: if you tried this pattern for a different Exchange Online query that Graph cannot answer cleanly, drop a note on the Flow Studio LinkedIn page. The Power Automate plus Azure Automation runbook combo has more headroom than most people give it credit for.

About Flow Studio MCP: Flow Studio MCP is a Model Context Protocol server that gives AI agents action-level visibility into Power Automate. It works with GitHub Copilot, Claude, Codex, and any MCP-compatible agent. Available on GitHub via the awesome-copilot list.

Related reading:

Catherine Han, Flow Studio