Creating a Power Automate Flow in Code
Tags: powerautomate, powerplatform, rpa, coding
Published: 2023-01-04 09:36:40

The biggest strength of Power Automate is it's user interface, based on the Logic App UI, but even more user friendly, it's why anyone can create amazing automations.

So why would anyone want to create a flow in code instead of with the UI, I have no idea, but I did anyway.

## How it Started

I first got interested in the code of a flow when I had to update 500 flows (they didn't have connection references so I didn't want to have to manually update every connection when deploying to a dedicated environment). 

Looking at the definition.json I was able to identify the connections of the flow. So I made a flow that read the definition, did a replace with connection reference, then updated the json. And now I I had 500 flows that now only need 3 connections on import, not 1500!

A few other occasions I find editing the definition beneficial, generally for find and replaces or validating complex expressions. But exporting, copying out of zip, updating, copying back and then importing, was far to cumbersome. And then I found this chrome extension [Power Automate Tools](https://chrome.google.com/webstore/detail/power-automate-tools/jccblbmcghkddifenlocnjfmeemjeacc/related)

---

## Edit Flow live in Code

When editing a flow, click the extensions button and it opens the definition to edit and save right in the browser.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/luwluzd9xpdido04zt1s.png)

Best of all, it has intellisense and even the same Validation check as the UI does:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yknrljq08qpi65rydmlr.png)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/15v3v8wggx6pxn1g4q0z.png)

So now I had the tool to properly edit/create in code. I would start a new flow in the UI and then flip to code, after looking at examples, and reading the schema [Microsoft.Logic/schemas](https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#) I was able to create working flows pretty quickly.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gzyskmqvzaitrf05tmez.png)

---

## Basics

The definition object is quite simple, with all actions/steps in a `actions` node (this is the same for container steps -steps that have actions/steps inside like Scopes and Conditionds).

The basic action structure is:

```
 "Name_of_Step": {
      "runAfter": {
        "name_of_previous_stepAction": [
          "when"
        ]
      },
      "metadata": {
        "operationMetadataId": "idNumber"
      },
      "type": "type",
      "inputs": "inputs from action/step"
    }

```

An example would be a compose, named Get_id, which runs after an excel list all rows action, and has an input which is the `utcNow()` expression:
 
```
"Get_Date": {
      "runAfter": {
        "List_rows_present_in_a_table": [
          "Succeeded"
        ]
      },
      "metadata": {
        "operationMetadataId": "df2acb42-3954-4b98-b8d9-g571120509"
      },
      "type": "Compose",
      "inputs": "@utcNow()"
    }
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s23s5wfcpdelk8t2ng0v.png)

Actions will have additional nodes in inputs, like `host`- connection info, `parameters`- inputs from user and `authentication` (generally always the same):

```
"authentication": {
          "value": "@json(decodeBase64(triggerOutputs().headers['X-MS-APIM-Tokens']))['$ConnectionKey']",
          "type": "Raw"
        }

```

Containers are very similar, but just have the `actions` node which contains all internal actions/steps.

---

## Definition Tips

A top tip I found was a useful website called [www.objgen.com](http://www.objgen.com/json), which converted simple text into json, helped speed up my workflow no end. It meant I had to have 2 windows open, and some copy and pasting, but definitely was quicker.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3mfl2xeg793wxayprbg9.png)

You can use the 'Peek Code' in the UI to see parts of the action/steps code.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tzjl35nh5xqd4oh72ofs.png)

Other interesting things I found out about the definition.json was

**Order**
The order of the steps/actions isn't related to order in the Json (the order is when the step was created). The `runAfter` key is what dictates the flow order, except within containers (steps that contain other steps like Scopes and Conditions). With these the first step within them is the flow order, as these steps don't have a `runAfter`(because in the flow they don't, they use the containers)

**Object Structure**
Within the steps the order of the keys doesn't matter, but with the UI generated the order isn't consistent 

e.g `runAfter`
- Standard Action: at beginning of object
- Condition: before else

Or `type`
- Standard Action: near beginning
- Scope: at the end

**Optional**
Not all keys are required, biggest example is `operationMetadataId`

```
"metadata": {
    "operationMetadataId": "e76eee77-177d-47ef-b5c2-973ba7c29615"
 },
```

This can be removed and has no impact (the `operationMetadataId` key was only added recently, some legacy exports won't have them).

---

## Results
So would I recommend creating flows in code, the answer is hell no. When I said I could make working flows, I neglected to say only basic ones. Why... well:

**Speed** of the UI (especially with the complexity and inconsistencies of all the steps/actions) is faster then code.  

**Populated inputs** (like listing SharePoint Sites), are auto populated by built in he api calls. 

**Selection of GUID's through dropdowns** (e.g selecting mailbox folder by name in Outlook actually selects folder GUID). Trying to track down these GUID's can be almost impossible, let alone in anyway quick.

**Expressions/Variable list**, having them to hand is so much easier than trying to remember them all.

**Order** having to key order in the `runAfter` is a lot harder then the natural order in a UI, it's so easy to get wrong but not see.

_But, and this is a big but, editing in code is incredibly useful. Where starting from scratch it is just to painful, but doing updates is really useful:_

**Updates** with find & replace are so much easier.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5cd2cb9y5bncgqpodr9r.png)

**Validating/Code Reviews** can be so much easier buy just finding keys, like checking all the `runAfter` keys are right or Get action have Pagination turned on.

**Editing huge/nested flows** is not fun in the UI. I've had flows so big or nested that the browser struggles when every step is opened up. Doing edits in the code will never hang your browser, and using the find allows you to jump straight to the step instead of searching.

---

I don't think I really expected to replace the UI with code, but I was surprised how useful I found it as a tool. Flipping between UI and the code review more often than I thought. Shout out to Kamil Rithaler, the developer of [Power Automate Tools](https://chrome.google.com/webstore/detail/power-automate-tools/jccblbmcghkddifenlocnjfmeemjeacc/related), it's a great tool which without it editing in code isn't practical, and it's free.

---

**Further Reading**

- [logic-apps-workflow-definition-language](https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-workflow-definition-language)
- [workflow-definition-language-functions-reference](https://learn.microsoft.com/en-us/azure/logic-apps/workflow-definition-language-functions-reference)