DEV Community

Cover image for Creating a Power Automate Flow in Code
david wyatt
david wyatt Subscriber

Posted on • Edited on

Creating a Power Automate Flow in Code

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


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.

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

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 I was able to create working flows pretty quickly.


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"
    }

Enter fullscreen mode Exit fullscreen mode

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()"
    }
Enter fullscreen mode Exit fullscreen mode

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"
        }

Enter fullscreen mode Exit fullscreen mode

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, 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.

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

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"
 },
Enter fullscreen mode Exit fullscreen mode

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.

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, it's a great tool which without it editing in code isn't practical, and it's free.


Further Reading

I made a follow on blog all about schema and Jason keys: Understanding the Power Automote Definition

Top comments (5)

Collapse
 
pwagma profile image
Pwagma

Hi! I use a similar workflow jumping from UI to code, also for powerapps.
I have a couple of templates and I use Claude to create main structure.
My problem is that to validate sintaxis I need to manually paste and correct typical errors. Sometimes fast sometimes is slow and I need to re-start.
Do you know any tool that we could connect to Claude to validate sintaxis for both power automate or powerapps? This would be very helpful
Thanks
Pablo

Ps: I agree, the extension works temperamentally, also helps jumping between old and new UI, false/true flag on url

Collapse
 
wyattdave profile image
david wyatt

Afraid I don't, though after my struggles with the extension I just released a Vs code extension that is a lot better marketplace.visualstudio.com/items...
There is a skill.md built in that you can reference in the GitHub repo that helps with expressions but not everything you need.

Collapse
 
pwagma profile image
Pwagma

Looks pretty cool!
Thank you for your work! I will try it on my next project and will let you know how it goes!
Thanks
Pablo

Collapse
 
uwe_wolfgangradu_e467586 profile image
Uwe Wolfgang Radu

Hi David! Is this extension still supposed to work? I tried it both in Edge and Chrome, and in both browsers it merely pops up the extension management menu when you click the extension in the browser toolbar. It sounds extremely useful to me right now and I would love to get it working.

Collapse
 
wyattdave profile image
david wyatt

It can be temperamental for me, but if I refresh the page still works
demo gif