Learn how to schedule desktop flows using cloud flow recurrence triggers, pass runtime parameters like dates and codes at execution time, and write structured logs to SharePoint after every run — whether it succeeds or fails. This lesson takes you from manual desktop flow execution to fully automated, auditable RPA in a single build.

Picture this: your team has a reporting process that runs every morning at 7 AM. Someone has to log into a legacy ERP system, pull yesterday's transaction data, paste it into an Excel template, and email the results to three different managers. Right now, that someone is a human being — setting an alarm, sipping coffee before they're ready, and doing the exact same 23 steps they did yesterday and will do again tomorrow.
You've already built a desktop flow in Power Automate Desktop that handles those 23 steps flawlessly. But it only runs when you manually press "Run." That's better than doing it by hand, but it's not automation — it's delegation to a slightly faster version of yourself. True automation means the process runs on a schedule, without anyone touching it, and leaves a clear audit trail so you can prove it worked (or diagnose why it didn't).
By the end of this lesson, you'll be able to wire a cloud flow to a recurrence trigger, have that cloud flow call your desktop flow at a scheduled time while passing in runtime parameters (like the target date or report type), and write the results of every run to a SharePoint list so you have a permanent, queryable log.
What you'll learn:
Before diving in, you should be comfortable with the basics of Power Automate Desktop. If you haven't built and tested a desktop flow yet, work through Getting Started with Power Automate Desktop: Installing, Recording, and Running Your First Desktop Flow first.
You should also understand how cloud flows invoke desktop flows. The mechanics of that connection — how inputs travel from cloud to desktop and outputs travel back — are covered in detail in Triggering Desktop Flows from Cloud Flows: Passing Inputs and Returning Outputs. Read that article if you haven't already, because this lesson builds directly on top of it.
Finally, you'll need:
When you run a desktop flow manually from the Power Automate Desktop designer, the cloud layer isn't involved at all — you're just executing locally. The moment you want scheduling, logging, or orchestration, you need a cloud flow: a flow that lives in the Power Automate cloud service and can react to triggers, call connectors, and coordinate logic across services.
Think of the cloud flow as a conductor and the desktop flow as a musician. The conductor decides when to start, tells the musician what piece to play (the input parameters), listens for the result, and then writes a note in the performance log (SharePoint). The musician — your desktop flow — never needs to know what time it is or where the log lives. It just does its job with the instructions it was given.
This separation of concerns is the right design. Your desktop flow stays focused on UI automation. Your cloud flow handles scheduling, parameter injection, and result persistence. When something goes wrong, you know exactly which layer to investigate.
Key insight
Cloud flows and desktop flows are not the same thing and live in different execution environments. Cloud flows run in Microsoft's cloud infrastructure. Desktop flows run on a physical or virtual Windows machine. The connection between them goes through a machine registration that you configure in the Power Automate portal.
Before scheduling anything, your desktop flow needs to be built to receive parameters and return results. Let's use a concrete example: a flow that logs into a legacy inventory system, pulls the day's stock counts for a given warehouse code, and returns both the total item count and a status message.
Open your desktop flow in Power Automate Desktop. To create an input variable (a value the cloud flow will send at runtime), click the Variables panel on the right side of the designer, then click the plus icon and choose "Input/output." Fill in:
WarehouseCodeWH-001 (used when running locally for testing)Create a second variable for the report date:
ReportDateNow create output variables that your flow will populate before it finishes:
Variable name: TotalItemCount
Data type: Number
Input/Output: Output
Variable name: RunStatus
Data type: Text
Input/Output: Output
Inside your desktop flow logic, after extracting the inventory data, you'll assign values to these outputs. For example, after reading data from the legacy app, you might use a "Set variable" action to assign %RecordCount% to TotalItemCount and set RunStatus to "Success".
Understanding Variables, Lists, and Data Tables in Power Automate Desktop will help you manage more complex output scenarios — particularly when you need to return structured data rather than simple strings.
Warning
Variable names in desktop flows are case-sensitive and cannot contain spaces. Use PascalCase consistently (e.g., WarehouseCode, not warehouse_code or Warehouse Code). Mismatches between the variable name in the desktop flow and the name the cloud flow expects will cause silent failures.
Before building the cloud flow, set up the destination for your logs. A SharePoint list is ideal because it's queryable, visible to non-technical stakeholders, and integrates natively with Power Automate.
Go to your SharePoint site and create a new list called Automation Run Log. Beyond the default "Title" column, add these columns:
| Column Name | Type | Purpose |
|---|---|---|
| FlowName | Single line of text | Which automation ran |
| RunDate | Date and Time | When the run was triggered |
| WarehouseCode | Single line of text | Input parameter used |
| ReportDate | Single line of text | Input parameter used |
| TotalItemCount | Number | Output from the desktop flow |
| RunStatus | Single line of text | "Success", "Failed", or "Partial" |
| ErrorDetail | Multiple lines of text | Error message if run failed |
| DurationSeconds | Number | How long the run took |
You can name the Title column "RunID" or leave it as Title and populate it with a generated identifier like WH-001-20250115.
Tip
Keep your SharePoint log list simple at first. It's tempting to log every possible detail, but a clean, scannable list is more valuable than an overwhelming one. You can always add columns later. Start with status, inputs, outputs, and timestamps.
Now you're ready to build the orchestrating cloud flow. Navigate to make.powerautomate.com, click "Create" in the left navigation, and choose "Scheduled cloud flow."
Give your flow a descriptive name — something like Daily Inventory Bot - Warehouse Run. In the "Run this flow" section, configure:
Click "Create." You'll land in the cloud flow designer with a Recurrence trigger already placed.
Click on the Recurrence trigger to expand its settings. Switch the view to "Show advanced options." Here you'll find additional controls that most beginners miss:
Time zone: By default, recurrence runs in UTC. If your business is in Eastern Time and you want the flow to run at 7 AM Eastern, you must set the time zone explicitly. Set it to "(UTC-05:00) Eastern Time (US & Canada)" and set the "At these hours" field to 7. Leave "At these minutes" as 0.
Days of the week: If you only want weekday runs, change the "Frequency" to "Week" and set "On these days" to Monday, Tuesday, Wednesday, Thursday, Friday.
Warning
The time zone field in Recurrence only appears when you set frequency to "Week" or "Day" with advanced options visible. If you skip this and leave it on UTC, your 7 AM trigger will fire at midnight or 2 AM local time depending on your offset. Always double-check this setting before deploying.
After the Recurrence trigger, add an "Initialize variable" action. Name it RunStartTime and set its type to String. For the value, use the expression:
utcNow()
This captures when the run began. You'll use this later to calculate duration.
Add another "Initialize variable" action named ErrorDetail of type String, with an empty default value. This variable will be populated only if the desktop flow fails.
One of the most powerful aspects of this architecture is that the cloud flow can compute what parameters to send based on context — rather than hardcoding them.
For our inventory example, the ReportDate should be yesterday's date (we're pulling yesterday's transactions each morning). Add a "Compose" action and enter this expression:
formatDateTime(addDays(utcNow(), -1), 'yyyy-MM-dd')
This takes today's UTC date, subtracts one day, and formats it as 2025-01-14. Name this Compose action YesterdayDate. You'll reference its output as the ReportDate input to your desktop flow.
For WarehouseCode, you might hardcode it here, pull it from a SharePoint configuration list, or even loop through multiple warehouse codes (running the desktop flow once per warehouse). For now, let's set it as a hardcoded string WH-001 using another Compose action named TargetWarehouse.
Add a new action by clicking the plus sign below your Compose actions. Search for "desktop flows" and select "Run a flow built with Power Automate Desktop."
In the action configuration:
TargetWarehouse Compose action using dynamic content.YesterdayDate Compose action.When you save this action, Power Automate reads the input/output variable definitions from your desktop flow and presents them as named fields. This is why getting the variable definitions right in Step 1 matters so much — the cloud flow interface is driven entirely by what the desktop flow declares.
The "Run a flow built with Power Automate Desktop" action returns the output variables your desktop flow defined. After this action completes successfully, you can reference TotalItemCount and RunStatus directly in subsequent actions using the dynamic content panel.
But flows don't always succeed. Wrap the desktop flow action in a Scope block and configure error handling:
In the failure branch, add a "Set variable" action targeting ErrorDetail and populate it with the expression:
outputs('Run_a_flow_built_with_Power_Automate_Desktop')?['error']?['message']
This expression pulls the error message from the failed action's output. If the machine was unavailable, a selector broke, or the desktop flow threw an unhandled exception, that message lands in ErrorDetail.
Key insight
If you don't handle the error branch explicitly, a failed desktop flow run will cause the entire cloud flow to stop immediately — and you'll get no log entry in SharePoint at all. Always write to your log regardless of success or failure. A missing log entry is worse than a logged failure because you don't even know the run was attempted.
For robust error handling patterns inside the desktop flow itself, see Error Handling in Desktop Flows: On Block Error, Retry Policies, and Recovery Screenshots.
After both the success and failure branches, add a "Compose" action in the main path to calculate how long the run took:
div(
sub(
ticks(utcNow()),
ticks(variables('RunStartTime'))
),
10000000
)
This expression computes the difference in ticks (100-nanosecond intervals) between now and when you captured RunStartTime, then divides by 10,000,000 to get whole seconds. Name this Compose action DurationSeconds.
Now add the "Create item" action from the SharePoint connector. Configure it as follows:
concat(outputs('TargetWarehouse'), '-', outputs('YesterdayDate'))
This creates a readable run identifier like WH-001-2025-01-14.
Map the remaining fields using dynamic content:
Daily Inventory BotutcNow() or the triggerOutputs()?['body/timestamp'] expression to get the trigger's exact fire timeTargetWarehouse Compose outputYesterdayDate Compose outputTotalItemCount output from the desktop flow actionRunStatus output from the desktop flow action (or use "Failed" in the error branch)ErrorDetail variableDurationSeconds Compose outputTip
In your error branch, duplicate the "Create item" SharePoint action but hardcode RunStatus as "Failed" and set TotalItemCount to 0. This ensures you always get a log entry. You can use a condition gate after both branches merge to avoid writing two entries — set a RunStatus variable in each branch and write to SharePoint once at the end.
Don't wait until 7 AM tomorrow to find out if it works. Use the "Test" feature in the cloud flow designer.
Click the "Test" button in the top right corner of the flow editor. Choose "Manually" and click "Test." This fires the flow immediately, exactly as if the recurrence trigger had fired. Watch the run history in real time — each action shows green (success) or red (failure), and you can expand any action to see its inputs and outputs.
After a successful test, check your SharePoint list. You should see a new row with yesterday's date, the warehouse code, the item count, and a status of "Success."
If the desktop flow action shows "Connection failed" or "Machine unavailable," verify that your machine is registered, the Power Automate Desktop agent is running, and you're targeting the right machine group. Managing Machines and Machine Groups for Scalable Unattended Automation in Power Automate covers machine configuration in depth.
Build the following end-to-end automation using what you've learned:
Scenario: You have a desktop flow called DailyWebReport that navigates to an internal web portal, extracts a summary metric (say, the number of open support tickets), and sets an output variable TicketCount (Number) and ExtractStatus (Text — either "Success" or "NoData").
Your tasks:
TargetDate (Text) to the desktop flow to specify which date's data to pullMM/dd/yyyy (the format your portal expects) and pass it as TargetDateStretch goal: Add a condition after logging: if TicketCount is greater than 50, send an email notification to a manager using the Outlook connector.
The recurrence fires at the wrong time Almost always a time zone issue. Open the Recurrence trigger, click "Show advanced options," and verify the Time zone field is set explicitly. UTC is the default and catches many people off guard.
The desktop flow input fields don't appear in the cloud flow action This means the desktop flow either hasn't been saved/published, or the input variables weren't properly defined as Input type in the Variables panel. Re-open the desktop flow, verify each variable's Input/Output setting, save it, and then refresh the cloud flow action.
SharePoint "Create item" fails with a type mismatch
If you're mapping TotalItemCount (a number from the desktop flow) into a SharePoint Text column, the connector may fail or store it oddly. Match your SharePoint column types to your desktop flow output types. Number outputs go to Number columns, text outputs go to single-line text columns.
The flow succeeds but I see no log in SharePoint
Check whether the "Create item" action is inside a branch that only runs on success. If the desktop flow failed silently (e.g., returned a RunStatus of "Failed" without throwing an exception), and your cloud flow logic only logs on the success path, you'll miss entries. Always log unconditionally.
Duration shows a huge number
If you forgot to divide by 10,000,000 in the ticks calculation, you'll see a 9-digit number instead of seconds. Double-check your formula. Alternatively, use the simpler approach of storing utcNow() at the start, utcNow() at the end, and computing the difference with the dateDifference expression if your environment supports it.
Note
For large-scale deployments where you need to monitor many flows across many machines simultaneously, the built-in Power Automate run history is often insufficient. The SharePoint logging pattern you've built here is a stepping stone toward more sophisticated monitoring, which is covered in Monitoring and Troubleshooting Desktop Flow Runs at Scale.
You've built something genuinely useful in this lesson. Your desktop flow now runs on a schedule without human intervention, receives context-appropriate parameters computed at runtime, and writes a permanent, queryable audit trail to SharePoint whether it succeeds or fails. That's the core loop of production RPA: trigger, parameterize, execute, log.
The pattern you've learned here scales. Want to run the same flow against five warehouses? Add a loop before the desktop flow action and iterate through an array of warehouse codes, calling the desktop flow once per iteration. Want to pause the schedule during holidays? Add a SharePoint configuration list with a PauseAutomation flag and check it at the top of your cloud flow. Want to alert on failures? Add a condition after the SharePoint write and send a Teams message if RunStatus equals "Failed."
From here, consider exploring:
The foundation is solid. Now build on it.