article by Frank Nimphius, May 2018
Update: Oracle Intelligent Bots has been rebranded Oracle Digital Assistant to better describe its capabilities beyond a standard chatbot. To learn more, visit cloud.oracle.com/digital-assistant
To simplify the definition of common navigation, but also to provide fallbacks in case that states or component don't handle navigation, Oracle Intelligent Bots 18.2.3* and later provide a new feature, which is the ability for the bot designer to specify default navigation handlers.
About Dialog Flow Navigation in Oracle Intelligent Bots
Bot conversations are defined as states in Oracle Intelligent Bots. Each state is associated with a component that renders the bot UI for a user input or a bot response, or that executes logic. A conversation therefore is defined as the linear or non-linear sequence in which states are visited in the context of a dialog flow. For this, Oracle Intelligent bots provides the following options to "trigger" navigation
- Empty Navigation – Sequential navigation that navigates from one state to a next as they appear in the dialog flow going from top to bottom doesn't require any explicit transition directive. In other words, the absence of an explicitly defined state transition always leads to sequential navigation. For example, the following two pseudo state definitions lead to sequential navigation as they don't specify a next state as the target.
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
or
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
transitions: {}
- Actions – Actions allow a component, system or custom, to provide hints to the bot designer as to where navigation should go next. A component can return as many actions as needed. An action is a string that the component returns when it finished processing for the dialog flow to procede. However, its you the bot designer who decides whether or not use those hints or ignore them (e.g. by using empty navigation for sequential navigation). If you want to use the component hint, then the state definition looks as shown below
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
transitions:
actions:
action_string1: "go_to_state1"
action_string2: "go_to_state2"
The example above configured the "actions" transition. "action_string1" and "action_string2" are strings returned by the component associated with the current state. The "go_to_sate1" and "go_to_sate2" names are actually the name of states the dialog engine navigates to when an action string is returned by the component. As an example, a component that evaluates regular expressions may return "match" and "nomatch" as action string. Bot designers map those action names to state names that would handle the reported outcome. The navigation performed with actions can be sequential but also non-sequential, which means it can skip next states or event jump back to a previous state.
Note that you can define as many actions as you want. There is no restriction to the number of actions. The Common Response component (CR component), for example, allows you to define your own actions strings at design time. - Next – The "next" transitions does what is written on the tin: it navigates to a named next state. The state that it navigates to when the component finished processing may be the next state in the dialog flow or any other flow defined. Lets have a look at an example
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
transitions:
next: "go_to_state"
A variant of the BotML sample above is to use expressions to conditionally navigate to a next state
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
transitions:
next: "${variable}"
With this you could, for example, make navigation dependent on the user locale: next: "${profile.locale}_information". For a German user the navigation would be to a state with the name "de_information" while for an English user navigation would be to a state with the name "en_information"
- Error – Components may throw an error if they cannot process. Reason for this could be a problem in the component (seldom) or a failure in a dependent system (more likely). Bot designers could use the error transition to gracefully handle scenarios in which unexpected happens. Lets have a look at an example
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
transitions:
error: "componentErrorHandler"
In this example "componentErrorHandler" is a dialog flow state that handles component errors. If you define error transitions on the component then you have a good chance of handling the problem gracefully because the state you navigate to may be explicitly defined to handle this specific state's problems.
- Return – The return statement does not transition explicit. However, it resets the conversation in that it cleans context variable values and internal state. So the next user input will happen at the beginning of the dialog flow. In other words, the navigation issued by the "return" transition statement is to the top of the dialog flow after cleaning up all context state.
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
transitions:
return: "done"
Note that the string value added to the return statement is not currently used. You can use "done" as in the sample or the name of the state that exits the conversation. Its up to you.
Precedence
There must be a reason for why the previous paragraph listed all the options for navigation in Oracle Intelligent Bots. The reason is that defining default navigation does make more sense if you understand the precedence that a transition type has over the next.
The "weakest" navigation is empty navigation. This means that any other transition directive would be followed first if it matches. Only if none of the other transition definitions matches then empty navigation is used to navigate to the next state.
"Next" is stronger than empty navigation but weaker than "actions". If a next transition is defined then empty navigation never happens for a component and state. However, if actions are defined and if a matching action string is returned by the component then "next " is not used.
"Actions" and "error" require the component to return a specific outcome, which means they don't work otherwise. In this case "next" and then "empty navigation" would determine the next state to navigate to.
With the above it should be clear, that transition directives could be mixed and matched. For example the following BotML code navigates to the returned action or error directive. If none of these are true, then it follows the "next" transition definition
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
transitions:
next: "go_to_state_next"
error: "go_to_error_handler"
actions:
action_string1: "go_to_state1"
action_string2: "go_to_state2"
Default Transitions
Starting Oracle Intelligent Bots 18.1.3, you can define a default transition that is called when an action, error or next transition is not defined on the component but the condition for one of these is met. For example
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
The above BotML pseudo code uses empty navigation since no other transition directive is defined. Similar, …
state_name:
component: "component_name"
properties:
component_property: "value"
component_property: "value"
transitions:
actions:
actions:
action_string1: "go_to_state1"
action_string2: "go_to_state2"
… the above BotML pseudo code would perform empty navigation if the action string returned from the component does not match "action_string1" or "action_string2".
To prevent empty navigation thus is one use case that a default transition can handle. Another use case is to define a global error handler so that you don't need to specify the error transition on each and every state definition. You only would define local error handlers if you knew how to handle possible errors for a state. Both pseudo BotML code sample don't specify an error handler, which means that a user-unfriendly system error is displayed when a problem occurs. Here too a default transition helps.
Defining Default Transitions
Default transitions are defined below the context section as shown below:
context:
variables:
iresult: "nlpresult"
defaultTransitions:
error: "DefaultErrorHandler"
next: "reportMissingNavigationDirective"
actions:
unexpectedAction: "HandleUnexpectedAction"
states:
…
DefaultErrorHandler:
component: "System.Input"
properties:
prompt: "I am sorry, but I discovered a problem. Do you want me to direct you to an agent?"
variable: "yesNo"
transitions:
next: "handleAgentRequest"
The above BotML code defines three default transitions:
- The default error handler is called whenever no error handler is defined on a component state.
- The unexpectedAction is an action string returned by several components like System.List and CR component. So whenever the action is not defined on the component it will be handled by the default transition.
- The "next" default transition handles cases in which empty navigation is performed. You can use this directive e.g. to report errors in the bot dialog flow design that lead to empty navigations, which may lead to unwanted navigation.