# Add Cloud Flow

> >-

- **Type:** Skill
- **Install:** `agentstack add skill-microsoft-power-platform-skills-add-cloud-flow`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [microsoft](https://agentstack.voostack.com/s/microsoft)
- **Installs:** 0
- **Category:** [Developer Tools](https://agentstack.voostack.com/c/developer-tools)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [microsoft](https://github.com/microsoft)
- **Source:** https://github.com/microsoft/power-platform-skills/tree/main/plugins/power-pages/skills/add-cloud-flow
- **Website:** https://aka.ms/ppskills

## Install

```sh
agentstack add skill-microsoft-power-platform-skills-add-cloud-flow
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

> **Plugin check**: Run `node "${PLUGIN_ROOT}/scripts/check-version.js"` — if it outputs a message, show it to the user before proceeding.

# Add Cloud Flow

Connect one or more Power Automate cloud flows to a Power Pages code site, or wire already-registered flows into additional pages/components. For new flows this skill:
- Creates the `adx_cloudflowconsumer` metadata YAML in `.powerpages-site/cloud-flow-consumer/`
- Assigns web roles based on the flow's scenario and target audience
- Generates client-side TypeScript/JavaScript service code to trigger the flow with CSRF authentication

For already-registered flows, the skill skips metadata and role creation and goes straight to client-side integration — wiring the existing flow into new UI locations.

## Core Principles

- **Multiple flows in one run**: The user can add several flows at once. All flows are planned together and implemented together before asking for deployment.
- **Ask before acting**: Present a full HTML plan (all flows, roles, reasoning) before creating any files.
- **Web roles drive access**: Every flow must have at least one web role. Anonymous Users role is valid but must be confirmed.
- **Scenario determines roles**: Understand what each flow does and who triggers it before picking roles.
- **Use TaskCreate/TaskUpdate**: Track all phases upfront before starting any work.

> **Prerequisites:**
> - An existing Power Pages code site with `.powerpages-site` deployed
> - PAC CLI authenticated (`pac auth who` must succeed)
> - Azure CLI authenticated (`az login --allow-no-subscriptions` works whether or not your account has an Azure subscription — Dataverse and Power Platform tokens are AAD-scoped)

**Initial request:** $ARGUMENTS

---

## Workflow

1. **Verify Prerequisites** — Locate the project, confirm `.powerpages-site` exists, inventory web roles and existing flows
2. **List Available Flows** — Fetch flows from the Power Automate Flow RP API
3. **Select Flows & Understand Scenarios** — User picks one or more flows; determine scenario and audience for each
4. **Determine Web Roles** — Propose minimum roles per flow with reasoning
5. **Review Plan** — Render HTML plan for all flows; get user approval
6. **Create Metadata** — Write `.cloudflowconsumer.yml` for each flow; create missing web roles first
7. **Client-Side Integration** — Generate typed service code to call each flow from the frontend
8. **Verify & Summarize** — Validate all YAMLs, record skill usage, offer deployment

---

## Phase 1: Verify Prerequisites

**Goal**: Locate the Power Pages project and confirm all prerequisites are met

**Actions**:

1. Create todo list with all 8 phases (see [Progress Tracking](#progress-tracking) table)

### 1.1 Locate Project

Look for `powerpages.config.json` in the current directory or immediate subdirectories.

**If not found**: Tell the user to create a site first with `/create-site`.

### 1.2 Read Config

Read `powerpages.config.json` to get the `siteName` (used for display and plan rendering).

### 1.3 Check `.powerpages-site` Exists

Look for the `.powerpages-site` folder in the project root.

**If not found**:

> 🚦 **Gate (plan · add-cloud-flow:1.3.deploy-first):** `.powerpages-site` missing — cloud flow YAML lives inside it. Deploy first or stop.
>
> **Trigger:** Phase 1.3 found no `.powerpages-site` directory.
> **Why we ask:** Cloud flow YAML written to a non-existent path will never deploy.
> **Cancel leaves:** Nothing — no YAML files written.

Use `AskUserQuestion`:

| Question | Options |
|----------|---------|
| `.powerpages-site` is required to add cloud flows. Would you like to deploy the site now? | Yes, deploy now (Required), Cancel |

**If "Yes, deploy now"**: Invoke `/deploy-site` first, then continue to Phase 2.
**If "Cancel"**: Stop.

### 1.4 Read Existing Web Roles

Read all `.webrole.yml` files from `.powerpages-site/web-roles/` to inventory available roles. Note each role's `id`, `name`, `adx_anonymoususersrole`, and `adx_authenticatedusersrole`.

### 1.5 Check Existing Cloud Flows

Check `.powerpages-site/cloud-flow-consumer/` for existing `.cloudflowconsumer.yml` files. For each file, read:
- `processid` — the flow's `workflowEntityId`
- `name` — the flow's display name
- `adx_CloudFlowConsumer_adx_webrole` — assigned web role UUIDs

Store these as the **already-registered flows** list. These flows already have metadata and web roles configured but may need additional frontend integration on other pages or components.

### 1.6 Detect Frontend Framework

Read `package.json` to detect the framework (React, Vue, Angular, Astro). Note the framework and its conventions for Phase 7. See `${PLUGIN_ROOT}/references/framework-conventions.md` for the detection mapping.

**Output**: Project root, site name, framework, available web roles, already-registered flows (with processid, name, and web roles)

---

## Phase 2: List Available Flows

**Goal**: Fetch all Power Automate cloud flows that have a PowerPages trigger

**Actions**:

Run the list-cloud-flows script (reads environment from `pac auth who` internally):

```bash
node "${PLUGIN_ROOT}/skills/add-cloud-flow/scripts/list-cloud-flows.js"
```

This calls the **Power Automate Flow RP API** with the filter `properties/definitionSummary/triggers/any(t: t/kind eq 'powerpages')`. Results include:

| Field | Source | Used for |
|-------|--------|----------|
| `id` | `properties.workflowEntityId` | `processid` in YAML; URL in client-side API call |
| `flowRpName` | `flow.name` | Flow RP identifier |
| `displayName` | `properties.displayName` | Shown to user; written as `name` in YAML |
| `description` | `properties.description` | Shown to user |
| `state` | `properties.state` | Shown to user (Active/Draft) |

**Separate into two lists**:
- **Unregistered flows**: Flows whose `id` does NOT match any `processid` from Phase 1.5 — these need full setup (metadata + roles + client-side)
- **Already-registered flows**: Flows whose `id` matches a `processid` from Phase 1.5 — these already have metadata and roles but can be integrated into additional pages/components

**Handle errors**:
- Exit code 1 with auth message → prompt the user to run `az login --allow-no-subscriptions`
- Zero flows from API (no flows with a PowerPages trigger exist at all) → tell the user that no Power Automate flows with a PowerPages trigger were found in this environment. Guide them to create a flow first:

  > "No Power Automate cloud flows with a PowerPages trigger were found in this environment. To use this skill, you first need to create a flow in [Power Automate](https://make.powerautomate.com) with the **"When a Power Pages flow step is run"** trigger, then run this skill again to connect it to your site."

  **Stop the workflow** — do not continue to Phase 3.

- Zero unregistered flows but already-registered flows exist → do **not** stop. Continue to Phase 3 with only the already-registered flows available (for additional frontend integration).

**Output**: List of unregistered flows and list of already-registered flows

---

## Phase 3: Select Flows & Understand Scenarios

**Goal**: Understand the user's intent, suggest the most relevant flows (including already-registered ones for additional integration), let the user confirm or adjust, and determine the scenario for each selected flow

**Actions**:

### 3.1 Analyze User Intent & Suggest Flows

Before showing the full list, analyze the user's initial request (`$ARGUMENTS`) against **both** the unregistered flows and the already-registered flows. Match the user's described need to specific flows using display name, description, and scenario inference.

When matching intent, check already-registered flows first — the user may be asking to wire an existing flow into a new page or component, not register a new one.

- **If the user described a specific need** (e.g., "add automation for the contact form", "connect the email notification flow"): Identify flows whose name or description closely match the request and present them as **recommended** picks, explaining why each is a good match. Also show the remaining flows as additional options in case the suggestion is wrong.

  ```
  Based on your request, I recommend:
    ⭐ 1. Contact Form Submission — Sends an email when a contact form is submitted (Active)
         → Matches your request to add automation for the contact form

  Other available flows:
    2. Support Ticket Handler — Creates a case record from user input (Active)
    3. Newsletter Signup — Adds the user's email to a mailing list (Draft)
  ```

- **If the user's request is generic** (e.g., "add a cloud flow", "connect some flows"): Fall back to presenting the full list without recommendations.

  ```
  Available flows:
    1. Contact Form Submission — Sends an email when a contact form is submitted (Active)
    2. Support Ticket Handler — Creates a case record from user input (Active)
    3. Newsletter Signup — Adds the user's email to a mailing list (Draft)
  ```

Present both categories clearly when both exist:

```
New flows (not yet registered):
  1. Newsletter Signup — Adds the user's email to a mailing list (Active)

Already registered (available for additional frontend integration):
  2. Contact Form Submission — Already connected, can be wired into more pages
  3. Support Ticket Handler — Already connected, can be wired into more pages
```

> 🚦 **Gate (plan · add-cloud-flow:3.1.select-flows):** Multi-select over discovered + already-registered flows. Drives the rest of Phases 4–7.
>
> **Trigger:** Phase 2 list-cloud-flows returned at least one flow.
> **Why we ask:** Wrong flows get registered (new `.cloudflowconsumer.yml` files written) or wrong existing flows get re-wired into the frontend.
> **Cancel leaves:** Nothing — no YAML or client code written yet.

Use `AskUserQuestion`:

| Question | Options |
|----------|---------|
| Which flows would you like to add or integrate? You can select from both new and already-registered flows. | (list or multi-select of flow names, with recommended flows pre-highlighted if applicable) |

If more than 10 flows are available, ask the user to type names or numbers (comma-separated for multiple).

### 3.2 Tag Selected Flows

For each selected flow, tag it based on its source:

| Tag | Meaning | Phases to execute |
|-----|---------|-------------------|
| **`new`** | Unregistered flow — needs full setup | Phases 4 → 5 → 6 → 7 (metadata + roles + client-side) |
| **`integration-only`** | Already registered — metadata and roles exist | Skip to Phase 7 (client-side integration only) |

### 3.3 Determine Scenario Per Flow

For each selected flow, identify its scenario from the name and description:

| Scenario type | Examples | Who triggers it |
|--------------|----------|-----------------|
| **Form submission** | Contact form, feedback, survey | Authenticated or anonymous visitors |
| **User self-service** | Profile update, request, leave application | Authenticated users only |
| **Admin action** | Bulk processing, content approval, data export | Admins / specific roles only |
| **Background / system** | Scheduled sync, enrichment | Not triggered by portal users directly |

If a flow's scenario is unclear, use `AskUserQuestion` per flow:

| Question | Context |
|----------|---------|
| What does "[flow name]" do on your site? Who triggers it? | Needed for role assignment |

For **`integration-only`** flows, the scenario is still needed to guide where and how the flow is wired into the frontend (Phase 7).

### 3.4 Determine Client-Side Function Name Per Flow

For each flow, derive a camelCase function name for the client-side service:
- Strip special characters and connector words from the display name
- Example: "PowerPages -> Send an email notification (V3)" → `sendEmailNotification`
- Example: "Contact Form Submission" → `submitContactForm`

For **`integration-only`** flows, check whether a trigger function already exists in the codebase (from a previous run of this skill). If it does, reuse that function name — do not create a duplicate. Only create a new function if one doesn't exist yet.

**Output**: Selected flows list, each with tag (`new` or `integration-only`), scenario, target audience, and client-side function name

---

## Phase 4: Determine Web Roles

**Goal**: Propose the minimum set of web roles for each **`new`** flow based on its scenario

> **Skip for `integration-only` flows** — these already have web roles assigned in their `.cloudflowconsumer.yml`. Do not re-propose or modify roles for them.

**Actions**:

### 4.1 Analyze Role Requirements Per Flow (New Flows Only)

| Scenario | Recommended roles |
|----------|-------------------|
| Any visitor (including unauthenticated) | `Anonymous Users` (confirm — security implication) |
| Only logged-in users | `Authenticated Users` |
| Only specific groups | Custom role(s) matching the group |

**Do NOT assign all roles by default.** Use the minimum set per flow. Different flows in the same batch can have different role sets.

### 4.2 Match Against Existing Roles

For each proposed role across all flows, check whether it exists in `.powerpages-site/web-roles/`. Mark roles as **existing** or **proposed/new**.

### 4.3 Compose Per-Role Reasoning

For each role assigned to each flow, write one sentence explaining why:

- `Authenticated Users` on a profile form: "Only logged-in users can update their profile."
- `Anonymous Users` on a contact form: "Unauthenticated visitors must be able to submit a contact request."
- `Blog Authors` on an email flow: "Blog Authors are the primary actors who submit posts triggering this notification."

### 4.4 Flag Anonymous Roles

If any flow has `Anonymous Users` assigned, note this — the HTML plan renders a warning banner and the confirm step must explicitly surface it.

**Output**: Per-flow role sets with reasoning, list of roles that need creating

---

## Phase 5: Review Plan

**Goal**: Render the HTML plan for all flows and get user approval before writing any files

**Actions**:

### 5.1 Build Plan Data

Assemble the plan JSON (kept in memory — not written to disk). Include all selected flows in `CLOUD_FLOWS_DATA`, distinguishing `new` from `integration-only`:

```json
{
  "SITE_NAME": "",
  "PLAN_TITLE": "Cloud Flow Integration Plan",
  "SUMMARY": "",
  "WEB_ROLES_DATA": [
    {
      "id": "",
      "name": "",
      "desc": "",
      "builtin": false,
      "isNew": true,
      "isAnonymous": false,
      "color": "#0078d4"
    }
  ],
  "CLOUD_FLOWS_DATA": [
    {
      "flowId": "",
      "name": "",
      "displayName": "",
      "description": "",
      "state": "Active",
      "tag": "new | integration-only",
      "scenario": "",
      "rationale": "",
      "webRoles": [
        { "id": "", "reasoning": "" }
      ]
    }
  ],
  "RATIONALE_DATA": [
    { "icon": "⚡", "title": "", "desc": "" }
  ]
}
```

For **`integration-only`** flows, `webRoles` should reflect the existing roles from the `.cloudflowconsumer.yml` (read-only — not being changed). The `rationale` should describe where the flow will be additionally integrated (e.g., "Wiring existing Contact Form flow into the support page").

### 5.2 Render HTML Plan

```bash
node "${PLUGIN_ROOT}/scripts/render-cloudflow-plan.js" \
  --output "/docs/cloud-flow-plan.html" \
  --data-inline ''
```

The render script refuses to overwrite existing files. Before calling it, check if the default output path (`/docs/cloud-flow-plan.html`) already exists. If it does, choose a new descriptive filename based on context — e.g., `cloud-flow-plan-contact-form.html`, `cloud-flow-plan-apr-2026.html`. Pass the chosen name via `--output`.

Open the rendered file in the default browser (`open` on macOS, `start` on Windows, `xdg-open` on Linux).

### 5.3 Confirm with User

Give a brief CLI summary: number of flows, scenarios, role count, any anonymous-role warnings.

> 🚦 **Gate (plan · add-cloud-flow:5.3.plan-approval):** Final sign-off on the

…

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [microsoft](https://github.com/microsoft)
- **Source:** [microsoft/power-platform-skills](https://github.com/microsoft/power-platform-skills)
- **License:** MIT
- **Homepage:** https://aka.ms/ppskills

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-microsoft-power-platform-skills-add-cloud-flow
- Seller: https://agentstack.voostack.com/s/microsoft
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
