Writing Action Code 

Actions are snippets of JavaScript (ES5) code running in the context of the conversation session as part of a conversation dialog step. Actions offers enormous power to the scenario composer. Basically, it allows you to take control over the Bot Framework's APIs to be able to modify and extend your bot's functionality. You can add an Action object anywhere on the designer canvas by dragging the Action icon onto the canvas. An Action object has one entry point and one exit node.

Asynchronous actions 

There are two types of actions: synchronous and asynchronous. In synchronous code, when the code snippets finish execution the next element is called automatically.

On the other hand, when writing asynchronous code, you must check the Asynchronous checkbox so that the automatic call to the next element will be canceled. The Health Bot Service framework can't assume when to call the next element, so you as the scenario author need to provide explicit instructions on when to move to the next element by using a next() expression. See an example of asynchronous action in the section Writing actions best practices.

Actions runtime context 

Code written in an action runs in a special runtime sandbox called a NodeJS VM. When this context is created, it is empty of any objects -- a clean slate. We need to pass to this VM all the objects the author of the action might need to complete their task.  

The author will want to pass their most used objects to the action, in addition to the require object -- the one that allows you to import other node objects as long as they exist in our package.json.

Below is a list of objects we pass to the action sandbox with links to more information:

Object Description
Session Bot framework's current running session.
Require Allows you to import node modules. This is a special version of require you can use to import only packages that are white listed
Builder Allows you to build bot messages, as well as attachments and cards, and send them to the client.
Moment Allows you to manipulate the date and time library.
Next next() is the function you should call when you want to progress to the next step in an asynchronous action.
request-promise Follow the link to view the request-promise library. This object is used to call rest APIs.
Config Configuration object allows access to the values of tenants’ configuration.
Underscore Follow the link to view a useful JavaScript library.

 

White Listed Packages

Below is a list of useful Node JS modules you can import with require:

Package Description
crypto Cryptographical functions
path Path utilities
string-decoder String utilities
querystring Query string parsing
url Url parsing
util NodeJS Utilities
jsonwebtoken JSON Web Token implementation (symmetric and asymmetric)
node-sha1  Exports a SHA1 function that uses node's crypto module under the hood
object-path Access deep object properties using a path
request-promise The simplified HTTP request client request with Promise support, powered by Bluebird
soap A minimal node SOAP client
strformat String formatting for Node.js and AngularJS
to-markdown HTML-to-Markdown converter
ttl Simple in-memory cache for JavaScript
underscore JavaScript's functional programming helper library
xml2js Simple XML to JavaScript object converter

Extending the session function

In addition to all the built-in functionality of the session function, the Health Bot Service has added custom programmatic functionality for you, the author.

Function Description
session.trace(message: string, level:number) Output trace string to the debug window
level: 0-3
session.saveFeedback(message: string) Write feedback string for this user 

Writing actions best practices 

The following is a brief list of best practices to keep in mind when authoring actions:

  • You can always press Ctrl + Space to get a list of variables and functions you can use in actions.

  • Be careful not to write infinite loops or overly heavy code in an action. Actions can't run for more than two seconds. After two seconds, the action will fail with a timeout error.

    Note: This does not mean that asynchronous operations can't run for more than two seconds.

  • You can access the arguments passed to the current scenario by using the ${scenarioArgs} variable.

Example

See below for an example of an asynchronous action for saving feedback:

session.saveFeedback("This was a very good experience").then(function() {
    next();
}).catch(function(err) {
    session.trace("Error writing feedback " + err.message, 3 /*crtitical error*/);
});

Writing in-line expressions 

Everything that is available to the action author is also available in in-line expressions in some steps. These expressions should be very simple -- for example, concatenating strings. If you want to write more complex code, use actions before you get to the step that needs the result from the expression.

The in-line expression will not be evaluated if there is only a literal string. The string "as-is" will be returned.