Write Your Own Bot
Bots in JBManager follow a finite state machine paradigm, using the transitions
library. It is recommended to refer transitions documentation to understand the basic concepts of states, transitions & conditions.
Each Bot is represented by a python class which is a child class of AbstractFSM
class present in jb-manager-bot module.
credentials
in constructor contains all the credentials that will be required by the bot. You can define these credentials while installing the bot in JBManager UI. Values of credentials are passed while configuring the bot in JBManager UI. These credentials are passed in the credentials
dict in the constructor, with credential name as key and credential secret as value. Save this credential as an instance variable credentials
, after performing sanity check if the credentials are present.
A new instance of Bot is initialised for each user session, maintaining seperation between user session.
States
Each processing step in the Bot flow is represented be a state. This is same as state defined in the transitions library.
Declaration: To declare state in Bot code in JBManager, add the state name in states list class variable of your bot code.
Definition: To define the state, create a instance method of name on_enter_<state_name>
in your Bot class.
Status
Each bot running on JBManager can have 4 different status which controls the flow of the bot. The various status are described below:
WAIT_FOR_ME
- It should be used on the top of each state definition representing processing logic of a state is currently executing and should wait for processing to finish before making transition to any other state.MOVE_FORWARD
- It represents that current processing is finished and the FSM is ready to transition to next state.WAIT_FOR_USER_INPUT
- It represents that FSM should wait for user input before making transition to another state. It is used in cases where the FSM wants to capture the user input. The next state after this state should contain the logic to handle the user input.WAIT_FOR_CALLBACK
- It represents that FSM should wait for external before making transition to another state. It is used in cases where the FSM wants to capture the input from 3rd party webhook APIs. The next state after this state should contain the logic to handle the callback input.WAIT_FOR_PLUGIN
- For internal use only.END
- It represents the end of the bot flow. It should be added at the last state of the bot flow.
NOTE: WAIT_FOR_ME
should only be used at start of the state definition. MOVE_FORWARD
, WAIT_FOR_USER_INPUT
, WAIT_FOR_CALLBACK
and END
should be used at the end of state definition. WaIT_FOR_PLUGIN
should never be used in any custom FSM.
Transitions
The switch from one state to another state is managed by defining transition
in Bot class. After completing the current state, the bot will switch to the state as defined by the transition.
In the above example, after completing the first_state
, the bot will switch to executing second_state
. In case the bot is defined to wait for user input or webhook callback after first state (by setting appropriate status in the end), the bot will wait after executing first_state
and only after recieving user input or webhook callback(whichever applicable), it will switch to second_state
.
Conditional Transition
If the next state to switch depends on a boolean condition, conditional transition can be defined to switch. We need define the transition with conditions
key and appropriate condition should also be declared and defined.
To define the condition, create an instance method with the same name as condition name. The method should return boolean True
value denoting the condition to be satisfied, else False
denoting the condition is not satisfied.
In the above example, after finishing the first_state
, bot will call the conditions associated with first_state
as source. Whichever condition returns True
, bot will take that transition and switch to appropriate state defined in the dest
of the transition. If multiple conditions are satisfied, bot will take the transition which is defined first in the transitions
list. For more details on the working of transitions, see transitions documentation.
Variables
To retain information across the states, use variables
dictionary defined in the AbstractFSM
, with variable name as key in string format and value for the variable data.
NOTE: Add only json serializable keys and values to the variables
dictionary.
User Input
To access input by user inside a state, use the instance variable current_input
defined in the AbstractFSM
class. This variable contains the value of current user input in str
data type format.
Note: Variable current_input
will contain the value of user input within the scope of state which comes next to input state i.e state ends with WAIT_FOR_USER_INPUT
status. It contains None
in any other state.
Webhook Input
To access input by an 3rd party webhook api inside a state, use the instance variable current_callback
defined in the AbstractFSM
class. This variable contains the value of current webhook data in str
data type format (You might need to parse it to json).
Note: Variable current_callback
will contain the value of webhook data within the scope of state which comes next to callback state i.e state ends with WAIT_FOR_CALLBACK
status. It contains None
in any other state.
Sending Message to User
To send a message back to user from the bot, use send_message
method defined in the AbstractFSM
class. send_message
method takes FSMOutput
object as an arguement. Populate the object of FSMOutput
class according to the message you want to send to user.
For more details, see FSMOutput documentation.
Possible destinations
out
- The message will follow translation(if applicable) and converted to speech and sent it to user.channel
- There are some messages which don't require translation and should be interpreted as a special message. Those could be either flags for language selection or metadata for the forms which will be displayed to user.rag
- The message will go to RAG component of JBManager instead of user.
Handling Files
To handle Files in the FSM, supplied in the form of bytes. You can access the file bytes using the current_input variable if the state is waiting for user input or current_callback if waiting for a webhook callback.
Note:
Follow the below steps to ensure th FSM receives the file.
Modify the
process_incoming_messages
function inside theincoming
file under Channel section to create ImageMessage or DocumentMessage data object accordinglyModify the
handle_user_input
function inside thebot_input
file under flow section to add file data received from the user.Ensure that the
fsm_input
object is populated with the file data.
Last updated