article by Frank Nimphius, November 2019
User scope variables in Oracle Digital Assistant keep their values beyond conversation sessions. So if, in the context of a conversation, the bot needs to memorize information, then this information should be saved in a user scope variable.
User scope variables are defined at runtime, and not at design time. The variables are saved in the instance specific Oracle Digital Assistant internal database. User scope variables cannot be shared between users and also are messenger specific. This means that a user who runs the same bot on two different messaging channels will save information twice. As far as the content goes that can be saved in a user scope variable, the same types apply as can be used with variables defined in a dialog flow.
To create user scope variables and to store values, you can use the System.SetVariable component or a custom components. To read from user scope variables, you use an expression the dialog flow or a custom component.
This article explains how to work with user scope variables in a dialog flow.
Sample for this article
The sample skill for this article is quite simple. It creates an object and an array to then save it in a user scope variable. At runtime, the user scope variable are then accessed from expressions to print the response shown in the image below
Creating the data mockups
To simulate a real use case, in which the data is queried in a custom component and then saved in a dialog flow variable, the sample uses the System.SetVariable component with Apache FreeMarker expressions to create an object with three attributes "apple", "banana", "oracle". Each attribute references an object with two attributes: "color" and "type". The object is saved in a dialog flow variable bamed "myObject" (variable is of type "string")
Similar, an array is created and saved in a dialog flow variable "myArray"
So with this pre-requisite in place, the user scope variables can be set.
Writing data to user scope variable
In a dialog flow, you use the System.SetVariable component to write the content of a variable into a user scope variable. The image below writes the content of the "myObject" variable to a user scope variable named user.myObject. The "user." prefix indicates that the variable should be created in the user memory scope. Note that you can assign a user scope variable also as the value of a variable property of a e.g System.Text or System.List component. In this case the variable value would be a string.
With this, there are two user scope variables created: "user.myObject" and "user.myArray".
Accessing user scope variables
The image below shows how to reference the user scope variable from an Apache FreeMarker "List" directive. The myArray user scope variable is accessed through "user.myArray.value" in the directive itself (Apache directives don't use "${…}" in the declaration). The below example reads the array, assigns the array elements to a variable "k" that then prints the "make" and "type" attributes.
The image below shows the expression you use to access a nested attribute of an object. ${user.myObject.value.oracle} references the "oracle" attribute in the object. To read one of the nested attributes, you just append the attribute name as so: ${user.myObject.value.oracle.color}
Similar to objects you can access individual elements in an array that is saved in a user scope variable: ${user.myArray.value[0],make} references the "make" attribute of the first object in the myArray user scope variable (which holds an array)
A special case
Reading keys from an object, in which case a key represents an attribute, is a special case. Here, as shown in the image below, you don't use ${user.myObject.value} to reference the object, but reference the object value as a JSON string that then you turn into an object using the Apache FreeMarker "eval" built-in function. This then allows you to print the attribute names (the keys).
A key in an object can be used e.g. to write generic code that prints all information of the object:
The Apache FreeMarker expression for this is shown below:
readObjectFromUserScopeVariable:
component: "System.Output"
properties:
text: "The user scope object has the followingcontent:\n\n<#list (user.myObject?string?eval)?keys as k>${k}: ${user.myObject.value[k].color}, ${user.myObject.value[k].type} \n</#list>"
keepTurn: true
transitions:
next: "readArrayFromUserScopeVariable"
Accessing user scope variables from custom components
You can access user scope variables, for example the "user.myObject" from custom components using: conversation('user.myObject'). A better way though is to pass the name of the user scope variable as an input parameter to the custom component. Avoid tight coupling of a custom component to a specific skill by allowing it to make assumptions about the name of a variable.
About the user scope variable scope
User scope variable not only have a scope that spans user conversation sessions, it also is accessible throughout a digital assistant. This means that a user scope variable could be used to share information between skills. Like for custom components, the rule should be to not make assumptions about the name of a shared user scope variable but to pass the user scope variable name as a custom skill parameter. A sample for this is explained in the following article: TechExchange Quick-Tip: A Generic Way To Share Information Between Skills in a Digital Assistant Using User-Scope Variables
Download Sample Skill
You can download the sample used in the screenshots from the link below. After downloading the ZIP file, import it from the Oracle Digital Assistant skills dashboard (no need to unzip it)
Related Content
TechExchange: All 2-Minutes Oracle Digital Assistant Tech Tip Videos on YouTube
TechExchange Quick-Tip: Accessing Attribute Names and Values of a Data Object