Skip to main content

Architecture and Data Exchange

In Windmill, a workflow is a JSON serializable value in the OpenFlow format that consists of an input spec (similar to Scripts), and a linear sequence of steps, also referred to as modules. Each step consists of either:

  1. Reference to a Script from the Hub.
  2. Reference to a Script in your workspace.
  3. Inlined Script in TypeScript (Deno), Python, Go, Bash, SQL or non-supported languages.
  4. Trigger Scripts which are a kind of Scripts that are meant to be first step of a scheduled Flow, that watch for external events and early exit the Flow if there is no new events.
  5. For loop that iterates over elements and triggers the execution of an embedded flow for each element. The list is calculated dynamically as an input transform.
  6. Branch to the first subflow that has a truthy predicate (evaluated in-order).
  7. Branches to all subflows and collect the results of each branch into an array.
  8. Approval/Suspend steps which suspend the flow at no cost until it is resumed by getting an approval/resume signal.
  9. Inner flows.

Flow architecture

Input Transform

With the mechanism of input transforms, the input of any step can be the output of any previous step, hence every Flow is actually a Directed Acyclic Graph (DAG) rather than simple sequences. You can refer to the result of any step using its ID.

Every step has an input transform that maps from:

  • the Flow input
  • any step's result, not only the previous step's result
  • Resource/Variable.

to the different parameters of this specific step.

It does that using a JavaScript expression that operates in a more restricted setting. That JavaScript is using a restricted subset of the standard library and a few more functions which are the following:

  • flow_input: the dict/object containing the different parameters of the Flow itself.
  • results.{id}: the result of the step with given ID.
  • resource(path): the Resource at path.
  • variable(path): the Variable at path.

Using JavaScript in this manner, for every parameter, is extremely flexible and allows Windmill to be extremely generic in the kind of modules it runs.

Connecting Flow Steps

For each field, one has the option to write the JavaScript directly or to use the quick connect button if the field map one to one with a field of the flow_input, a field of the previous_result or of any steps.

From the editor, you can directly get:

  • Static inputs: you can find them on top of the side menu. This tab centralizes the static inputs of every steps. It is akin to a file containing all constants. Modifying a value here modify it in the step input directly.
  • Dynamic inputs:
    • using the id associated with the step
    • clicking on the plug logo that will let you pick flow inputs or previous steps' results (after testing flow or step).

Static & Dynamic Inputs

You can connect step inputs automatically using Windmill AI.


A state is an object stored as a resource of the resource type state which is meant to persist across distinct executions of the same Script. This is what enables Flows to watch for changes in most event watching scenarios.