2. Basic Flow Definition¶
2.1. Flows are like plugins¶
They are defined by a .flow file, similar to the plugin ones:
[Core] Name=MyFlows Module=myflows [Documentation] Description=my documentation. [Python] Version=3
Now in the myflows.py file you will have pretty familiar structure with a BotFlow as type and @botflow
as flow decorator:
from errbot import botflow, FlowRoot, BotFlow class MyFlows(BotFlow): """ Conversation flows for Errbot""" @botflow def example(self, flow: FlowRoot): """ Docs for the flow example comes here """ # [...]
Errbot will pass the root of the flow as the only parameter to your flow definition so you can build your graph from there.
2.2. Making a simple graph¶
Within your flow, you can connect commands together.
For example, to make a simple linear flow between !first, !second and !third:
@botflow def example(self, flow: FlowRoot): first_step = flow.connect('first') # first is a command name from any loaded plugin. second_step = first_step.connect('second') third_step = second_step.connect('third')
You can represent this flow like this:
O is the state "not started" for the flow example.
You can start this flow manually by doing !flows start example.
The bot will tell you that it expects a !first command:
Once you have executed !first, you will be in that state:
The bot will tell you that it expects !second, etc.
2.3. Making a flow start automatically¶
Now, usually flows are linked to a first action your users want to do. For example: !poll new, !vm create,
!report init or first commands like that that suggests that you will have a follow-up.
To trigger a flow automatically on those first commands, you can use auto_trigger.
@botflow def example(self, flow: FlowRoot): first_step = flow.connect('first', auto_trigger=True) second_step = first_step.connect('second') third_step = second_step.connect('third')
You can still represent this flow like this:
BUT, when a user will execute a !first command, the bot will instantly instantiate a Flow in this state:
And tell the user that !second is the follow-up.
2.4. Flow ending¶
If a node has no more children and a user passed it, it will automatically end the flow.
Sometimes, with loops etc., you might want to explicitly mark an END FlowNode with a predicate. You can do it like this, for example for a guessing game plugin:
In the flow code...
from errbot import botflow, FlowRoot, BotFlow, FLOW_END class GuessFlows(BotFlow): """ Conversation flows related to polls""" @botflow def guess(self, flow: FlowRoot): """ This is a flow that can set a guessing game.""" # setup Flow game_created = flow.connect('tryme', auto_trigger=True) one_guess = game_created.connect('guessing') one_guess.connect(one_guess) # loop on itself one_guess.connect(FLOW_END, predicate=lambda ctx: ctx['ended'])