Skip to main content

Approval Steps / Suspend in Flows

Flows can be suspended until resumed or cancelled event(s) are received. This feature is most useful to implement approval steps but can be used for other purposes as well.


An approval step will suspend the execution of a flow until it has been approved through the resume endpoints or the approval page by and solely by the recipients of the secret urls.

Suspending a flow in Windmill

Other ways to pause a workflow include:

  • Early stop/Break: if defined, at the end of the step, the predicate expression will be evaluated to decide if the flow should stop early.
  • Sleep: if defined, at the end of the step, the flow will sleep for a number of seconds before scheduling the next job (if any, no effect if the step is the last one).
  • Retry a step a step until it comes successful.
  • Schedule the trigger of a script or flow.

An event can be:

  • a cancel
  • a pre-set number of approval that is met.

For the moment we receive the approval steps in the form of an HTTP request. For each event, a single URL is generated. It is not unique to each user to whom it is sent.

Add Approval Script

You can think of a scenario where only specific people can resume or cancel a Flow. To achieve this they would need to receive a personalized URL via some external communication channel (like e-mail, SMS or chat message).

When adding a step to a flow, pick Approval, and write a new approval script or pick one from WindmillHub. This will create a step where the option in tab "Advanced" - "Suspend" is enabled.

Adding approval step

Use wmill.getResumeUrls() in Typescript or wmill.get_resume_urls() in Python from the wmill client to generate secret URLs.

The number of required approvals can be customized. This allows flexibility and security for cases where you either require approvals from all authorized people or only from one.

Required approvals

Note that approval steps can be applied the same configurations as regular steps (Retries, Early stop/Break or Suspend).

Add a form to the approval page

You can add an arbitrary schema form to be provided and displayed on the approval page. Users opening the approval page would then be offered to fill arguments you can use in the flow.


In the Advanced menu of a step, go to the "Suspend/Approval" tab and enable the Add a form to the approval page button.

Add properties and define their Name, Description, Type, Default Value and Advanced settings.

Add argument

That will the be displayed on the approval page.

Fill argument

You can use the arguments values connecting to resume["argument_name"] in further steps.

Use argument

This is a way to introduce human-in-the-loop workflows and condition branches on approval steps inputs.

Tutorial: A Slack Approval Step Conditioning Flow Branches

The answer to the arguments of an approval page can be used as an input to condition branches in human-in-the-loop workflows.

Here is a basic example we will detail below.


This flow:

  1. Receives a refund request form a user.
  2. Asks on Slack via an approval step what action to take.
  3. The answer is a condition to branches that lead either a refund, a refusal or a deeper investigation.
Fork and try the flow

An automated trigger version of this flow is available on Windmill Hub.

For the sake of the example, we made this flow simple with a manual trigger. Two input were used: "User email" and "Order number", both strings.

Flow inputs

Then, we picked an approval step on the Hub to Ask channel for approval on Slack. With inputs:

  • "slack": your Slack resource.
  • "channel": Slack channel to publish message, as string.
  • "text: Refund request by _${flow_input["User email"]}_ on order ${flow_input["Order number"]}..

Slack inputs

In the Advanced settings of the step, for "Suspend/Approval". We added the following properties to the form.

Form settings

Form settings 2

This will lead to the following approval page:

Approval page

This approval page will generate two keys you can use for further steps: resume["Action"] and resume["Message"]. resume is the resume payload.

Those are the keys you can use as predicate expressions for your branches.

Branches predicate expressions

With Branch one, the first branch whose predicate expression is true will execute.


The content of each branch is of little importance for this tutorial as it depends each operations and tech stack. For the example we used two Hub scripts: Send Email with Gmail and Send Message to Channel with Slack.

Example of arguments used for Gmail and Slack scripts:

Gmail inputs


Slack inputs

Automated Trigger Version

You could use the Mailchimp Mandrill integration to trigger this flow manually by an email reception.


Find it on Windmill Hub

The branch is executed

This flow can be found and forked on Windmill Hub.