Conversation flow and memory in Composer
APPLIES TO: Composer v1.x and v2.x
For many bots, state (where the conversation left off or data previously received about the user) is necessary for the bot to have a useful conversation. Composer creates for your bot various properties and memory scopes in which to track your bot's active state. Some properties are maintained for you, such as which dialog is active, but you can also save and retrieve your own properties.
With the memory system, you can:
- Use properties in adaptive expressions.
- Use properties in bot responses and response templates.
- Store user profiles and preferences.
- Remember things between sessions, such as the last search query or a list of recently mentioned locations.
- Pass information between dialogs.
For information about the properties that Composer sets by default, see Memory scopes and properties.
Tip
You should provision a state storage resource, such as Azure Cosmos DB, as part of your publish profile or bot deployment.
Provisioning a state storage resource will ensure that your bot or skill can restore the conversation state on each turn, including when your bot or skill has scaled out to multiple instances.
Without the resource, your bot or skill may communicate inconsistently, depending on the scale or configuration of your deployment. For more information on state storage, see Managing state in Bot Framework SDK.
A piece of data in memory is referred to as a property. A property is a distinct value identified by a specific address comprised of two parts, the scope of the property and the name of the property: scope.name
.
Here are some examples:
dialog.index
this.value
turn.activity
user.name
user.profile.age
The scope of the property determines when the property is available, and how long the value will be retained.
Tip
It's useful to establish conventions for when to use the conversation
, user
, turn
, and dialog
scopes.
Such conventions help with maintenance and context sharing.
Both user and conversation state are scoped by channel. The same person using different channels to access your bot appears as different users, one for each channel, and each with a distinct user state.
When creating a property, also consider how long the property needs to exist. Read more in the composer best practices article.
The Bot Framework defines some longer-term scopes.
- The
settings
scope contains information from the bot configuration file. This is a read-only scope. - The
user
scope associates properties with the current user. Properties in the user scope don't expire. These properties are in scope while the bot is processing an activity associated with the user. - The
conversation
scope associates properties with the current conversation. Properties in the conversation scope have a lifetime of the conversation itself. These properties are in scope while the bot is processing an activity associated with the conversation (for example, multiple users together in a Microsoft Teams channel).
The framework defines some shorter-term scopes. Use these for values only relevant to a specific task.
- The
dialog
scope associates properties with the active dialog. Properties in the dialog scope are retained until the dialog ends. - The
this
scope associates properties with the current action. This is helpful for input actions since their life time typically lasts beyond a single turn of the conversation. Composer defines some properties for you. For an input action:this.value
holds the recognized value for the current input action.this.turnCount
holds the number of times the bot asked the user for this input.
- The
turn
scope associates properties with the current turn. Properties in the turn scope expire at the end of the turn.
The framework also defines scopes for managing the dialog system itself.
- The
dialogcontext
scope contains properties associated with the dialog stack. - The
dialogclass
scope contains information about the active dialog. - The
class
scope contains information about the current action.
There are three tabs in the properties pane that relate to setting properties with prompts: asking for input, managing properties, and validating input.
You might configure an action that prompts for the user's age to store the result in a user.age
property.
Input is collected from users with prompt types provided in the Ask a question submenu.
Prompts define the questions posed to the user and are set in the Responses box under the Bot response tab in the properties pane.
Tip
When prompting the user for information, you can enter in a plain text string, as the example above demonstrates, but you can also use any of the three insert menus. Each results in a drop-down list containing relevant options to choose from:
Reference an existing item in your Bot Responses template.
Reference a property in memory
Reference a prebuilt adaptive expressions function.
Under the User Input tab, the Property property indicates where the user's response will be stored. You can use the Output format property to post-process the user's input.
For more information about implementing prompts, see Asking users for input.
Composer provides a set of memory manipulation actions in the Manage properties submenu. Use these to create, modify and delete properties in memory. Properties can be created in the editor and during runtime. Composer manages the underlying data for you.
Use Set a property to set the value of a property. The image below shows the Value drop down-list with its available options.
The value of a property can be set to a literal value, like true
, 0
, or fred
, or it can be set to the result of an adaptive expression. It's not necessary to initialize the property when storing simple values.
Use Set properties to set a group of properties.
The value of each property is assigned individually in the properties pane. You select Add to set the next one.
Use Delete a Property to remove a property from memory.
Use Delete properties to remove properties from memory.
Use Edit an Array Property to add and remove items from an array. Items set in Value can be added or removed from the beginning or end of an array in the Items property using push, pop, take, remove, and clear in Type of change. The result of the edited array is saved to Result Property.
Tip
You can push the value of an existing property into an array property. For example, you can push turn.choice
into dialog.choices
.
Use Get activity members when you need to get the members who are participating in an activity.
Use Get conversation members when you need to get the members who are participating in a conversation.
Use Update activity to update a message or an activity that was previously sent. To do so, you need the ID of the message that was already sent that you want to update. To get the ID of a message, save turn.lastresult.id
after you call SendActivities. You can use a Set a property action to capture this value and store it for later use.
Note
The Update activity action is supported by channels such as Microsoft Teams and various open-source channel adapters such as Slack and Webex. Before using this action, check whether the channels your bot uses support this activity type. This action isn't currently supported in Bot Framework Emulator and Web Chat.
Use Delete activity to delete a message or an activity that was previously sent. To do so, you need the ID of the message that was already sent that you want to delete. To get the ID of a message, save turn.lastresult.id
after you call SendActivities. You can use a Set a property action to capture this value and store it for later use.
Note
The Delete activity action is supported by channels such as Microsoft Teams and various open-source channel adapters such as Slack and Webex. Before using this action, check whether the channels your bot uses support this activity type. This action isn't currently supported in Bot Framework Emulator and Web Chat.
A child dialog can pass properties to its parent dialog. In this way, a child dialog can encapsulate a multi-step interaction, collect and compute multiple values, and then return a single object containing all of the properties to its parent dialog.
For example, a child dialog named profile may have two prompts to build a compound property representing a user profile:
When the active dialog returns properties to its parent dialog, the return value is specified as the Default result property. You can view and modify this in the properties pane when the dialog is selected in the bot explorer:
Finally, the parent dialog is configured to capture the return value inside the Begin a new dialog action:
When executed, the bot will execute the profile child dialog, collect the user's name and age in a temporary scope, then return it to the parent dialog where it's captured into the user.profile
property and stored permanently.
Some properties are automatically created and managed by the bot. These are available automatically. For example:
Property | Description |
---|---|
turn.activity | The full incoming Activity object. |
turn.intents | If a recognizer is run, the intents found. |
turn.entities | If a recognizer is run, the entities found. |
turn.dialogEvents.event name.value | Payload of a custom event fired using the EmitEvent action. |
Bots can retrieve values from memory for various purposes. The bot may need to use a value in order to construct an outgoing message, or make a decision based on a value then perform actions based on that decision, or use the value to calculate other values.
Sometimes, you'll refer directly to a property by its address in memory: user.name
. Other times, you'll refer to one or more properties as part of an expression: (dialog.orderTotal + dialog.orderTax) > 50
.
Bot Framework Composer uses Adaptive expressions to calculate computed values. This syntax allows developers to create composite values, define complex conditional tests, and transform the content and format of values. For more information, see adaptive expression operators and adaptive expression prebuilt functions.
When used in expressions, no special notation is necessary to refer to a property from memory.
A bot can evaluate values from memory when making decisions inside a branching action like an If/Else or Switch branch. The conditional expression that is tested in one of these branching actions is an expression that, when evaluated, drives the decision.
In the example below, the expression user.profile.age > 13
will evaluate to either True
or False
, and the flow will continue through the appropriate branch.
In this example, after prompting the user using the Prompt with multi-choice action and storing the result in the turn.choice
property, the Branch:Switch action is used to make a decision based on the user's selection.
When using For each and For each page loops, properties also come into play. Both require an Items property that holds the array, and For each page loops also require a Page size, or number of items per page.
One of the most powerful features of the Bot Framework system is the bot response language, particularly when used alongside properties pulled from memory.
You can refer to properties in the text of any message, including prompts.
You can also refer to properties in bot response templates. See Language Generation to learn more about the bot response system.
To use the value of a property from memory inside a message, wrap the property reference in curly brackets and preface it with a $
like this: ${user.profile.name}
.
The screenshot below demonstrates how a bot can prompt a user for a value, then immediately use that value in a confirmation message.
In addition to getting property values, it's also possible to embed properties in expressions used in a message template. Refer to the adaptive expressions page for the full list of pre-built functions.
Properties can also be used within a bot response template to provide conditional variants of a message and can be passed as parameters to both built-in and custom functions.
There are a few short-hand notations supported to access specific memory scopes.
Symbol | Usage | Expansion | Notes |
---|---|---|---|
$ | $userName |
dialog.userName |
Short hand for the dialog scope. |
# | #intentName |
turn.recognized.intents.intentName |
Short hand for a named intent returned by the recognizer. |
@ | @entityName |
turn.recognized.entities.entityName |
@entityName returns the first and only the first value found for the entity, immaterial of the value's cardinality. |
@@ | @@entityName |
turn.recognized.entities.entityName |
@@entityName returns the actual value of the entity, preserving the value's cardinality. |
% | %propertyName |
class.propertyName |
Short hand for instance properties, such as MaxTurnCount , DefaultValue , and so on. |
- Bot responses in Bot Framework Composer.
- For more information about using input actions, see how to Ask for user for input.
- For a list of predefined properties in memory, see Memory scopes and properties.