Skip to content


A context manager can both facilitate synchronisation and support a form of RPC by letting participants in a context session expose actions which other participants can ask the context manager to run. Both state synchronisation and action invocation are central concepts for Manatee. A flow is a single executable script which can interact with UI of an application or perform other functionality as described in the modules documentation. A flow can be either a state, an action or a module.

State flows

A state flow represents functionality to set or get the state of an application for a given subject. Both a get and a set version for the same subject is required for the state synchronisation to take place.

An example: Getting an application A and application B to synchronize state using UI integration with the subject foo can be accomplished by creating two state flows for each application, one for getting the current value of foo and one for setting it. If the current value of foo in application A is stored in a textfield accessible with the name fooA then we’d perhaps simply write the get foo flow as follows:

Value = Fields["fooA"].read();

and the set foo flow as:


Similar flows may be applicable for application B.

Notice the use of the special Value in both flows. This is a special variable which is used to store the current value of the subject. It is only available in get and set flows and is used to store the value which should be written to/read from the shared context.

Manatee will then take care of extracting the value and setting it when necessary. The state of foo will be extracted and stored in the context manager regardless of whether there are other applications that must be synchronised.

Application synchronisation example

The shared state (the current value of all synchronised) subjects are available to all flows of type state and action in the Inputs map. The current value for the subject of state flow is also made availble in the special Value variable (as seen in the set foo flow above).

An application does not need to support all subjects made available in the shared context but may decide on supporting a subset only.

Mapping flows

A mapping flow is used to map the existing values in the shared context to new values through a transformation performed in a flow. An example could be that you have a patient identifier in one format that needs to be translated into another format for another application. In this case you can utilise a mapping flow to do the mapping automatically. This is illustrated below.

Mapping a value in the shared context between two formats

A mapping flow operates on one subject only so you need two mapping flows for a two-way mapping.

Action flows

An action flow resembles an RPC invocation either internally in an application or between applications. A flow always belongs to an application and will be run in the context of that application. It cannot be run unless the application is running and attached to a session in Manatee, so Manatee will always attempt to connect to an existing application before starting a new instance when asked to run an action flow for a given application.

Action flows can be started in numerous ways. Two of them are either by a trigger or by using a flow-menu which appears in an application in a context session when the user right-clicks while holding the alt key down.

The flow-menu

Action flows can be used for automation and for fire-and-forget frontend integrations. It is also possible to create action flows, which spans multiple-applications to transfer data or to automate multi-application workflows.

Filtering flows shown in the flow-menu

The flow-menu displays flows, which are relevant for the application and location within the application in which it was invoked. It does this in two ways;

The first filtering is done by extracting values for any subject from whatever the user might have clicked. If the flow has inputs these must be matched with the subjects and values extracted from the context of the click. The purpose of this mechanism is to ensure that the flow has the correct inputs, but it also provides a neat mechanism for open-ended integration. If, for example, we’ve defined a subject for a patient identifier then for a flow which switches patient in an EHR we can define this as an input. Now this flow can be everywhere where we can extract patient identifiers, e.g. you’ll be able to switch the EHR to patient found in an Excel spreadsheet or any other type of application where a patient identifier can be extracted.

An example. If a subject is defined for a patient identifier, this subject can be used in a flow, which switches patient in an EHR. This flow can be initiated from everywhere where we can extract a patient identifier, e.g. to switch the EHR to a patient found in an Excel spreadsheet.

The second filtering is done such that anchored flows are only shown if they’re the anchor matches the location clicked.

Module flows

Module flows are flows which contain some shared functionality which is made available to other (state and action flows). It is a mechanism by which functionality (code) can be shared between flows. A module flow should follow the following template:

// Define some functionality that can be useful for other flows
var isEven = function (n) {
  return n % 2 === 0;

// The `exports` object should be populated with the functions
// and variables that should be exported from the module flow
exports.isEven = isEven;

There are more details on module flows in the flow documentation.

Built-in modules

A flow may interact with the user interface of the application in which it belongs by using any of the defined fields. A number of built-in modules are also made available for a flow. The details and exact nature of these are described in the Manatee v1.29 page for each version of Manatee.

The modules cover a wide range of functionality from inspecting and manipulating the OS windows to accessing external services through http and creating Excel documents. The flow documentation contains numerous examples of their usage.


Triggers are hooks which determine when a flow is run (if not invoked manually). It is possible to have multiple triggers for a single action flow.

Once a trigger is added to a flow it will run the flow when the trigger conditions are met on the Manatee instances which the flow is made available to. It should be noted that adding a trigger can thus interrupt a user of s/he is using the machine running the triggered flow and is therefore recommended primarily for unattended machines. In some cases it will make sense to trigger a flow in an attended situation though.

Examples of triggers are;

  • When a window with a certain title is opened.
  • When a file in a certain folder is created.
  • When the user presses a certain hot-key combination.

See more info in the triggering flows section as well as the documentation for each type of trigger.

Creating a flow

A flow must have a name, a type and some auxiliary information depending on the type of flow. For state flows you must specify its subject and whether the flow gets or sets the state for the subject.

Creating a state-flow

For an action flow the subject prefix should be set. This serves as an identifier for the flow.

Creating an action-flow

For both state and action flows it is useful to set a maintainer as well. Cuesta can be configured, so only the maintainer can edit the flow.


A flow will not be available for a Manatee unless it has at least two groups; one that is the same as the primary (production) group of the Manatee instance and one that is in the set of all the (AD) groups of the user (combined with the username and the name of the machine). Both of these groups must be applied to the application as well.

Editing a flow

Once a flow is created the functionality or code of the flow can be edited as text or in the blockly editor. See the flow documentation for details of how to write flow code and examples as well as documentation on the available modules.


The code of a flow can be edited directly in the code editor. The language we support is Javascript.

The code editor

The code editor has auto-completion and other advanced features. Hit the F1 key to show a list of editor functions and their assigned keyboard shortcut (if any). The editor analyzes your code as you type and points out any problems it finds.

As can be seen in the video, detected problems that you are ok with can be ignored with the // disable-check comment.

If the editor is running in the manatee embedded browser or in an external browser with the Sirenia extension, the flow can be run with F10 or debugged with F11 straight from the editor. If any code is highlighted, only the highlighted code is run.


When the ‘modern’ javascript option is selected while creating a new flow, some additional modern language features become available. They include the following:

  • Arrow functions
var sum = (a, b) => a + b;
  • Block scoped constant variable declarations. This expresses your intent to never change a value.
const fileName = "user-list.csv";
  • Block scoped mutable variable declarations. This expresses your intent that the value may change.
let fileName = "user-list.csv";
  • Template string literals. A powerful mechanism for formatting strings.
function formatFilename(x) {
  return `user-list-${x}.csv`;
const multiLine = `Line 1
Line 2`;

You can also check out this guide to ES6 for some idea of what has changed from ES5. Be aware that we don’t support all ES6 features.


Blockly is a visual programming tool which uses blocks that combines like a puzzle to define complex functionality. Our modules, field interaction etc. is available as pre-defined blocks. Running a sub-flow (i.e. invoking a flow from another flow) is also possible. Blockly can be used to construct the same flows as done via the code-editor and it is possible (to a certain extent) to switch back and forth between the code editor and blockly.

The blockly editor

The simplicity of blockly also makes it possible to setup a workflow where you have dedicated developers constructing the “building blocks” for your automation needs in the code editor while the domain specialists use blockly to piece together actual workflows without writing a single line of code.

Importing flows

It is possible to drag Microsoft Steps Recorder or UiPath projects onto the code editor to import/convert the automations into an existing or new flow.


Anchors are used to filter where a flow can be activated using the flow-menu. Adding an anchor is simply done by selecting which field(s) to use as anchors. When added the flow will only show in the flow-menu when activated within one the fields given. Defining no anchors means that the flow will appear regardless of where the menu was activated.

Inputs and outputs

A flow can accept inputs and produce outputs. Each input can be typed to any of the configured subjects. This is also used for deciding which flow to show in the flow-menu; only flows which can have their inputs matched with extracted content is shown. The value of the input can be accessed in the flow using the Inputs map, e.g.:

var myInput = Inputs["myInputSubject"];

Outputs from a flow can be any root scope defined variable. If we have the following flow;

var myValue = "foo";
var myOtherValue = Windows.topMost.title;

then myValue and myOtherValue can be made outputs in the Settings tab of the flow.

Triggering flows

A flow can be setup to run automatically by using a trigger. Triggers include:

  • Cron which runs flows at certain pre-defined times.
  • Window which runs flows when certain windows are shown or hidden.
  • Filesystem which monitors a folder and runs a flow when files are added, removed or changed
  • and several more …

The group filtering still applies to flows with triggers - thus it is only Manatees which match the groups of a flow that can be triggered.

Adding a trigger to a flow