Skip to main content
Version: 8 - Apfelstrudel

Flows

Flows contain your automation logic in the form of flow scripts. With them, you define what you want to automate and how to do so. This makes them your most important resource in Engine.

The flow script is written in Python. Executions of flows will process the handler function of the flow script.

Depending on the complexity of your automated process, it can consists of one or many flows. Executions of flows can start executions of other flows and pass inputs and outputs between each other.

important

You don't need to know Python to use Engine. Engine provides many features that make it possible to run and monitor flows without coding experience. (e.g. Dependency Visualisation, Script Visualisation, Execution Live Monitor)

Creating or modifying flows, on the other hand, requires some knowledge of Python.

tip

Small flows with well-defined scope can be re-used by many automated processes. We recommend breaking automated processes down into several flows which automate specific tasks. In addition to simpler re-use, it also makes it easier to maintain and extend your automated processes.

Working with Flows

You can create flows in the User Interface by pressing the "Create" button and selecting "Flow":

The buttons to create a flow

The new flow is opened and you can directly modify the script.

The flow script editor provided in the Engine user interface comes with built-in Linting, supports Breakpoints and Step Through. If you prefer to use an offline editor of your choice you can also do so. You can synchronise your offline work with Engine using the Git Integration.

When making changes, Engine does not store older versions of your flows. Make sure to have a backup of your flows if you make significant changes. Or even better: use the Git Integration.

Clicking the "Run" button in the flow view will create an execution of the flow and automatically redirect you to the execution view. Read more about executing flows in the documentation on Development and Productive Mode.

Interaction between Flows

Executions of flows can create executions of other flows.

example

Create a child execution.

import flow_api

def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
my_flow = this.flow('my_other_flow_name')
return this.success('all done')

When an execution creates another execution, a parent-child relation is established between them:

The parent execution lists all children in the "Children" tab

The child execution has a button to navigate to the parent

Passing values

Interactions between flows can be leveraged to build big and complex processes from small an maintainable elements.

Let's observe how you can break up a process into parts. Note that we are passing values between flows multiple times, and one flow's result influences what the other flow does.

example

Flow 1 - Main Process

import flow_api

def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
initial_value = 42

new_value = this.flow(
'Calculator',
name='calculate new value',
initial_value=initial_value, # passing initial_value to the flow 'Calculator'
).get('output_value')['result'] # getting 'result' field of the output_value of the flow 'Calculator'

this.flow(
'Messenger',
name='create message with result',
message_value=new_value, # passing new_value to the flow 'Messenger'
)
return this.success('all done')

Flow 2 - Calculator

import flow_api

def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
# getting initial_value from the 'initial_value' field of the input_value
initial_value = inputs['initial_value']

# doing some (not very) complex calculations
result = initial_value * 1

# saving result into the 'result' field of the output_value
this.set_output(result=result)

return this.success('all done')

Flow 3 - Messenger

import flow_api

def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
# getting message_value from the 'message_value' field of the input_value
message_value = inputs['message_value']

# creating message
this.message(
subject='Message',
message=f' The value is: {message_value}',
)

return this.success('all done')
note

This example is of course very simple and it might be easier to implement all functionality within a single flow. Breaking up processes becomes relevant with increasing complexity and when thinking about future scalability.

Handling Errors

If a child execution fails, it will raise an exception, causing the parent execution to fail as well. To avoid the parent failing, you can catch the exception:

example

Create a child execution and handle errors.

import flow_api

def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
try:
my_flow = this.flow('my_other_flow_name')
except flow_api.DependencyFailedError:
this.log('my_other_flow_name failed')
else:
this.log('my_other_flow_name succeeded')
return this.success('all done')

Please refer to Exceptions for details about error handling.

Interaction with other Services: Connectors

In order to connect with services outside of the Engine platform, you can create connection executions from your flow.

Creating a connection execution from your flow is simple:

import flow_api

def handler(system: flow_api.System, this: flow_api.Execution, inputs: dict):
my_connection = this.connect(
connector_type='GIT',
command='get',
repository_url='https://example.com/path/to/repo.git',
)
# read the outputs of the connection and log them
this.log(my_connection.get('output_value'))

return this.success('all done')

Learn More

Connector Types
Third-Party Python Modules
Executions
Webhooks