Skip to content

🚨 Mission 09: Human Oversight and Handling Alternative Flows

🕵️ CodenameOPERATION FAIL-SAFE⭐ Difficulty⏱️ Time 60 min 🧩 ProductsMicrosoft Copilot StudioMicrosoft DataverseMicrosoft OutlookMicrosoft Teams🏷️ TagsAutomationCompliance🏭 IndustriesHR

Preview

This mission is in preview. Content may change and some steps might not work as intended.

🎯 Mission Brief

Welcome back, Agent. In the previous two missions you built a workflow that files resumes, asks the Hiring Agent to match them, and notifies recruiters in Teams. It works, but it cannot yet ask for help or report a failure.

In this mission you'll add human review for uncertain decisions, then make failed runs visible with a try/catch pattern that raises an alert.

🔎 Objectives

In this mission, you'll learn:

  1. How to pause for human review, branch on the answer, and end inactive routes cleanly
  2. How to verify that the role-matching agent asks for help only when its evidence is ambiguous
  3. How to catch failures with a Scope and Run after condition and raise an alert
  4. How to break a step on purpose and read what the run history tells you

🧠 Handling alternate flows

Everything you have built so far is the happy path, where the mail arrives carrying a readable PDF and the agent has enough evidence to match it to a role. Real workflows often run off that path.

Handling those alternate flows takes two different techniques, depending on which kind of logic went wrong:

Deterministic logicProbabilistic logic
Writing a row, uploading a file, posting a cardClassifying an email, matching a resume to a role
Retry the transient fault, mark the run failed, then alert a humanAsk a human before acting when the evidence is ambiguous
You test it by breaking it on purposeYou test it by feeding it awkward inputs

This mission builds a route to handle each of these alternative flows to ensure that the hiring data consistency is preserved.

Covered in Recruit

Human review appears in the node palette in Recruit Mission 07: Automate with Workflows but is never configured there. This mission sets one up, decides what it asks, and routes what comes back.

🧪 Lab 09 - Handle the alternate flows

Prerequisites

Before you start this lab you need:

  • The Autonomous Resume Intake workflow from Missions 07 and 08, published and filing resumes successfully. Everything here is added on top of it.
  • The Hiring Hub app and the Resumes, Job Applications and Tasks tables in Dataverse
  • A test mailbox you control - never a shared or production inbox
  • The test resume PDFs you used in Mission 08 (for example AVERY EXAMPLE (FICTITIOUS).pdf)

Your workflow is still watching the mailbox

If you left the workflow Published at the end of Mission 08, it is still polling that mailbox and will run on any email matching its Subject Filter. This mission needs those live runs, so leave it on - but check that the mailbox is a test one you control.

The workflow you carried in from Mission 08 needs a defined response to uncertainty and runtime failure before it can watch a mailbox unattended. Let's add both paths and then break a step on purpose to prove the failure path works.

9.1 Ask a human when the email is ambiguous

We will now handle the emails that do not route cleanly, where the Classify node routes to Other, the resume is unreadable, or the Hiring Agent can't confidently pick a role. In each of these cases we will pause and ask a person with a Human review node.

You end up with two ways to involve a human, and the difference is who decides that a human is needed:

Human review node (this lab)Request for information (inline agent, Mission 08)
Who decides to askYou - it is a step on a branchThe agent, mid-reasoning
Firesevery time that branch runsonly when the agent judges the evidence ambiguous
Question wordingfixed, written by youwritten by the agent for that specific case
Best fora known category ("we can't classify this")a judgment call you can't enumerate up front

Use the node when you can name the situation in advance, and the agent's request when you cannot. Avery's contradictory Data Analyst email is the second case, because no branch could have predicted it. Taylor's resume is neither, because its role history, PL-400 and pro-code skills map straight to Power Platform Developer with nothing to ask about.

A working agent might make the workflow look like it is stuck!

An agent step publishes its activity log only once it completes, so an agent that is waiting on a human shows nothing at all. Do not cancel the run to "see what it's doing" - cancelling destroys the log you would need to diagnose it. Give it the answer it is waiting for instead.

  1. On the canvas, find the Other branch under the Sort the email node and select the button labeled Add a step after Other.

    The Other branch with its add-step control highlighted

  2. In the Add dialog, under Actions, select Human review.

    The node is added straight away - there is no second list of options to choose from.

    The Add dialog with Human review selected

  3. Select the new node to open its panel.

    The Connection box reads Human review with a green tick and the word Connected. This connector is created for you the first time you use the node.

    The new Human review node open on the Other branch

  4. Rename the node to Triage an unclear email - select the name at the top of the panel, type the new name and press Enter.

    The rest of the mission refers to the node by that name, and its compiled identifier becomes Triage_an_unclear_email.

    The review node renamed for email triage

  5. In Title, enter Review flagged application. This is the subject line the reviewer sees.

    The Title field holding the review request subject

  6. Select </> Switch to expression mode for Message, then paste the complete review request:

    text
    An email arrived that could not be classified. It came from @{triggerOutputs()?['body/from']} with the subject @{triggerOutputs()?['body/subject']}. Please tell us how to handle it. Is this an application that should be processed? Choose Yes to file the attached resume, or No to ignore this email.

    The Message field expands into a multiline editor containing the text and both expressions.

    The review message with sender and subject tokens

  7. In Assigned to (first to respond), start typing your name or email address, then select yourself from the results.

    Confirm your name appears as a chip with your initials. Typing an address without selecting it from the list leaves the field empty.

    The Assigned to field naming the reviewer

  8. Leave Channel set to Outlook - it is already the default.

    The reviewer node keeping its Outlook channel

  9. Select ➕ Add an input, then choose Yes/No from the Choose the type of user input menu.

    The Yes or No input type selected

  10. Select the box next to the type and replace the placeholder with Is this an application?

    The Yes or No question the reviewer answers

    An input's type is fixed

    The type drop-down list looks editable, but switching it does not re-type the underlying input. If you choose the wrong type, delete the input row and add a new one. Delete lives on the row's the more options menu - and for Text inputs only, so does Add dropdown, if you want to offer a fixed list of answers.

  11. On the command bar select Save.

    The Save button for the configured review node

9.2 Route the answer and end the dead branches

Right now the reviewer's answer is recorded and then thrown away - the run ends either way. We will now branch on the answer so that Yes files the resume through the same pipeline the Application branch uses, and No stops the run.

  1. On the Other branch, hover the Triage an unclear email node and select the labeled Add a step after Triage an unclear email.

    The reviewer node with its add step control

  2. In the Add dialog, search for if, then select If/Else under Other.

    The Add dialog searched for if with If/Else under Other

  3. Select the new node, select its name at the top of the panel, and rename it to Did the reviewer confirm it. Press Enter.

    The renamed review condition node

  4. Fill in the condition as follows.

    FieldValue
    PropertySelect ⚡ Insert dynamic content and choose the Is this an application? output of Triage an unclear email
    OperatorEquals (leave as-is)
    ValueYes

    The condition comparing the answer with the text Yes

    Enter Yes, not true

    The input type is Yes/No, but its output is named Is this an application?. The designer accepts a comparison against the boolean true. It looks right and publishes cleanly, but at runtime the node returns the string"Yes" or "No", so equals(..., true) is always false - including when the reviewer answered Yes. Nothing errors, but the branch never fires and nothing tells you why. After a run, the step's Outputs read { "boolean": "Yes", ... }, and the quotes mean text.

  5. Now join the If lane to the work that already exists. Drag from the output handle on the right-hand edge of the Did the reviewer confirm it node onto the left-hand edge of the Process application scope, so a new connector is drawn between them.

    The If lane connected to Process application

  6. Look at where Process application now sits.

    The Process application scope is now reachable from two routes - the Application classification and the Did the reviewer confirm it branch.

    Process application receiving both workflow routes

Process application now sits after the Classify node, so it runs whenever the switch completes - no matter which branch was taken. OutOfOffice, Junk and the Else lane you are about to use for "No" have no path to that merge, so the compiler injects a hidden terminate step into each one and marks the whole run Failed with PartialJoinNotReached ... (code: CROSS_SCOPE_MERGE). An out-of-office reply would no longer be read and ignored - it would fail the run.

So next we end those three branches deliberately, with an End node, so the run stops cleanly before it ever reaches the merge.

  1. Hover the Did the reviewer confirm it node and select the labeled Add a step after Else.

    The Else lane with its add step control

  2. In the Add dialog, type End in the search box and select End - it is listed on its own under the Other heading, above similarly named connectors.

    The Add dialog searched for End on the Else branch

  3. Leave Run status set to Succeeded - the default. Nothing went wrong, there was simply nothing to do.

  4. Rename the node to Stop - not an application.

    Renamed Stop node and its Succeeded run status

  5. Repeat those four steps twice more, on the OutOfOffice branch naming the node Stop - auto-reply, and on the Junk branch naming it Stop - junk mail.

  6. On the command bar select Save, then Publish. The canvas now carries all three Stop nodes on their dead branches.

    The finished canvas with four branches and every Stop node

All four branches now have somewhere to go:

--- config: look: neo flowchart: useMaxWidth: true --- flowchart TB CL["Sort the email<br/>(Classify)"] CL -- "Application" --> PA["Process application<br/>(Scope)"] CL -- "OutOfOffice" --> E1["Stop - auto-reply<br/>(End · Succeeded)"] CL -- "Junk" --> E2["Stop - junk mail<br/>(End · Succeeded)"] CL -- "Other" --> HR["Triage an unclear email<br/>(Human review)"] HR --> IF{"Did the reviewer<br/>confirm it"} IF -- "If · Yes" --> PA IF -- "Else · No" --> E3["Stop - not an application<br/>(End · Succeeded)"]

9.3 Test both review answers

Next we answer No and watch the run stop, then we replay that run, answer Yes, and watch it continue into the filing pipeline.

Answer No

  1. Send the monitored mailbox an email with Application in the subject, a PDF attached, and a body that is clearly not an application:

    text
    Hi there, I am not applying for anything today. I just wanted to ask how long
    your recruitment process usually takes, and whether you accept speculative
    CVs. I have attached a document only so you can see the format we use. No
    action needed.

    The non-application email sent with an attachment

    The trigger fires only on mail with attachments, so a bare text email never starts a run at all.

  2. Open the Activity tab and select the running item. Triage an unclear email shows Waiting, and the actions after it show Waiting too because they are queued behind the review.

    The run stays in this state until a human answers the card. It is not stuck and it will not time out on its own.

    The run waiting on the reviewer node

  3. Open the mailbox you entered in Assigned to and find the Request information email. Check Focused, then Other, then Junk.

    The card shows your Title, the Message with the sender and subject filled in, the heading Is this an application?, two radio buttons and a Submit button.

  4. Select No, then select Submit on the card.

    The review card with No selected

    Use the card's own Submit control - replying to the email does not resume the run. If the buttons do nothing, select Show content first. The card is replaced by "Your response has been successfully submitted."

  5. Return to the Activity tab and open the same run. Within a couple of minutes it finishes Succeeded, with Triage an unclear email and Stop - not an application both green, and Process application and everything inside it Skipped.

    The No run ending green on the deliberate stop

  6. Open Resumes in the Hiring Hub and confirm no new row was created.

Now answer Yes

  1. On the Activity tab, locate the run-selection checkboxes. Select runs selects every visible run, so leave it cleared.

    Activity list with run selection controls

  2. Tick only the run you just finished.

  3. Confirm the command reads Resubmit 1 selected run, then select it.

    One original run selected for resubmission

    Resubmit replays the original trigger payload, attachments included, against the currently published definition - so you are testing the same email a second time.

  4. Open the new run and confirm Triage an unclear email is waiting for a response.

    The resubmitted run waiting on the reviewer again

  5. Wait for the new Request information card to arrive in the reviewer's mailbox.

  6. Select Yes on the card, then select Submit.

    The review card with Yes selected

  7. Open the new run in Activity. This time Stop - not an application is Skipped and Process application runs the full pipeline: the resume is filed, the Hiring Agent matches it, and the Teams card is posted.

    The review-Yes run continuing through the application filing path

  8. Select Did the reviewer confirm it and read its Inputs. They should read { "expressionResult": true }.

    The reviewer condition inputs showing expressionResult true

9.4 Let the agent ask for help itself

The fixed Triage an unclear email human request form handles a situation we can name before the workflow runs. Role ambiguity is different, because the workflow has already filed the PDF, and the matcher must compare that evidence with the open roles in Dataverse before it knows whether another person is needed. The existing Match to an open role agent node from Mission 07 owns that decision.

  1. Inside Process application, select Match to an open role.

    The Match to an open role node open for review

  2. Scroll down the panel and toggle Request human assistance on.

    Its Request for information tool lets the same grounded matcher pause only when two roles fit closely, the PDF is unreadable, or the evidence conflicts.

    Grounded role matcher human assistance settings

  3. Read the instructions and confirm they tell the matcher to return one role when the evidence is clear, and to ask for one role when it is not.

  4. Select Save, then Publish.

Next we exercise the path where the matcher asks for help itself.

  1. Send an email to the monitored mailbox with Application in the subject and a resume PDF whose experience fits more than one open role.

    The ambiguous application email leaving the monitored mailbox

  2. Open the Activity tab and select the new run. Match to an open role reads Running, and every action after it reads Waiting.

    The run held at the role matcher awaiting an answer

  3. Open the mailbox you assigned the reviewer, find the newest Which open role for candidate... card, choose one Job Role, then select Submit. The card replaces its form with a confirmation once your answer is in.

    The role choice card asking which open role fits

  4. Return to the Activity tab and confirm the matcher resumed with that answer, and that Hand off to the Hiring Agent then created and scored the application.

    The matcher resumed and handing the application onward

That run shows the second kind of human involvement. Nothing on the canvas told the workflow to ask - Match to an open role compared the PDF against the open Job Roles, found more than one that fitted, and raised the question itself. The run waited at that node until you answered, then carried on into Hand off to the Hiring Agent with the role you chose.

9.5 Catch a failed run and raise an alert

Right now the Application branch has nowhere to go when a step fails. Dataverse refuses a write, the branch stops, and nobody is told.

The fix is a try/catch. You already have the try: the Process application Scope you built in Mission 07, a box drawn around the work that might fail. Now you add the catch - a second Scope that runs only if the first one failed, posts a message to Teams, and marks the run Failed.

Because a Scope reports Failed if any action inside it fails, this one catch covers the row write, the PDF upload, the agent call and the Teams card.

First, look at the settings the connector already gives you. Every action has its own Settings panel, which you open from the node's more options menu.

  1. On the canvas, select the File resume in Dataverse node.

    The File resume in Dataverse node open on the canvas

  2. At the top of its panel select the more options menu, then Settings. The panel is headed ‹ Settings and every section is already open: Networking, Run after, Security and Tracking.

    The File resume node Settings panel

  3. Read the Networking section without changing anything:

    SettingWhat you should seeWhat it means
    Retry policyDefaultTransient failures are already retried for you.
    Timeout (ISO-8601)PT1HAn hour is the ceiling this action is given before it is abandoned.
    PaginationoffOnly fetches the first page of results.
    Async patternonLong-running calls are polled until they finish.

    The connector already supplies a retry policy and a one-hour timeout, so leave both at their defaults for this workflow.

    The Networking defaults on File resume in Dataverse

  4. Select the chevron next to Settings to go back to the node panel.

  5. On the canvas, hover the Process application container and select the on its right-hand edge, labeled Add a step after Process application.

    The add control on the Process application failure edge

  6. In the Add dialog, search for scope, then select Scope under Other.

    The Add dialog searched for scope with Scope under Other

  7. Select the name Scope at the top of the panel, rename it to Handle failure, and press Enter.

    The Application branch now reads Process applicationHandle failure, with the second box empty.

    The Handle failure Scope placed after Process application

  8. Put the alert inside the catch. Hover the Handle failure container and select the labeled Add a step inside Handle failure.

    Add a step inside Handle failure

  9. In the Add dialog's search box, type post message.

    Add dialog filtered to post message

  10. Under the Microsoft Teams heading, select Post message in a chat or channel.

  11. Rename the node to Alert - filing failed - select the catalog name at the top of the panel, type the new name and press Enter.

  12. Fill in the node as follows.

    FieldValue
    Post asFlow bot (leave as-is)
    Post inChat with Flow bot
    Recipientyour own account
    MessageALERT: Resume filing failed - review the run in Activity
  13. Select Save. Handle failure now contains a single step, Alert - filing failed.

    Alert step saved inside Handle failure

  14. Make the catch run only on failure. On the canvas select the Handle failure container, choose the more options menu, then Settings.

    The Handle failure scope Settings panel

  15. Find the Run after section. The first card is headed Process application - the step that runs before this one. Edit only this card. A second card underneath is headed Alert - filing failed, which is the alert step inside this scope.

    Run after section for Handle failure

  16. Set the four states on the Process application card as follows, so the alert fires only when something inside Process application breaks.

    StateSetting
    Succeededclear the checkbox (it’s selected by default)
    Failedtick
    TimedOuttick
    Skippedleave it cleared

    Run after set to Failed and TimedOut

  17. Select the chevron next to Settings, then select Save.

Keep the catch as the last step on the branch. A step that runs after a skipped step is skipped too, so on a healthy run - where Handle failure is skipped - anything placed after it would be skipped as well, and the run would still report Succeeded while doing nothing at all. If you ever do need a step after a catch, open its Run after and tick Skipped as well as Succeeded, which is the finally half of the pattern.

  1. Catching the error is only half the job. You still want the run recorded as a failure, so it shows up in the Activity list, in run-history filters and in any monitoring built on run status.

    On the canvas, select ➕ Add a step after Alert - filing failed - so the alert is sent first, and the run ends after it.

  2. In the Add dialog, search for end, then select End under Other. The node is called End, not Stop or Terminate - searching for terminate returns only unrelated third-party connector actions.

    The Add dialog searched for end with End under Other

  3. Fill in the node as follows.

    FieldValue
    Run statusFailed - the field is labeled Run status, not Status, and offers Succeeded, Cancelled and Failed
    codeResumeIntakeFailed - a short, easy-to-search, machine-readable label
    messageThe block below - include the offending email so the failure identifies itself without anyone opening the run
    text
    The Autonomous Resume Intake workflow could not complete the Process
    application scope for the
    email from @{triggerOutputs()?['body/from']} with subject '@{triggerOutputs()?['body/subject']}'.
    A recruiter alert has been sent. Open this run and check the per-action
    statuses inside Process application to find the failing step.

    The code and message boxes appear only once Run status is Failed. Neither of the other two statuses represents a fault, so neither takes error detail.

    End node set to Failed with error code

  4. Save.

Now test the catch. You need a step inside Process application to fail while the workflow is running, so next you break the Resume Title expression on File resume in Dataverse.

  1. Inside Process application, select the File resume in Dataverse node.

    The Resume Title column before the catch test rewrites it

  2. In Resume Title, remove the Name token, then select Switch to expression mode (</>).

  3. Enter the following expression, then select Switch to token picker to commit it:

    text
    int('not-a-number')

    Temporary Resume Title expression before committing the change

    The expression is valid, so the designer saves and publishes it. At runtime, not-a-number cannot be converted to an integer. The filing action fails with InvalidTemplate before its Dataverse connector call begins.

  4. Select Save, then Publish. The header changes from Draft to Published.

    If it stays on Draft, open the health center - something else is still unresolved.

  5. Email the monitored mailbox with a short subject beginning with Application, a one- or two-sentence body, and a resume PDF attached. Use Application - J1003 as the subject, and write the body as a genuine application - for example, Avery Example is applying for J1003 Power Platform Consultant. The attached PDF is the authoritative resume.

    The attachment is required because Only with Attachments is on - an email without a file never starts a run.

    Use that application wording so Sort the email routes directly to Application. The failure this lab is testing comes from the expression above.

  6. Wait for the trigger to poll, then open Activity and select the newest run.

    The catch test run reporting the failed processing scope

  7. Read the node statuses. Process application and File resume in Dataverse are Failed, while Alert - filing failed and End are Succeeded.

    The containing Handle failure scope reads Cancelled, not Succeeded, because the End action terminates its own container after creating the alert.

  8. Select the failed File resume in Dataverse node and open Run Details.

    It shows InvalidTemplate because int cannot convert not-a-number to an integer. Inputs and Outputs both say No data available, because expression evaluation failed before the connector ever received an input.

    Run details for the failed resume filing step

  9. Check Teams. The Flow bot chat now carries the message ALERT: Resume filing failed - review the run in Activity.

    Failure alert delivered in Teams

Now undo the break.

  1. Inside Process application, select File resume in Dataverse again.

    File resume node reopened after the test

  2. In Resume Title, select Switch to expression mode, replace the int expression with the following expression, then select Switch to token picker:

    text
    items('For_each_attachment')?['name']

    Original attachment name expression ready to commit

  3. Check that Resume Title shows the Name token again.

    Resume Title restored to the Name token

    That is the attachment's file name from the loop's current item, not the email Subject. After a clean run the column should read exactly AVERY EXAMPLE (FICTITIOUS).pdf.

  4. Select Save, then Publish.

Turning the workflow off when you are done with it

Leave the workflow Published for now - Mission 10 uses it. A published workflow keeps polling the mailbox, so when you no longer need it running, open the Workflows list, hover the Autonomous Resume Intake row, select the more actions menu and choose Turn off. Its Status then reads Draft, and selecting Publish starts it again.

✅ Mission Complete

Mission 09 is complete. Your workflow now pauses for a person when it should, names every step, and tells someone when a write fails.

You can now:

Human oversight: You added fixed and agent-generated review requests before the workflow acts.

Readable automation: You named each node so the canvas and run history explain the process.

Failure handling: You used a Scope and Run after condition to surface failed writes.

Observability: You broke a step on purpose, read the run details, and confirmed the alert it raised.

⏭️ Move to Schedule Interviews with Work IQ mission

📚 Tactical Resources

🔗 Workflows in Copilot Studio

🔗 Error handling and retry policies

🔗 Adaptive Cards

Analytics