Bot Framework Composer Series - 2 - Property management
This is the second part of my Bot Framework Composer blog series. If you want to know more about Adaptive Cards in Composer, take a look at the first part
Introduction
While building chatbots using Bot Framework Composer I often encoutered the problem that I needed to store properties and use them within my dialogs for different purposes. Within the Bot Framework SDK, I would most probably use the state to store information which is not only valuable within a single dialog or turn, but for the whole conversation. The equivalent of the state in Composer is called “memory” which can be described as the bot’s mind or brain.
But unlike within the SDK, the concept of storing properties is a bit different from the state approach, where you basically have user and conversation state. Therefore, this post will give you an overview on how to manage your properties accordingly within your Composer based chatbot.
Property scopes
Within Composer there are four different property scopes:
- user
- conversation
- dialog
- turn
In Composer, property names are always in the format “scope.name” (e.g.: user.firstName). Therefore, the scope of the property is actually part of the property’s name. When setting a new property you’ll need to make sure that you choose the correct scope, otherwise you might end up using a property which can’t be used in the current context. This can happen if you create a property “turn.choiceResult” in one dialog which you want to access in another dialog. As the scope of this property is turn, the value can’t be accessed outside of this particular turn. Therefore you would need to use another scope for your property to fulfill your use case. All of these scopes have a different property lifetime, which are described below…
user
The user scope is tied to the user. This is why properties in the user scope are stored indefinetly for a specific user. Use this scope if you want to store user information such as the following within your bot:
- General information such as name, birthday, age, …
- Location information such as address, street, postal code, country, …
- Contact informaiton such as email address, telephone number, …
To create a new property using the user scope, simply name your property user.propertyName
(e.g.: user.name or user.age).
conversation
In contrast to the user scope, the conversation scope is tied to one specific conversation (identified through the conversationID). Like the user scope, the properties in the conversation scope are kept forever, however they could be accessed by multiple users within the same conversation. Examples use cases for using the conversation scope may be:
- General information about the conversation (e.g.: conversation language)
- Current topic of the conversation
- Wether the bot already asked a specific question within the conversation
- Poll responses given by users within a specific conversation
If you want to create a new conversation-scoped property just use conversation.propertyName
as the property’s name (e.g.: conversation.topic).
NOTE: The conversation scope is not always only bound to one specific user only. For instance, when your bot is used in a Microsoft Teams team or group conversation, multiple users are part of the same conversation and therefore share the same conversationID. So please use this scope accordingly.
dialog
The dialog scope, as the name already suggests, is bound to the active dialog and all parent or child dialogs of the active one. Therefore, the properties in that scope are accessible until the last active dialog in that dialog stack ends (look at this doc for more information on how dialogs work). The following examples make perfect sense, when used in the dialog scope:
- Answers to prompts within a given dialog which are used in further turns
turn
The turn scope is bound to one specific turn within the conversation. A turn is basically described as handling one specific message from the user, therefore this scope is the one with the lowest lifetime as these kind properties are only retained until the bot has successfully handled the user’s message. Thus, turn-scoped properties are often used to cache certain values before persisting them into other scopes, like dialog or user. Three out of the box property within turn scope, however, are:
- turn.activity.text holds the user message within the current turn
- turn.activity.type holds the activity type of the current turn (e.g.: message, conversationUpdate, typing, endOfConversation, messageReaction, …)
- turn.activity.locale holds the locale of the locale of the turn.activity.text property (e.g.: en-us, de-de, …)
Summary
Properties are an essential part within Bot Framework Composer. They are an easy way to share information across the whole conversation and therefore minimize the effort to implement a bot. However, you should always pick the scope accordingly to prevent, that properties are shared between users if they shouldn’t or even worse, properties are in a scope which do not provide the needed property lifetime (e.g. turn scope) 🤖