Context Variables

πŸ“˜

Disclaimer

This is a straight up copy/paste from an article on our Gitlab environment. We will be working on adapting this documentation to the new possibilities Readme delivers us.

Deep dive

This documentation provides all information that is needed to use the context variables functionality within the CM.com Chatbot.

What are context variables?

'Normal' variables are used as a store for information: you put a certain value in and are able to retreive it at a later time.
Context variables extend these variables with the following options on save:

Save optionAccessibilityScope
Until the end of the conversationOnly within the sessionSession
For all future conversationsAcross sessions for a particular chatChat
Shared between conversationsAcross all chatsShared

The option you choose has impact on the amount of time the information stored in that variable will be available. It's linked to the accessibility of that variable too, also denoted by the scope.

Use cases

In most cases storing a variable until the end of the conversation (session scope) will suffice. An example of this is saving an option the user has chosen in order to determine what further part of the script needs to be run. This option can differ from session to session and should therefor only exist in one session.

When you want information to be available after the session is over you'd opt to save the variable for all future conversations (chat scope). A use case for this is asking the user for their name and starting every subsequent session by personally welcoming them.

In case you want to make information available more publicly you can opt for a variable that's shared between conversations (shared scope). This means you'll be able to read from and write to that variable as long as you know its identifier. A use case for this would be a pizza company which lets a group of friends order their pizza's via the bot. By using a unique order number everyone can add their pizza of choice to the order. (See the Pizza bot deep-dive for a more in-depth explanation)

How to use context within the chatbot script

Creating context variables

Context variables can be created in the following steps:

Input step

369369

Save input from a user

Variable step

368368

Save a specified value under a specified name

Web request step

356356

Save information that's extracted from the response

Entry step

Save information from the capture groups in the catch regex, as described in the Bot Script Specification

385385

Read context

The following feature matrix shows you where context variables can be read:

StepRead Support
Entryx
Text√
Input
variable namex
timeout√
Media
name√
url√
Logic
variable√
equals testsx
regex testsx
starts with testsx
CDP event√
Web Request
method√
url√
retry amountx
retry delayx
body√
header keyx
header value√
query parameter keyx
query parameter value√
response extraction variablex
response extraction selectorx
Listpicker
title√
subtitle√
media url√
option label√
option media url√
Apple Pay
merchant name√
order reference√
description√
recipient email√
currency code√
recipient country code√
language country code√
line item labelx
line item typex
line item amountx
Text With Url
message√
url√
url label√
media name√
media url√
Set Variable
keyx
variable√
Location
label√
latitude√
longitude√
search query√
radius√
Wait
interval√
Hand Over
mutation keyx
mutation value√
context keyx
context value√
Command
name√
context value√

To accomodate reading from the different save options, we use the following notation style:

  1. {@session.orderCode}
  2. {@chat.firstName}
  3. {@shared('test').firstName}
  4. {@shared(@session.orderCode).firstName}

Let's unpack this bit by bit:

First off we're greated with brackets surrounding the read definition itself, which indicate that we're injecting a variable. Inbetween them we start by denoting the type the variable is saved under using the corresponding scope definition. This definition is prepended with an @ sign so the system knows not to take this text literally. This is followed by the value you want to retrieve from that scope.

You may have noticed the deviation of the shared scope notation with it's parentheses. This is used to denote the identifier which is required when using context shared between conversations. If the identifier is between single quotes (' ') it's a literal, hardcoded text (example 3), but these variables can also be nested, which comes in handy for providing a dynamic identifier for context shared between conversations:

391391

Here the variable orderCode scoped to the current session is used as the identifier for the CurrentOrderItem context shared between conversations. This CurrentOrderItem then contains the property firstName (example 4).

Read context fallback

If a variable doesn't exist, it gets replaced with an empty text. Currently no validation exists on the existence of context variables, so be careful and sufficiently test your script.

Pizza bot deep-dive

This case is a good example to understand most of the context functionality and uses some more advanced techniques for its implementation. It uses shared scope, a session variable to dynamically provide the shared scope with its identifier and setting a variable based on a regex match from the entry step. The flow works as follows:

The bot listens to an input in the form of "Order xxxxx", where xxxxx is a random 5 digit range of numbers. With the advanced Regex functionality, we save this code as a context variable with session scope under the name orderCode. This scope makes the most sense here as we the variable will be parsed again at the start of the next session.

378378

An order isn't complete without items. To get the user's order we use an input step. That value is put in the variable CurrentOrderItem when the user eventually decides which pizza he/she wants and saved using the shared scope. To put this in the list of current orders, the session variable orderCode that is parsed from the input step comes into play.
Since the shared identifier accepts a context definition we can make sure the pizza order is always stored in the list of the specific order code with which the chat is started.

373373

The dynamic shared context variable works like this: the chatbot recognizes a context variable and resolves this to the orderCode, which in this case is 12345. Now the value for currentOrderItem is saved under the shared identifier 12345. If multiple people add their order, they're all added under that key, which will contain multiple orders from different people.

To confirm the pizza you've ordered we fetch the value of the variable currentOrderItem. In this example it'll default to the last added order in the list. This can be accomplished by using the read notation of shared context and the nested value of orderCode to keep everything dynamic. We make sure to reference the CurrentOrderItem as that's been defined in the input step earlier.

378378

Context variables technical documentation

Write context to database

When a request has been received to save context, it will first be converted to a stringified JSON object. This is then put inside a ContextWriteEnvelope event, where:

  • Context: the stringified object as converted previously
  • ChatId: hash of the channel, ConversationClientId and ConversationHostId in the form of a Guid
  • SessionId: the phonenumber, appleId, some other handle in the form of a Guid

A context variable's value might look like this, including several primitive types and nesting:

{
  "Firstname": "Thimo",
  "Lastname": "Koolen",
  "DateOfBirth": {
    "Day": 22,
    "Month": 12,
    "Year": 1997
  },
  "Active": true
}

The IContextClient (which is injected inside the ChatGrain) handles persisting the given value in the database.

Read queries

Read queries make use of JSON path (a query language for JSON). This supports. This supports more exotic querying than just getting a single value, like querying for items between a certain index range or even filter expressions which select all elements in an object or array that match the specified filter.

Queries are constructed using a IContextQuery object. As JSON Path doesn't allow for multiple fields within one query, the IContextQuery object has a list of queries. Each query has these properties:

  • Key: The name of the result in the final JSON Object
  • Value: The JSON Path query

Adding such queries to an IContextQuery instance is made possible in two ways:

  1. With objectname.Selectors.Add(key, value) where key and value are explained above.
  2. With a stringified JSON object by calling the helper method AddFromStringifiedJson on it

Combining this information we'll get the following simple query by property:

{
  "First": ".$Firstname",
  "Last": ".$Lastname",
  "BirthYear": ".$DateOfBirth.Year"
}

which results in the following JSON object after reading:

{
  "First": "Thimo",
  "Last": "Koolen",
  "BirthYear": 1997
}

Notice that the key in the query with JSON path and the key in the result are identical.


Did this page help you?