Tag: Power Automate

  • How to Build Your First AI Agent in Copilot Studio

    How to Build Your First AI Agent in Copilot Studio

    Step by step diagram showing how to build an AI agent in Copilot Studio, from instructions to knowledge to tools to publishing

    Microsoft published a guide on how to build an AI agent aimed at anyone, and the framework is genuinely sound: define the job, give the agent knowledge, give it tools, test it, let it run. What the article does not give you is the clicks. So this is how to build an AI agent in Copilot Studio following that exact recipe, end to end. By the end you have a working internal FAQ agent that can also create a ticket, published to Teams. I built a variant of this internally last quarter, and the framework holds up. The gaps between the steps are where it gets interesting.

    Step 1: Define One Job Before You Build an AI Agent in Copilot Studio

    Microsoft’s guide says start with a clear purpose. In practice this means the Instructions field, and this is where most first builds go wrong. People write vibes: “You are a helpful assistant for IT questions.” That constrains nothing. Write scope enforcement instead:

    You answer questions about internal IT policies using only the attached knowledge sources. If the answer is not in the knowledge sources, say so and offer to create a support ticket. Do not answer questions about HR, payroll, or anything outside IT. Do not guess at policy details.

    Keep it under 500 tokens. I covered why in the business skills post: instruction sets that grow past a few hundred tokens start degrading reliability. One job. Tight boundaries. Explicit refusal behavior.

    Step 2: Attach a Knowledge Source the Agent Can Cite

    In the agent’s Knowledge section, add your SharePoint site. Use the site URL, not a document library deep link, and check that the files are PDF or Word. The indexer handles those well. It handles scanned images inside PDFs poorly, and you will not find out until the agent confidently answers from the two readable pages and ignores the rest.

    Turn on “Use general knowledge” only if you have a reason. For an internal policy agent, leave it off. Grounded-only answers with citations beat fluent answers with no source. If you are choosing between SharePoint and Dataverse here, I compared them in a separate post. For a first build, SharePoint is the shorter path. If you plan to give the agent its own identity and audit trail inside Dataverse, Entra Agent ID gives every Dataverse agent its own identity and is worth reading before you commit to the data layer.

    Step 3: Give It One Tool With a Power Automate Flow

    Microsoft’s guide calls this “giving the agent the ability to act.” Concretely: build a flow with the When an agent calls the flow trigger, add two text inputs (ticketTitle, ticketDescription), create the ticket row wherever your ticketing lives, and end with Respond to the agent returning the ticket number and status. Do not return a bare “success” flag. Return state the agent can reason about on the next turn. The Copilot Studio docs cover the wiring, but they undersell the description field.

    Then add the flow as a tool on the agent, and write the tool description as a retrieval hint, not documentation: Creates an IT support ticket when the user reports a problem that the knowledge sources cannot resolve. The orchestrator scores this against user input to decide when to call it. I went deep on this in How to Design Tool Definitions for Copilot Studio Agents. One tool for now. Resist adding more until the first one behaves.

    Step 4: Test in the Canvas With the Activity Map Open

    Open the test pane and turn on the activity map. Now test the way real users will actually talk, not the way you wish they would. Three categories: questions the knowledge sources answer, requests that should trigger the ticket flow, and deliberately bad inputs. “my thing is broken.” “can you help.” A question about payroll that should get refused.

    The activity map shows you which knowledge source or tool the orchestrator picked and why. When it picks wrong, the fix is almost always the tool description or the instructions, not the model. This is the step people consistently skip, and it is the one that decides whether the agent survives contact with real users. I wrote about why agents fail in production after passing testing, and clean test conversations are the whole story. Testers ask questions they already know the agent can answer. Real users do not.

    Step 5: Publish to Teams and Watch the First Week

    Publish, then add the Microsoft Teams channel. Start with “available to specific users” and pick a pilot group of ten people, not the whole org. Then read the transcripts in the Analytics section every day for the first week. Not the satisfaction score. The actual conversations. You will find phrasings you never tested, a refusal that fired too aggressively, and at least one question your knowledge source cannot answer that it obviously should. That first week of transcripts is worth more than any amount of pre-launch testing. If generative answers start overriding your scoped topics during this phase, the fix is covered in Stop Copilot Studio Generative Answers From Hijacking Your Topics.

    The Working Agent and the Pitfall That Breaks Most First Builds

    Final state: one agent, one scoped job, one SharePoint knowledge source, one flow that creates tickets, published to a Teams pilot group. Microsoft’s five-part recipe maps cleanly onto this. The guide is right that anyone can follow the framework.

    The pitfall: skipping step 4 because the happy path worked twice in the test canvas. In my experience the agents that embarrass their builders are never the ones that failed in testing. They are the ones that were never tested against inputs designed to break them. Budget as much time for hostile testing as for building. The building is the easy half.

    Frequently Asked Questions

    How do I build an AI agent in Copilot Studio for the first time?

    Start by writing a tight Instructions prompt that gives the agent one clear job and explicit boundaries, then attach a knowledge source like SharePoint, and connect a single Power Automate flow as a tool. Test it before publishing to a channel like Teams. Keeping the scope narrow on your first build makes it much easier to identify where things go wrong.

    What should I write in the Instructions field when creating a Copilot Studio agent?

    Instead of writing a vague description, define exactly what the agent can and cannot do, which sources it should use, and how it should respond when it does not know the answer. Keeping the instruction set under 500 tokens helps maintain reliability, as longer prompts can reduce consistency.

    When should I turn on general knowledge in Copilot Studio?

    Only enable general knowledge if your agent genuinely needs to draw on information beyond your attached sources. For internal use cases like a policy or FAQ agent, leaving it off produces more trustworthy answers because responses are grounded in your own documents and can be cited.

    Why does my Copilot Studio agent give incomplete answers from PDF files?

    The knowledge indexer in Copilot Studio handles standard PDF and Word files well but struggles with scanned images embedded inside PDFs. If your documents contain scanned pages rather than real text, the agent may only read the portions it can process and skip the rest without flagging it.

    Source: How to build an AI agent: A simple guide for anyone (Microsoft AI Blog).

  • How to Turn HTTP Actions Into a Power Automate Custom Connector

    How to Turn HTTP Actions Into a Power Automate Custom Connector

    I ran into this building something internally: twelve flows, all calling the same internal REST API through the HTTP action, all with the same API key pasted into a header field. The key rotated. Eleven flows broke overnight, and the twelfth broke a week later because nobody remembered it existed. The fix is a Power Automate custom connector. By the end of this walkthrough you will have one connector with connection-level authentication, typed outputs in the dynamic content picker, and zero secrets sitting in flow definitions.

    One thing up front so nobody is surprised: the HTTP action is premium and custom connectors are premium. You are not saving on licensing here. If you want to understand exactly what triggers premium licensing before you ship, How to Run a Power Platform Licensing Audit Before You Ship walks through flagging premium connectors and mapping user licenses. You are saving on secret sprawl, duplicated Parse JSON actions, and the maintenance cost of every flow knowing the raw URL.

    Step 1: Capture the working request

    Before you touch the connector wizard, get one successful call working in a plain HTTP action. You need four things written down: the method, the full URL, every header the API requires, and a real response body. Run the flow once and copy the raw JSON from the run history outputs. Save it somewhere. You will paste it into the connector definition in Step 4, and the quality of your dynamic content depends entirely on how representative this sample is. If a field can be null, make sure your sample shows it populated, or the schema inference will type it wrong.

    Step 2: Create the Power Automate custom connector

    Go to make.powerautomate.com, then Custom connectors under Data, then New custom connector. If you have an OpenAPI file or a Postman collection, import it and skip ahead. For an internal API you probably do not, so pick Create from blank. On the General tab set the scheme to HTTPS, the host to your API domain (api.internal.example.com, no protocol prefix), and the base URL to the shared path segment, for example /v2. Everything you put here is one edit away when the API moves. That is the whole point. The custom connector docs on Microsoft Learn cover the import paths if you go that route.

    Step 3: Move the key into connection-level security

    On the Security tab, choose API Key as the authentication type. Set the parameter label to something a human understands, the parameter name to the exact header the API expects (x-api-key in my case), and the location to Header. This is the step that pays for everything else. The key is now entered once per connection, stored encrypted, and never appears in the flow definition, the export package, or the run history. When the key rotates, you update the connection. Every flow using it picks up the change. Compare that to my eleven broken flows.

    If your API uses OAuth 2.0, the same tab handles it, but you will need an app registration and a redirect URL. API key is the fast path for internal services.

    Step 4: Define the action with Import from sample

    On the Definition tab, click New action. Give it a summary and an operation ID that reads like a verb, because that text is what shows up in the action picker. Then hit Import from sample, set the method and relative path (/invoices/search), and paste the request body you captured in Step 1. Do the same for the response: open the default response, paste your saved JSON, and let it infer the schema.

    This response schema is what kills the Parse JSON actions. Every field in your sample becomes a typed token in dynamic content. Instead of body('HTTP')?['data']?['invoiceNumber'] in a dozen flows, you get invoiceNumber as a pickable token. Untyped payloads always come back to bite you at the consumption end, and that same discipline around schema and parameter definitions applies when you are building tools for AI agents — How to Design Tool Definitions for Copilot Studio Agents covers exactly how typed outputs affect whether an agent selects and uses a tool correctly.

    Step 5: Test the connection and swap the flows

    Use the Test tab. Create a connection, enter the API key, fire the operation, and check the returned status code against what your plain HTTP action produced. Then go through your flows one by one: add the connector action, remap the inputs, repoint downstream references from the old body('HTTP') expressions to the new typed tokens, delete the HTTP action last. Do not delete first. You want the old expression text visible while you remap.

    Since connectors are solution-aware, put the connector inside a solution before you build against it if this ever needs to move environments. Retrofitting that later is painful — understanding how solution layers decide which customization wins makes it much clearer why getting the connector into a solution early avoids hard-to-debug conflicts later.

    The final state and the one pitfall

    End result: one connector, one connection per environment, secrets out of flow definitions, typed outputs everywhere, and a single place to edit when the API changes. The maintenance profile of those twelve flows went from twelve edits to one. In my experience this is the single highest-return refactor available in a flow estate that grew organically.

    The pitfall: custom connector requests have a hard timeout of 2 minutes. A plain HTTP action will happily wait longer with the right retry settings. If your API has a slow endpoint, a report generator, a bulk export, anything that can run past 120 seconds, keep that one call on the HTTP action or redesign it as an async polling pattern. I learned that one the hard way, staring at a 504 that the same request never produced from the raw action.

    Frequently Asked Questions

    What is a Power Automate custom connector and why would I use one?

    A Power Automate custom connector is a reusable wrapper around an external or internal API that lets you call it from flows without hardcoding URLs, headers, or secrets. It centralises authentication and request configuration in one place, so when something like an API key changes, you update it once rather than hunting through every flow that uses the raw HTTP action.

    How do I move an API key out of my flow definitions and into a secure location?

    In a custom connector, you can configure API Key authentication at the connection level on the Security tab. You specify the exact header name the API expects, and the key is entered once when creating a connection, stored encrypted, and never written into the flow definition itself.

    When should I replace HTTP actions in my flows with a custom connector?

    If you have multiple flows calling the same API, sharing the same headers or secrets, or duplicating Parse JSON actions to handle responses, a custom connector is worth building. It reduces secret sprawl, cuts down on repeated configuration, and makes maintenance much easier when API details change.

    How do I get typed outputs and dynamic content when building a custom connector?

    You need to provide a real response body sample from a successful API call, which the connector wizard uses to infer the response schema. The quality of the dynamic content picker depends on how representative that sample is, so make sure any fields that can contain values are populated in the sample rather than null.

  • Attended vs Unattended RPA for Power Automate Desktop Flows

    Attended vs Unattended RPA for Power Automate Desktop Flows

    Two computer setups side by side illustrating attended vs unattended RPA in Power Automate desktop flows

    You built the desktop flow. It works. Now comes the question that actually decides the economics of the whole project: does it run on a person’s machine while they watch, or on a dedicated machine at 3 AM with nobody around? That is the attended vs unattended RPA decision, and I keep seeing teams get it wrong in both directions. Some pay for unattended bots to run flows that need a human answer halfway through. Others burn an employee’s afternoon babysitting a flow that should have been scheduled on a VM.

    I have built both kinds. Here is how I compare them now, dimension by dimension.

    The Attended vs Unattended Cost Gap

    Attended RPA is included in the Power Automate Premium per-user licence, which sits around $15 per user per month. If a person is signed in and triggers the flow on their own machine, that licence covers it.

    Unattended is a different animal. The unattended process licence runs around $150 per bot per month, and if you want Microsoft to host the machine for you, the hosted process option lands around $215 per month. Want two flows running concurrently on the same machine? That is another unattended licence. This is the ten-times gap, and it is where How to Run a Power Platform Licensing Audit Before You Ship earns its keep. I have watched estimates double after someone finally read the concurrency rules.

    Machine and Session Requirements

    Attended flows need an active, unlocked Windows session. The user is signed in, the screen is visible, and the flow drives the UI in front of them. Lock the screen mid-run and the flow dies. That is not a bug. It is the definition of attended.

    Unattended flows create their own session on a machine where nobody is signed in. That means the machine must allow it: no other active session on that account, credentials stored in the connection, and on standard Windows 10 or 11 you get exactly one unattended run at a time per machine. Multiple parallel sessions need Windows Server or multiple machines in a machine group. The Microsoft Learn requirements for unattended runs are strict, and every requirement you skip becomes a 4 AM failure.

    Failure Modes

    Attended flows fail loudly and recover cheaply. The user is right there. A selector breaks, a popup appears, the flow stops, the human clicks past it and reruns. Annoying, but the blast radius is one person’s afternoon.

    Unattended flows fail silently and recover expensively. Nobody sees the unexpected dialog box. The run sits there until timeout, the queue backs up, and you find out from the downstream team the next morning. Everything covered in Selectors vs Image Recognition for Power Automate Desktop Flows matters three times more unattended, because there is no human to absorb the surprise. If you go unattended, you also need error handling, screenshots on failure, and alerting. Budget that build time. It is not optional.

    Human in the Loop

    Some processes genuinely need a person mid-flow. A judgment call, an approval, a value read off a paper document. Attended handles this naturally with input dialogs. Unattended cannot do it at all, and I have seen teams contort a process into ugly two-phase flows just to force it unattended. If a human decision sits in the middle of your process, that is your answer. Do not fight it.

    Throughput Ceiling

    This is where unattended wins without argument. An attended flow runs when a human is available, which means business hours, one run at a time, competing with the person’s actual job. An unattended machine group with three VMs runs around the clock and processes a queue in parallel. If your volume is hundreds of transactions a day, attended is not a real option no matter how cheap the licence looks. Concurrency also introduces its own gotchas inside the flows themselves — why variables break when you turn on concurrency in Power Automate is worth reading before you scale a machine group.

    At a Glance

    Dimension Attended Unattended
    Licence cost ~$15/user/month (Premium) ~$150/bot/month, ~$215 hosted
    Session User signed in, unlocked Bot creates its own session
    Failure recovery Human fixes it live Needs alerting and retry logic
    Mid-flow human input Native Not possible
    Throughput Business hours, serial 24/7, parallel with machine groups

    Choose Attended If, Choose Unattended If

    Choose attended if the process needs human judgment mid-run, if volume is low enough that a person triggering it is not a bottleneck, or if you are still stabilising the flow and want a human catching the surprises. It is also the honest choice for a pilot. Prove the flow works attended before paying unattended prices.

    Choose unattended if volume demands overnight or parallel runs, if the process is fully deterministic with no human decision anywhere, and if you have already invested in error handling and monitoring. And before either: check whether the target system has an API. As I have argued before, a lot of desktop flows should not exist at all. The best RPA licence is the one you never had to buy. More of my reasoning on these trade-offs is on my LinkedIn.

    Frequently Asked Questions

    What is the difference between attended vs unattended RPA in Power Automate Desktop?

    Attended RPA runs on a user’s machine while they are actively signed in, with the flow triggered by the person in front of it. Unattended RPA runs on a dedicated machine with no one present, typically on a schedule, creating its own session automatically. The key distinction is whether a human needs to be available during the run.

    How much does unattended RPA cost compared to attended in Power Automate?

    Attended automation is covered under the Power Automate Premium per-user licence at around $15 per user per month. Unattended requires a separate process licence at roughly $150 per bot per month, rising to around $215 if you use Microsoft-hosted machines. Running flows concurrently requires additional licences, which can cause costs to climb quickly.

    When should I use attended RPA instead of unattended for desktop flows?

    Use attended RPA when the process requires a human decision or input at some point during the run, or when the volume does not justify the higher licence cost. Unattended is better suited for high-volume, fully automated processes that can run overnight or in bulk without any human involvement.

    Why does my unattended desktop flow fail when no one is watching?

    Unattended flows can fail silently because there is no user present to handle unexpected popups, broken selectors, or login prompts. Unlike attended flows where a person can intervene immediately, unattended runs may sit idle until they time out, causing queues to back up before anyone notices the issue.

  • Why Do Variables Break When I Turn On Concurrency in Power Automate?

    Why Do Variables Break When I Turn On Concurrency in Power Automate?

    Diagram of parallel loop iterations writing to one shared variable, illustrating a Power Automate concurrency race condition

    Short answer: variables in Power Automate are scoped to the entire flow run, not to a single loop iteration. When you enable Power Automate concurrency on an Apply to each and use Set variable inside it, twenty iterations write to the same variable at the same time and stomp on each other’s values. Use Compose for per-iteration values, use Append to array variable for collecting results, and only fall back to sequential mode if you genuinely need Set variable.

    That is the whole answer. If you just shipped a flow that produces the right output for item 1 and garbage for items 2 through 40, that is almost certainly what happened. The rest of this post explains why, because the failure mode is nastier than it sounds.

    Why Power Automate concurrency causes this

    By default, Apply to each runs sequentially. One item at a time, in order. Flip on the concurrency control in the loop settings and it runs up to 50 iterations in parallel, with a default degree of 20. Microsoft documents this in the Apply to each reference, but the docs are quieter about what happens to your variables.

    Here is the problem. Set variable is a read and write against shared flow state. Iteration 3 sets the variable to its item’s value, and before it can use that value in the next action, iteration 7 has already overwritten it. Your Condition or your email body then reads whatever value happened to land last. Nothing throws an error. The flow run shows green checkmarks all the way down. You only find out when someone asks why customer A received customer B’s invoice.

    I burned an afternoon in this rabbit hole once with a flow that formatted a string per item and appended it to an email digest. Sequential test run with three items: perfect. Production run with 60 items and concurrency at 20: the same three names repeated in random order. No failed actions, no signal, nothing to catch. The debugging was miserable precisely because every individual action succeeded.

    The second thing concurrency takes away is ordering. Parallel iterations complete whenever they complete. If your logic assumes items are processed in the order they arrived, that assumption is gone the moment you move the slider.

    How to fix it

    The fix depends on what the variable was doing.

    If you were using Set variable to hold a per-item value, replace it with a Compose action. Compose outputs are scoped to the iteration that produced them, so parallel iterations cannot see each other’s outputs. This covers most cases, and it is faster too because Compose does not lock flow state the way variable actions do.

    If you were collecting results across iterations, use Append to array variable or Append to string variable. These operations are atomic, so they are safe under concurrency. What you give up is order: items land in the array in completion order, not source order. If order matters, append objects that carry an index and sort afterwards.

    If you were transforming every item into a new shape, ask whether you need a loop at all. A Select action maps an entire array in one operation, no loop, no concurrency, no race condition. Same for Filter array when you are only keeping some items. I reach for these first now and only use Apply to each when an action genuinely has to run per item.

    And if you truly cannot avoid Set variable inside the loop, set the concurrency degree back to 1. You lose the parallel speedup, but a slow correct flow beats a fast wrong one every time. That trade-off is not close.

    Related gotchas

    Two more things bite people once the variable problem is fixed. First, throttling. Twenty concurrent iterations means twenty simultaneous connector calls, and SharePoint and Dataverse will start returning 429s well before you expect. The built-in retry policy masks this until volume grows, which is a pattern I covered in my post on error handling patterns. If you see intermittent failures only on large runs, drop the concurrency degree before you touch anything else.

    Second, parallel branches are not the same feature and have their own trap. When two branches rejoin, the joining action runs only if its run-after conditions are met, and the default is that every preceding branch succeeded. One branch fails, the join silently skips, and the flow ends looking half green. Check the run-after settings on the first action after any join.

    Concurrency is genuinely useful. I have flows where it cut a 40-minute run to under 4. But the platform lets you drag and drop fast, and this is one of those places where you need to plan even faster. I have written more about these production failure modes on LinkedIn if you want the ongoing version.

    Frequently Asked Questions

    Why do variables break when I enable Power Automate concurrency in an Apply to each loop?

    Variables in Power Automate are shared across the entire flow run, not isolated to individual loop iterations. When concurrency is enabled, multiple iterations run at the same time and overwrite the same variable, causing unpredictable values to appear in your actions. No errors are thrown, so the problem can be hard to detect.

    How do I safely store per-item values inside a concurrent Apply to each loop?

    Replace Set variable with a Compose action, which keeps its output scoped to the iteration that created it. This means parallel iterations cannot overwrite each other’s values, and Compose is also faster because it does not lock shared flow state.

    Why does my Power Automate flow produce correct results in testing but wrong results in production?

    This often happens because test runs use a small number of items that process sequentially, while production runs have enough items to trigger parallel execution. Once concurrency kicks in, shared variables get overwritten across iterations and the output becomes unreliable.

    When should I turn off concurrency in Power Automate instead of refactoring my variables?

    Reverting to sequential mode is a reasonable option only if your logic genuinely depends on Set variable and refactoring is not practical. However, running iterations one at a time will be slower, so it should be a fallback rather than a first choice.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Why Do AI Agents Fail in Production When They Worked Fine in Testing?

    Why Do AI Agents Fail in Production When They Worked Fine in Testing?

    Why AI agents fail in production despite passing tests

    Short answer: AI agents fail in production because test conversations are too clean, tool descriptions are too vague, and nobody logs the decisions the agent actually makes. The agent looked fine in testing because you asked it the questions you already knew it could answer. Real users do not do that.

    This is the question I keep getting from people at other organisations who just deployed their first Copilot Studio agent or LangGraph build and watched it fall over in week one. So here is the longer version.

    The longer answer on why AI agents fail in production

    Three things go wrong, and they usually go wrong together.

    1. The input distribution shifts the moment real users show up. In testing you type “what is the status of order 12345”. In production someone types “hey can you check where my thing from last tuesday is at, i think it was for the warehouse team”. The orchestrator now has to route ambiguous phrasing across multiple topics or tools, and it picks one confidently and gets it wrong. I wrote about this specific failure mode in how Copilot Studio agent tool selection actually works under the hood. The planner is scoring, not dispatching. Noisy input equals noisy scores.

    2. Tools return status instead of state. A tool that returns {"result": "done"} gives the agent nothing to reason about on the next turn. When something goes sideways the agent cannot recover because it does not know what actually happened. I have hit this the hard way. The fix is boring: tools return the state the agent needs to make the next decision, not a success flag.

    3. Nobody logged the decisions. Run logs tell you the flow executed. They do not tell you why the agent picked tool A over tool B, or why it summarised the ticket that way. Without a decision log you are debugging blind. You end up guessing at prompts.

    There is also a fourth thing that gets ignored. Silent failure. A Power Automate action inside a Copilot Studio topic can fail and the agent will still generate a confident-sounding response for work that was never done. The user gets an answer. Nothing throws. You find out three weeks later when someone asks why the record was never created.

    How to fix it

    Start with the tool contracts. Every tool your agent can call needs a precise name, a description written as a retrieval hint rather than documentation, and parameters with concrete names. customerAccountNumber not id. If you are on Copilot Studio, the Microsoft Learn docs cover the schema but not the hint-writing style. That part you learn by breaking things.

    Then cap the tool count. Past roughly 10 to 15 tools on a single agent, selection quality degrades because the relevance signal gets noisy. Split the agent before you add another tool.

    Log the decision, not just the execution. For every turn: what did the user say, what tools did the orchestrator consider, what did it pick, what did the tool return, what did the agent do with that. Store it. Query it. This is the only way to improve the policy over time. I go deeper on this in the post on decision ownership.

    Add adversarial test cases. Not “does it work”. Test misspellings, mixed languages, requests that sit between two topics, requests that reference something from two turns ago, requests where the user gives incomplete information and expects the agent to ask. This is where production breaks. Test it before production does. If you want a structured way to think about adversarial evaluation, the red team methodology in Anthropic’s jailbreak safeguards framework for Fable transfers directly to internal agent testing.

    Fail loudly. If a tool call fails, the agent should know and say so, not paper over it. Wire actual error handling into every Power Automate step the agent can invoke. Return the error state to the orchestrator so it can decide what to do next.

    Related gotchas

    Two more worth flagging.

    Context window drift. Long conversations quietly push earlier turns out of context. The agent forgets what the user told it in turn one by turn twelve. If your use case has long sessions, either summarise state into a persistent variable or split the interaction. I have written more about when a conversational interface is even the right choice in Copilot Studio is not always the answer.

    Model updates. The underlying model gets updated. Your prompts that worked last month behave differently this month. This is not theoretical. Anthropic and OpenAI both ship model updates that shift behaviour on edge cases. The Anthropic Fable 5 redeploy postmortem is a useful template for understanding how regressions surface and what a proper rollback and recovery process looks like. If you are running on Claude or any hosted model, version-pin where you can and regression-test when you cannot.

    None of this is glamorous. It is the boring work that separates an agent that survives in production from one that gets rolled back in week two. I talk about more of these lessons on LinkedIn if you want to compare notes.

    Frequently Asked Questions

    Why do AI agents fail in production after passing all their tests?

    AI agents often fail in production because test inputs are too clean and predictable compared to what real users actually type. Other common causes include tools that return vague responses the agent cannot reason about, and a lack of decision logging that makes it nearly impossible to diagnose what went wrong.

    How do I stop my AI agent from choosing the wrong tool for a user request?

    Write tool descriptions as retrieval hints rather than documentation, and use specific parameter names that clearly signal their purpose. Ambiguous phrasing from real users causes the agent to score tools incorrectly, so tighter tool contracts reduce misrouting significantly.

    What is silent failure in an AI agent and why does it matter?

    Silent failure happens when an action inside an agent workflow fails but the agent still generates a confident-sounding response, giving the user no indication anything went wrong. This is dangerous because the underlying task was never completed, and the problem may not surface until days or weeks later.

    When should I add decision logging to an AI agent?

    Decision logging should be built in before the agent goes live, not added after something breaks. Without it, you can see that the agent ran but not why it chose a particular tool or produced a specific response, which makes debugging little more than guesswork.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Stop Reaching for Desktop Flows When a Cloud Flow Would Do the Job

    Stop Reaching for Desktop Flows When a Cloud Flow Would Do the Job

    Decision guide for cloud flows vs desktop flows in Power Automate

    I keep seeing the same pattern on LinkedIn and in community calls. Someone builds a desktop flow to read an Outlook inbox. Someone else builds a desktop flow to write rows into SharePoint. Then they wonder why the bot crashes every time IT pushes a Windows update. The cloud flows vs desktop flows decision is not a style choice. It is an architecture choice, and most teams get it backwards.

    The problem

    People reach for desktop flows because they saw a demo where someone automated a click on a button and it felt powerful. So now every automation idea starts with Power Automate Desktop open and a recorder running. That is how you end up with a UI automation reading an Exchange mailbox that has had a documented Graph API for years.

    Here is the rule I use, and it has not failed me yet.

    If the system has an API or a connector, use a cloud flow. If it does not, use a desktop flow. That is it.

    Everything else is rationalisation. Outlook has a connector. SharePoint has a connector. Dataverse has a connector. SAP has a connector. ServiceNow has a connector. Salesforce has a connector. If you are clicking buttons in any of these with Power Automate Desktop, you are building a fragile silo for a problem that was already solved.

    Cloud flow Desktop flow
    Target has a first-party connector Always. Over 1000 connectors exist. Never. You are rebuilding a solved problem.
    Target has a documented REST API Custom connector or HTTP action. One-time investment. No. UI automation against an API-backed system is selector fragility for nothing.
    Legacy app, Citrix, thick client, no API Not possible. The one real use case. Build it knowing the maintenance cost.
    Typical failure mode API error you can read and handle. Moved window, font scaling change, 3am patch reboot.
    Maintenance Low after setup. Babysitting forever.

    The fix

    Before you open Power Automate Desktop, run through three checks.

    Check 1. Does the target system have a Power Automate connector? Go to the connector reference and search. There are over 1000 connectors. If yours is there, the conversation is over. Build a cloud flow.

    Check 2. Does the target system have a documented REST API? If yes, and there is no premade connector, build a custom connector or use the HTTP action in a cloud flow. Still cloud. A custom connector is a one-time investment that pays back for years. A desktop flow against the same system needs babysitting forever.

    Check 3. Is the target a legacy desktop app, a Citrix session, a thick client with no API, or a website with no public API and aggressive anti-automation? Now you have a real desktop flow use case. Build it, but build it knowing the maintenance cost.

    The reason this matters is not aesthetics. It is failure modes. Cloud flows fail on API errors you can read and handle. Desktop flows fail because someone moved a window, changed a font scaling setting, or the machine running the unattended bot rebooted for patches at 3am. I wrote about this exact trade-off in RPA vs AI automation. Determinism is the whole point of RPA. The moment you put RPA in front of a system that already exposes a stable contract through an API, you are throwing away the determinism you came for and replacing it with selector fragility.

    One more pattern I see and want to call out. Hybrid flows are fine. A cloud flow that triggers a desktop flow only for the one screen that has no API is a perfectly clean design. What is not clean is a desktop flow that opens Outlook, opens SharePoint, opens Excel Online, all through the UI, when every single one of those has a first-party connector. That is not automation. That is a recorded macro pretending to be an enterprise solution. If you are prototyping flow logic and want a faster feedback loop without spinning up connectors every time, Thirty Days Running Ollama Locally for Automation Work covers where local AI actually saves time during that phase and where it falls short.

    The Microsoft Learn docs lay this out clearly under Power Automate documentation, but the guidance gets lost in the noise. The short version, from what I have built and watched others build: API first, connector second, custom connector third, desktop flow last. Reverse that order and you will spend more time fixing the automation than you saved by building it. And if your flows are starting to touch Dataverse directly, the Power Platform May 2026 Update has a few things worth turning on before you go further, particularly Power Fx UDTs hitting GA.

    Frequently asked questions

    When should I use a desktop flow instead of a cloud flow?

    Only when the target system has no connector and no documented API. That means a legacy desktop app, a Citrix session, a thick client, or a website with no public API. If a connector or REST API exists, build a cloud flow. No exceptions have held up in anything I have built or watched others build.

    Can I combine cloud flows and desktop flows?

    Yes, and the clean pattern is a cloud flow that orchestrates everything and triggers a desktop flow only for the one screen that has no API. The anti-pattern is a desktop flow driving Outlook, SharePoint, and Excel Online through the UI when all three have first-party connectors.

    Why do desktop flows need more maintenance than cloud flows?

    Because they fail on things that have nothing to do with your logic. A moved window, a font scaling setting, an unattended machine rebooting for patches. Cloud flows fail on API errors you can read, log, and handle in the flow itself.

    What if there is no premade connector for my system?

    Check for a documented REST API first. If one exists, build a custom connector or call it with the HTTP action from a cloud flow. That is a one-time investment that pays back for years. A desktop flow against the same system needs attention every time the UI shifts.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Thirty Days Running Ollama Locally for Automation Work

    Thirty Days Running Ollama Locally for Automation Work

    Workstation running Ollama locally for automation prototyping with Power Automate flows on a second monitor

    I spent the last thirty days running Ollama locally for automation prototyping. Power Automate flow drafts, Copilot Studio prompt iteration, extraction tests on documents I did not want to push to a hosted endpoint during early experimentation. This is the honest review.

    The short version: local AI earned a permanent spot in my prototyping loop. It did not earn a spot in production. The gap between those two things is bigger than most tutorials admit, and the hardware reality check is the part nobody writes about until they have lived through it.

    What I used it for and the setup

    Workstation is a 32GB RAM machine with a decent GPU. Nothing exotic. I ran Ollama with a rotation of models: Llama 3.1 8B for fast iteration, Qwen 2.5 14B for anything that needed actual reasoning, and a quantized Mistral variant for extraction work. Pulled, swapped, benchmarked over four weeks.

    The work itself was three buckets. Drafting Copilot Studio topic prompts and testing how they handled vague phrasing before I touched the real environment. Prototyping extraction logic for unstructured text where I wanted to see the shape of the output before deciding on a hosted model. And quick scratch work: rewriting a Power Fx expression in plain English, sketching a flow outline, asking dumb questions I did not want logged anywhere.

    What it does well

    Iteration speed. This is the win. When I am tuning a system prompt for a Copilot Studio topic, I want to run it twenty times with small variations and see what breaks. Doing that against a hosted endpoint means watching token costs, hitting rate limits, and waiting on network round trips. Locally, I iterate as fast as I can type. That alone saved me probably six hours over the month.

    Working with sensitive drafts. There are documents I would not paste into a cloud chat during a five-minute exploration. Internal text, draft policies, anything that has not been cleared for an external endpoint. Having a local model means I can think out loud against real text instead of synthetic placeholders. The placeholders always lie to you about how the real prompt will behave.

    Offline. I traveled twice this month. Trains, hotel wifi that pretends to exist. Ollama did not care. My prototyping loop kept moving.

    Learning the failure modes up close. Running models locally forced me to actually see how an 8B model reasons versus a 14B, where quantization hurts, where context windows bite. That intuition transfers directly to how I think about agentic workflows, because the reasoning layer is the reasoning layer regardless of where it runs.

    Where it falls short

    Quality drop on anything that needed real reasoning. I tried wiring a local model into a Power Automate flow through a custom connector for an extraction task that hosted models handle cleanly. The 8B model produced confidently wrong JSON about thirty percent of the time. The 14B was better but slower than I could tolerate inside a flow that triggered on document upload.

    Hardware reality. Most tutorials show a 7B model running snappy and call it a day. Try running a 14B model with a 16K context window while you also have Teams, a browser with forty tabs, and Power Apps Studio open. My machine started swapping. Cooling fans did things I did not know they could do. If you do not have a dedicated GPU with serious VRAM, you are running small models or you are waiting.

    Tool calling is rough. Hosted models have spent a year getting better at structured tool use. Local models I tested were inconsistent at best. For an automation developer, this matters. The whole point of an LLM in a flow is reliable structured output. When the local model returns malformed JSON for the fourth time in a row, you go back to the hosted endpoint and you do not feel bad about it. The work being done on the Dataverse plugin for coding agents is a good example of how the hosted side is pulling ahead on exactly this problem.

    No place in production. I want to be direct about this. I would not put a locally hosted model behind a production Power Automate flow at my desk. It is not redundant, it is not monitored, it is not anyone’s responsibility but mine. Production is a hosted endpoint with an SLA or it is self-hosted properly in infrastructure that someone else also watches. The OpenAI and Dell Codex on-prem partnership is the more honest version of what on-premise AI actually requires to work at that level.

    Where I would (and would not) reach for it next time

    I will keep running Ollama locally for prompt iteration, exploratory extraction tests, and any draft work that should not leave my machine. That is the lane. It is a real lane and it saves me real hours.

    I will not reach for it when I need consistent tool calling, when the task needs the reasoning quality of a frontier model, or when anyone other than me depends on the output. For those, I go back to hosted. I share my thinking on this kind of tradeoff regularly on LinkedIn, and the pattern is always the same: prototype locally, ship hosted.

    Should you start learning local AI right now? Yes, if you prototype a lot or handle drafts you would rather not send to a cloud endpoint. The intuition you build about model size, quantization, and context limits pays off everywhere else. Just do not let anyone sell you that your laptop is going to replace a hosted model in production. It is not. Not yet.

    Frequently Asked Questions

    How do I get started running Ollama locally for automation prototyping?

    You can install Ollama on a machine with sufficient RAM (32GB is a comfortable starting point) and pull models suited to your tasks, such as a smaller 8B model for fast iteration or a larger 14B model for more complex reasoning. From there you can test prompts and extraction logic against local documents without touching any hosted endpoints or incurring API costs.

    What are the main benefits of using a local AI model instead of a hosted one?

    Local models let you iterate quickly without worrying about rate limits, token costs, or network latency. They also allow you to work with sensitive or uncleared documents that you would not want to send to an external service during early experimentation.

    When should I use a local model versus a hosted AI endpoint for automation work?

    Local models are well suited to the prototyping and prompt-tuning phase, where speed and privacy matter more than peak output quality. For production automation workflows, hosted models typically offer better reasoning quality and reliability, making them the stronger choice once you move past early experimentation.

    Why does model size matter when choosing an Ollama model for automation tasks?

    Smaller models respond faster and use less memory, which suits quick iterative work, but they reason less reliably on complex tasks compared to larger models. Understanding this tradeoff locally builds practical intuition that directly applies when selecting and configuring models in production agentic workflows.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Inside a Power Platform Center of Excellence: Why Most Setups Stall in Month Three

    Inside a Power Platform Center of Excellence: Why Most Setups Stall in Month Three

    Power Platform Center of Excellence setup architecture diagram

    Most people think a Power Platform Center of Excellence setup works like installing a product. You import the CoE Starter Kit solution, run the setup wizard, point it at your tenant, and the dashboards fill up. Job done.

    That is the surface behaviour. The actual mechanism underneath is a chain of dependencies, sync jobs, and admin connector calls that quietly degrade if any one link breaks. I keep seeing teams hit this on LinkedIn and in conversations with people at other organisations. The kit looks healthy for six weeks, then the inventory stops matching reality and nobody knows why.

    Let me walk through what is actually happening underneath.

    What you see on the surface

    You install the CoE Starter Kit, the wizard provisions a Dataverse environment, and a set of cloud flows starts populating tables like Environments, Apps, Flows, and Makers. The Power BI dashboard lights up. You see a maker count, an app count, an orphaned resource list.

    From the outside, it looks like the kit is scanning your tenant. It is not scanning anything in real time. Every number you see is the result of scheduled flows that ran sometime in the last 24 hours, hit admin connectors, paginated through results, and wrote rows into Dataverse. The dashboard is just a read on that table.

    This matters because the moment those flows stop succeeding, your dashboard stops being true. And it does not tell you it stopped being true.

    The underlying mechanism

    The CoE kit runs on a stack of sync flows. The most important ones are Admin Sync Template v3 (environments), Admin Sync Template v4 (apps and flows), and the maker activity flows. Each one authenticates as the service account you set up during install and calls the Power Platform for Admins, Power Apps for Admins, and Power Automate Management connectors.

    Three things have to be true for those flows to keep working. The service account needs an active Power Platform Administrator or Global Administrator role. The account needs a per-user Power Automate licence with the right premium entitlements, because the admin connectors are premium. And the account needs to not be hitting throttling limits while paginating through a tenant with thousands of resources.

    The CoE sync flows are exactly the kind of workload that hits both platform-level and connector-level throttling, because they loop through every environment and every app in the tenant in one run. Getting your Power Automate error handling patterns right matters here — transient throttling errors need to be caught and retried differently from terminal failures, or the sync silently drops data.

    Where it breaks

    The most common failure mode is not the install. It is month three.

    The service account password expires, or MFA gets enforced tenant-wide, or someone removes the admin role because of a security review. The flows start failing silently. Default retry logic masks it for a week or two. Then the runs hit timeout and stop entirely. The dashboard freezes on stale data, but the numbers still look plausible, so nobody notices.

    The second failure mode is scale. The kit was designed for small to medium tenants. If you have 40,000 apps and 80,000 flows across hundreds of environments, the sync flows do not finish inside the 30-day Dataverse retention window for run history. You lose visibility into your own automation.

    The third one is the licensing trap. Teams install the kit on a trial, then move to production without giving the service account a proper premium licence. The flows technically run, but premium connectors throw 403s on specific calls, and only some tables populate. Half the dashboard works. The other half lies.

    What this means for how you build it

    Treat the CoE as a product you operate, not a kit you install. That changes a few decisions.

    Use a dedicated service principal with certificate auth where the connectors support it, instead of a user account with a password. The service principal does not expire, does not get MFA, does not get caught in a leaver process. Where you must use a user account, document it, monitor it, and put the password rotation in a runbook owned by a real team.

    Build a health check flow that runs daily and alerts when the last successful sync timestamp on each core table is older than 48 hours. Do not trust the dashboard to tell you the dashboard is broken.

    For larger tenants, split the sync flows by environment group instead of running them tenant-wide. The kit supports filtering, and partial visibility refreshed daily beats full visibility refreshed never.

    Decide what governance question the CoE is actually answering for you before you build dashboards on top of it. Inventory is not governance. A list of 12,000 apps with no owner attached is just a longer problem. The broader challenge of Power Platform governance that does not kill adoption is worth thinking through before you design your DLP and ownership policies around what the CoE surfaces, because the data is only useful if makers trust the system enough to stay inside it.

    The CoE Starter Kit is genuinely good engineering. It just is not magic. If you are starting to build out more automation on top of your tenant inventory, the question of why Power Automate is still worth learning in 2026 is a good framing for where to focus the team’s time once the CoE is stable. If you want to compare notes on how other teams are running theirs, I am always up for that conversation.

    Frequently Asked Questions

    Why does my Power Platform center of excellence setup stop working after a few weeks?

    The CoE Starter Kit relies on scheduled sync flows that call admin connectors on a recurring basis. If the service account loses its licence, hits throttling limits, or has a permission issue, those flows fail silently and your dashboards show stale data without any obvious warning.

    What licences and permissions does the CoE Starter Kit service account need?

    The service account requires either a Power Platform Administrator or Global Administrator role, plus a per-user Power Automate licence that covers premium connectors. Without the premium entitlement, the admin connector calls used by the sync flows will not run.

    How do I know if my CoE sync flows have stopped running correctly?

    The dashboards will not alert you automatically when sync flows fail, so you need to monitor flow run history directly. Comparing your app and environment counts against known tenant activity over time is a practical way to spot when the inventory has drifted from reality.

    Why does the CoE Starter Kit struggle with throttling on large tenants?

    The sync flows paginate through every environment and every app in a single run, which generates a high volume of connector calls in a short period. This makes them prone to both platform-level and connector-level throttling, so transient errors need to be handled with retries rather than treated as permanent failures.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • RPA vs AI Automation for Enterprise Workflows

    RPA vs AI Automation for Enterprise Workflows

    RPA vs AI automation comparison for enterprise workflows

    The decision I keep watching teams get wrong: should this workflow be built with RPA or with an AI agent. The RPA vs AI automation debate gets framed as old tech versus new tech, which is the wrong frame entirely. They solve different problems. Picking the wrong one is how you end up with a fragile bot that needs babysitting or an agent that hallucinates its way through invoice approvals.

    I have built both inside a large org. Here is how I actually decide.

    Determinism and predictability

    RPA assumes the screen, the field, and the click path are the same every time. If the SAP transaction code is VA01 today and VA01 tomorrow, RPA wins. It will execute that path 10,000 times with zero variance.

    AI automation assumes variance is the input. The email phrasing changes, the PDF layout changes, the customer asks the same thing five different ways. An agent reasons over that variance. It is non-deterministic by design, which is a feature for unstructured input and a liability for structured execution.

    Rule of thumb I use: if I can write the decision tree on a whiteboard in 15 minutes, it is RPA work. If the decision tree has more than 30 branches and half of them are “it depends on the wording,” it is agent work.

    Cost per execution

    Dimension RPA (Power Automate Desktop) AI Agent (Copilot Studio)
    Per-run cost Near zero after license Roughly 1 message credit per turn, often 5 to 15 turns per task
    License model Per-bot or per-user attended/unattended Message packs, 25,000 messages per pack
    Scaling cost Linear with bot count Linear with conversation volume and tool calls
    Failure cost Bot stops, you fix it Agent confidently completes the wrong task

    RPA at 100,000 runs a month is basically free compute after the license. An agent at 100,000 runs is not. I have seen teams underestimate this by an order of magnitude because they tested with 50 runs and extrapolated linearly without counting tool calls and orchestration turns.

    Maintenance and brittleness

    RPA breaks when the UI changes. A vendor pushes a new SAP Fiori update, three selectors shift, your bot fails at 3am. I have lived this. The fix is usually 30 minutes, but you need someone on call who knows the bot.

    AI agents break differently. They do not fail loudly. They drift. The model provider updates, your prompt that worked last month now produces a slightly different output format, and downstream parsing silently fails. I wrote about this in my agentic workflow post. The failure mode is worse because users find out three days later when the wrong invoice gets paid. If you are building flows that sit underneath an agent, Power Automate error handling patterns that actually work will save you from the silent failures that surface weeks after go-live.

    RPA maintenance is reactive and obvious. Agent maintenance is proactive and requires evaluation infrastructure most teams do not build.

    What the work actually looks like

    This is the dimension nobody compares on. Look at the input.

    Structured input, structured output, no judgment needed: RPA. Copying 200 rows from a legacy system into a SharePoint list, kicking off a daily report, screen-scraping a vendor portal that has no API. Boring, repetitive, deterministic. Power Automate Desktop handles this all day. If you are still deciding whether to invest time in the broader platform, RPA is not the right tool for every repetitive task is worth reading before you commit to a build.

    Unstructured input, structured output, judgment needed: AI. Reading 500 supplier emails and extracting the PO number, classifying tickets by intent, summarizing a 40-page contract into five bullet points. This is where Copilot Studio or a custom agent earns its cost.

    The hybrid case is the most common one and the one most teams miss. The agent reads the email, extracts the structured fields, then hands off to an RPA bot or a cloud flow that executes the deterministic part. The agent is the reasoning layer. RPA is the execution layer. They are not competitors. They are stacked.

    Governance and auditability

    RPA logs are simple. Action ran, action succeeded, here is the screenshot. Auditors love this.

    AI agents need decision logs, not just execution logs. You need to capture why the agent picked tool A over tool B. Most teams I talk to are not logging this and will get caught when the first compliance review hits. I covered this in The Real Shift Is Not Faster Work It Is Who Owns the Decision. Based on what I have built, this is the gap that bites you 6 months in, not on day one.

    Choose RPA if / Choose AI if

    Choose RPA if: the input is structured, the path is deterministic, the volume is high, the cost per run needs to be near zero, and the system has no API. This is most legacy integration work.

    Choose AI automation if: the input is unstructured, the work requires classification or extraction or summarization, variance is the norm, and you have the evaluation discipline to catch silent drift.

    Choose both if: you have a real workflow. Most enterprise automation is hybrid. The line is not RPA versus AI. It is figuring out which layer does what.

    Frequently Asked Questions

    What is the difference between RPA vs AI automation for enterprise workflows?

    RPA is built for repetitive, predictable tasks where the process follows the same steps every time, while AI automation handles unstructured or variable inputs that require reasoning. They are not competing technologies but tools suited to different problems. Choosing the wrong one leads to either a fragile bot or an agent making confident mistakes.

    When should I use RPA instead of an AI agent?

    Use RPA when your process is consistent, rule-based, and can be mapped out as a clear decision tree. If the same fields, screens, or steps repeat thousands of times without variation, RPA will be faster, cheaper, and more reliable than an AI agent.

    How do I know if AI automation is worth the cost for my workflow?

    AI agents consume message credits per turn and most tasks require multiple turns, so costs scale quickly at high volumes. Before committing, calculate expected monthly runs and multiply by average turns per task, not just per conversation. Teams often underestimate this significantly when testing at small scale.

    Why does RPA break so often in enterprise environments?

    RPA relies on fixed UI selectors, so any interface update from a vendor can shift elements and cause the bot to fail. These failures are usually quick to fix but require someone familiar with the bot to be available when issues occur. Unlike AI agents, RPA fails loudly and immediately rather than silently producing wrong results.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn

  • Power Automate Error Handling Patterns That Actually Work

    Power Automate Error Handling Patterns That Actually Work

    Power Automate error handling patterns with scopes and run after configuration

    Most Power Automate error handling I see in the wild is one Try scope, one Catch scope, and a Teams message that says Flow failed. That is not error handling. That is a notification with extra steps.

    Real Power Automate error handling patterns answer three questions. What failed. Why it failed. What happens to the work that was already in flight when it failed. If your flow does not answer all three, you are going to find out about problems from an angry colleague, not from your monitoring.

    I have rebuilt enough flows after silent failures to have strong opinions on this. Here is what I actually use.

    The Try Catch Finally pattern is the floor, not the ceiling

    Three scopes. Try runs your logic. Catch is configured with Run After set to has failed, is skipped, and has timed out. Finally runs after both, regardless of outcome. This is documented well in the Microsoft Learn Power Automate docs and most builders get this far.

    The problem is what people put inside Catch. Usually a single Post Message action with @{workflow()?['run']?['name']} and a generic failure string. That tells you the flow failed. You already knew that. It does not tell you which action failed inside the Try, what the actual error message was, or what input caused it.

    The fix is using result('Try') inside Catch and filtering for items where status is not Succeeded. That gives you the specific action name, the status code, and the error body. Now your alert is useful.

    Differentiate transient from terminal errors

    This is the pattern most flows skip and it is the one that matters most in production. A 429 from a connector is not the same problem as a 400 from bad input. One needs a retry with backoff. The other needs a human.

    Inside Catch, parse the error and branch. Status codes 408, 429, 500, 502, 503, 504 are transient. Retry them, ideally with a Do Until that has a delay and a max iteration count. Status codes 400, 401, 403, 404 are terminal. Do not retry. Log them and move on or escalate.

    Power Automate’s built-in retry policy on individual actions covers some of this, but it does not let you do anything intelligent with the failure. It just retries with exponential backoff and then gives up. For anything that touches an external system with rate limits, I wrote about how this connects to throttling limits and why default retry behaviour can mask problems until volume increases.

    Compensating actions for partial failures

    This is the one almost nobody does. If your flow creates a SharePoint item, then sends an email, then updates a Dataverse record, and step three fails, what happens to steps one and two? Nothing, by default. You have a SharePoint item that should not exist and an email that should not have been sent.

    The pattern is simple. Inside Catch, run compensating actions for whatever Try already completed. Delete the SharePoint item. Send a correction email. Mark the Dataverse record as Failed rather than leaving it half-updated. You do this by checking result('Try') for which actions actually succeeded before the failure, then reversing only those. If you are using SharePoint lists as your backend, as I covered in SharePoint Lists Are Still the Best Backend for 80 Percent of Power Platform Apps, the compensating delete is straightforward because the list item ID is always available in scope.

    It is more code. It is also the difference between a flow that fails cleanly and a flow that leaves your data in a state nobody can reason about three weeks later.

    Centralise error logging

    Stop writing custom logging logic in every flow. Build one child flow that takes the run ID, the flow name, the failed action, the error body, and the input payload, and writes it to a single Dataverse table or SharePoint list. Every flow calls that child flow from its Catch scope.

    Now you have one place to look when things break. You can build a Power BI report on it. You can spot patterns across flows. You can see that 80 percent of your failures are coming from one connector and actually fix the root cause instead of patching individual flows.

    The notification trap

    If every failure sends a Teams message, people stop reading them within two weeks. I have seen this play out on multiple internal builds. Tier your alerts. Transient errors that self-recover do not need a notification. Terminal errors that need human input do. Compensating actions that ran successfully need a log entry, not a ping.

    The goal is that when a notification arrives, the person receiving it actually opens it. Anything else is noise. This connects to a broader problem I have written about in Power Platform Governance That Does Not Kill Adoption, where poorly designed alerting policies erode trust in automation the same way overly restrictive DLP policies erode maker trust in the platform.

    The pattern that ties it together

    Try Catch Finally for structure. Result filtering for specificity. Transient versus terminal branching for intelligence. Compensating actions for data integrity. Centralised logging for visibility. Tiered notifications for sanity.

    None of this is exotic. All of it is skipped because the happy path works in testing and the edge cases only show up at volume. Build the error handling first. The flow will be slower to ship and faster to trust. And if you are still deciding whether Power Automate is worth investing this depth of effort into, Why Power Automate Is Still Worth Learning in 2026 covers exactly that question.

    Frequently Asked Questions

    What are the best power automate error handling patterns to use in production flows?

    Effective power automate error handling patterns go beyond a basic Try and Catch scope. You should capture specific action-level failures using result(‘Try’), differentiate between transient and terminal errors, and include compensating actions to undo partial work when a flow fails midway.

    How do I find out which action failed inside a Power Automate Try scope?

    Use the result(‘Try’) expression inside your Catch scope and filter for items where the status is not Succeeded. This returns the specific action name, status code, and error body, giving you meaningful diagnostic information instead of a generic failure message.

    When should I retry a failed action in Power Automate versus escalate to a human?

    Retry transient errors such as 408, 429, 500, and 503 using a Do Until loop with a delay and a maximum iteration count. Terminal errors like 400, 401, 403, and 404 indicate a problem with the request itself, so retrying will not help and the failure should be logged or escalated instead.

    Why does Power Automate’s built-in retry policy not work well for rate-limited connectors?

    The default retry policy applies exponential backoff and then stops, but it does not let you inspect or act on the failure in a meaningful way. At low volumes this can go unnoticed, but as traffic increases the lack of intelligent handling can cause widespread failures that are difficult to diagnose.

    About the author: Halilcan Soran is a Senior Business Analyst at Visa working on process optimization with Power Platform, RPA, and agentic AI. He previously led a 15-person team at Thomson Reuters, where the Power Automate solutions he built started his automation career. More about Halilcan · LinkedIn