12.1 Configuring Cloud Flow Actions
Key Takeaways
- Dynamic content tokens are just workflow definition language expressions underneath — Peek code on any action reveals the real @{...} syntax.
- coalesce() returns the first non-null value in its argument list and is the standard guard for nullable Dataverse columns.
- A variable must be created with Initialize variable at the top level of the flow before any Set, Increment, or Append action can use it.
- Select reshapes every item in an array while Filter array keeps items intact and only reduces the count — the exam swaps these two constantly.
- List rows OData filters use lowercase logical column names and single-quoted strings, for example statecode eq 0 and revenue gt 100000.
Every cloud flow is, at its core, a trigger followed by a chain of actions. On the AB-410 exam you are expected to know not just what each action does, but how data moves between actions — which means mastering the difference between dynamic content and expressions, knowing the built-in data operation actions cold, and being precise about what each Microsoft Dataverse connector action can and cannot do.
Dynamic content vs expressions
Dynamic content is the picker panel in make.powerautomate.com that lists outputs from previous steps — for example, Subject from When a new email arrives or Account Name from a Dataverse trigger. Dynamic content is convenient, but it can only point at an existing value. When you need to transform, combine, or compute a value, you write an expression using the workflow definition language (WDL), the same function syntax that underlies Azure Logic Apps. Every dynamic content token you pick is really just a WDL expression under the hood; select Peek code on any action to see the raw @variables('name') or @{triggerOutputs()?['body/subject']} syntax.
Functions you must recognize on sight:
| Function | Purpose | Example |
|---|---|---|
concat() | Join two or more strings | concat('INV-', variables('Number')) |
utcNow() | Current date and time in UTC | utcNow() returns 2026-07-18T20:49:37Z |
addDays() | Add (or subtract) days from a timestamp | addDays(utcNow(), 30) |
formatDateTime() | Format a timestamp with a pattern | formatDateTime(utcNow(), 'yyyy-MM-dd') |
coalesce() | Return the first non-null argument | coalesce(triggerOutputs()?['body/nickname'], 'No nickname') |
json() | Parse a string into a JSON object | json(variables('rawText')) |
length() | Count array items or string characters | length(outputs('List_rows')?['body/value']) |
Exam trap:
coalesce()is the standard answer whenever a scenario mentions a column that may be null or may not exist. A plain dynamic-content reference to a missing value causes null-propagation failures downstream;coalesce()supplies the fallback.
Variables
A variable must be created with Initialize variable before it can be used, and initialization can only happen at the top level of a flow — never inside a Condition, Switch, or loop. Supported types are Boolean, Integer, Float, String, Object, and Array. After initialization you mutate it with:
- Set variable — overwrite the value entirely
- Increment variable / Decrement variable — add or subtract a number (Integer and Float only)
- Append to array variable / Append to string variable — grow a collection or string, typically inside a loop
Variables are scoped to a single flow run; they are never shared across runs or across flows.
Data operations
The Data Operation connector is a set of code-free reshaping actions:
| Action | What it does |
|---|---|
| Compose | Holds any input — a value, expression, or object; often used as a scratch pad to inspect expression output |
| Select | Projects an array into a new array with a different shape, including renamed keys, using map mode |
| Filter array | Returns the subset of an array matching a basic condition or an advanced @ expression |
| Parse JSON | Converts a JSON payload into typed dynamic content; requires a schema — select Generate from sample and paste a sample payload |
| Create CSV table | Renders an array as CSV text, ready to save as a file |
| Create HTML table | Renders an array as an HTML table, ideal for email bodies |
| Join | Flattens an array into one string with a delimiter, such as comma-separated email addresses |
Exam trap: Select changes the shape of every item; Filter array changes the count of items but keeps each item intact. Questions love to swap these two.
Dataverse actions
The Microsoft Dataverse connector exposes the core row operations. Know the exact action names:
- Add a new row — creates a row in the chosen table and returns its ID.
- Update a row — updates an existing row; you must supply the Row ID (a GUID). You cannot update by email address or name — retrieve the GUID first.
- Get a row by ID — retrieves a single row by GUID, optionally narrowed with Select columns.
- List rows — retrieves many rows using Filter rows (an OData filter such as
statecode eq 0 and revenue gt 100000), Select columns, Sort by, Top count, Expand Query (pull columns from related tables through lookup navigation properties), plus pagination settings. - Relate rows / Unrelate rows — link or unlink two existing rows (commonly for many-to-many relationships) without touching their other columns.
- Perform a bound action — runs a Dataverse action scoped to one specific row, such as a custom close-or-escalate action.
- Perform an unbound action — runs a global Dataverse action that is not tied to any row.
Exam trap: OData filters require the table's logical (lowercase) column names and single quotes around string literals:
fullname eq 'Ada Lovelace'. Display names or double quotes produce an error.
Configure run after
Every action's Settings → Configure run after defines which predecessor outcomes allow it to execute: is successful (the default), has failed, is skipped, and has timed out. This is the mechanism behind error-handling branches and the try-catch pattern covered in the next section — an action configured to run only after has failed is, functionally, your catch block.
A flow must build a salutation from a Dataverse contact row, but the Nickname column is frequently empty. Which expression safely falls back to 'Friend' when the nickname is null?
You ran List rows against the Account table and now need a new array containing only each account's name and revenue, with the revenue key renamed to AnnualRevenue. Which action should you use?