1. Home
  2. Docs
  3. Publishers
  4. Basics
  5. Variables and the Expression Language

Variables and the Expression Language

In this section, we’ll go over the concept of variables and what you can do with them using our built in expression language.

As a side note, we’ve taken Symfony’s Expression Language and modified it to behave more like Java Expression Language.

Two major differences from Symfony’s original implementation are:

  1. If you reference a value that does not exist, instead of an error, you will get null.
  2. We added several convenience shortucts for methods. Instead of having to write $request->getPlatformId() or request.getPlatformId(), you can write request.platformId.
    • When you access a property on an object, we check it in the following order: property, getProperty(), isProperty(), hasProperty().

To start off, let’s go over the use cases for variables and expressions. With these, you can alter the response that is given to the user, you could alter the flow of your service based on some condition, set properties on the fly, etc.

To evaluate something, use the JUEL syntax: my_var evaluated will be ${my_var}. For example, in a Text Response Element you could place “Welcome to ${service_name}!”, which would then be parsed into a greeting for the user.

Setting values

Note

One thing to be mindful of is types of data you set. If you do my_var = 1, that 1 is not going to be a number, but rather a string. If you want to set data as a specific type, use my_var = ${1}.

Service variables

If you recall a previous chapter, we’ve described the Variables tab in the editor. This is where you can set variables that will be available throughout the whole service. In here you’d want to set constants and configuration variables. Generally, things that will be set once and never change. Examples might include paths to a filesystem, maximum retry counts, some API keys, etc.

Runtime variables

As the name suggests, these variables are set and are available during the service’s runtime. The most basic way to set them, and the one you’ll be using most often, is with the Set Params element.

Some elements will provide what we refer to as “status variables”. During their runtime, these elements will gather data and make it available under a name that you will be able to specify. As an example, loop elements will make information about the current loop iteration available, such as the current index, the value being iterated over, flags to indicate whether the element is first or last, etc.

You don’t have to memorize all of these status variable fields, as each element that provides one will have its specific data listed in its help file.

Setting and getting complex values

Using the expression language you can access array fields with the square brackets notation, e.g. ${some_array['field']['subfield']}. This will be important as some elements will result in complex nested data structures.

In addition to accessing data, you can also set nested data yourself. You can either set entire JSON objects yourself, like obj = ${{"prop": "value", "nested": { "a": 1 }}}, or incrementally with the square brackets notation, such as some_arr["prop"]["nested"] = 1.

To retrieve a complex value, use either period accessors OR square brackets. Mixing these will not work.

Either ${some.nested.property} OR ${some["nested"]["property"]}.

When accessing array fields with a numeric index, you have to use the square brackets notation. ${array[0]["prop"]} will work, ${array.0.prop} will not, and neither will ${array[0].prop}.

System variables

There are some variables that are added into the overall context by the currently running component.

Service level variables

  • state (string) – Currently running block ID.
  • previous_state (string) – The previously ran block ID.
  • returning (boolean) – Whether or not the same block got ran twice in a row via the special Read Block Again element.
  • first_call (boolean) – Whether or not this is the very first request in the session.
  • request (object) – Has several different properties
    • intentName (string) – The currently parsed intent name, if any
    • platformData (object) – Platform data specific to the current platform the session is running on. More on that later.
    • launchRequest (boolean) – Whether or not the incoming request is a launch request. Basically identical to first_call.
    • platformId (string) – The name of the platform the session is running on.
    • This list is not exhaustive. Check \Convo\Core\Workflow\IIntentAwareRequest for the rest of the available fields.

Block level variables

Some variables are specific to the currently running block. Currently we have:

  • failure_count (number) – The amount of times the user’s response could not be parsed properly. Starts at 0, and will reset to 0 the moment a request can be processed.
  • result (object) – Present only during a process phase. Contains filled slot values which you can access with result.yourSlotNameHere.

Scopes

Data can be stored under different “persistence levels” or “durations”. There are currently 4 main ones:

  1. Installation – The “longest” lasting one. Data stored under Installation is stored for as long as the conversational skill remains installed on the user’s device. Should the user delete and/or reinstall the skill, this data is lost.
  2. User – Second “longest” lasting scope. This data is stored until the user’s account is changed on their device.
  3. Session – This scope lasts for as long as a session is active. After it ends, this data is reset.
  4. Request – The shortest lasting scope, this scope lasts only for the duration of the current user <-> bot dialog turn. This is usually used by loop elements to provide the data of the current iteration.

Shadowing

If you’re not familiar with the term “shadowing” or “variable name shadowing”, it represents re-declaration of variables with the same name. In Convoworks, you may shadow a variable in various scopes, which are checked in order from most important to least important during expression extrapolation.

Let’s say you have a service level variable called my_name, and it is set to Greg. Later on, you set a variable on the Session scope somewhere, with the same name of my_name, but you set it to Bob. Then you place a Text Response element and set its text property to “Hi, my name is ${my_name}!” This will resolve to “Hi, my name is Bob!” because the Session scope is more specific (important) than the service level scope.

In order from least important to most important, the scopes are: service variables, installation scope, session scope, request scope.

Additionally, variables can be set on Service or on Component level. Component level will hide its parent Component or Service variables.