Publishing An Alexa Skill

An Alexa Skill in Javascript – Part 6

We’ve done it!  We’ve built an Alexa skill!  Woohoo!  Now we need to publish our skill to the Alexa Skills Catalog and make it official.  Publishing your Alexa skill is the last step in the process of developing and deploying an Alexa Skill.

NOTE:  Pay attention to Amazon’s developer promotions.  You can get a free T-Shirt, Echo Dot, Echo Spot, and even the Echo Show if you publish your skill at the right time.

Prepping the skill.json File

There are a few things we can do to enhance the skill.json file so our skill is ready for publishing.

First, find two images that you can use to represent your skill.  These will appear in the catalog inside the speech bubble, like so:

The images should be png files in two sizes:  small (108 x 108 px) and large (512 x 512 px).  Create a new folder in your project called images and drop the two image files into it for safe-keeping.  We’ll add them to the distribution page later.

Next, we can add some keywords to our skill.json file to help people find our skill more easily, right after the description tag add a “keywords” tag:

                    "description": "Roll Some Dice will roll ...",
                    "keywords": [
                        "die", "dice", "rpg", "dice roller"
                    ]
                }
            },

The last, and perhaps most difficult, task is to create the testing instructions.

Tip:  Test your own testing instructions.  Make sure Alexa actually does what you expect her to do.

Based on our intent’s sample phrases, the slots, the synonyms, and the edge conditions, we have quite a few testing instructions.  Here are those sample phrases we put in the en-US skill model file:

"samples": [
    "roll a die {plusMinus} {modifier}",
    "roll {diceCount} dice {plusMinus} {modifier}",
    "roll {diceCount} dice",
    "roll a die"
]

To test our intent, we need to test the following:

Basic Phrases:

  1. Say “Alexa, start Roll Some Dice and roll a die.”  Alexa will generate a random number between 1 and 6 and say, for example, “You said roll 1 dice. I rolled a three.”
  2. Say “Alexa, start Roll Some Dice and roll 10 dice.”  Alexa will generate 10 random numbers between 1 and 6 and report the results, for example, “You said roll 10 dice. I rolled 3 ones, 4 threes, a four, a five and a six.”

With a modifier:

  1. Say “Alexa, start Roll Some Dice and roll a die plus one.”  Alexa will generate a random number between 1 and 6  and add 1, and say, for example, “You said roll 1 dice plus 1. I rolled a two.”
  2. Say “Alexa, start Roll Some Dice and roll a die minus one.” Alexa will generate a random number between 1 and 6  and subtract 1, and say, for example, “You said roll 1 dice minus 1. I rolled a three.”

With a modifier using synonyms:

  1. Say “Alexa, start Roll Some Dice and roll a die add one.”  Alexa will generate a random number between 1 and 6  and add 1, and say, for example, “You said roll 1 dice plus 1. I rolled a six.”
  2. Say “Alexa, start Roll Some Dice and roll a die subtract one.” Alexa will generate a random number between 1 and 6  and subtract 1, and say, for example, “You said roll 1 dice minus 1. I rolled a three.”

With a modifier, testing the edge/limits we put in:

  1. Say “Alexa, start Roll Some Dice and roll a die plus seven.”  Alexa will generate a random number between 1 and 6  and add 7, maxing out at 6, and say, for example, “You said roll 1 dice plus 7. I rolled a six.”
  2. Say “Alexa, start Roll Some Dice and roll a die minus seven.” Alexa will generate a random number between 1 and 6  and subtract 7, with a minimum value of 0, and say, for example, “You said roll 1 dice minus 1. I rolled a zero.”

Testing missing slots and default values:

  1. Say “Alexa, start Roll Some Dice and roll dice.”  Alexa will generate a random number between 1 and 6 and say, for example, “You said roll 1 dice. I rolled a three.”
  2. Say “Alexa, start Roll some Dice and roll a die plus.”  Alexa will generate a random number between 1 and 6 and say, for example, “You said roll 1 dice. I rolled a three.”
  3. Say “Alexa, start Roll some Dice and roll 1 die frog 3.”  Alexa will not understand and should respond, “Sorry, I can’t understand the command.”

Now we need to “stringify” those phrases and put them in our skill.json file here:

"isAvailableWorldwide": true,
"testingInstructions": "Sample Testing Instructions.",
"category": "GAME_INFO_AND_ACCESSORY",

The easiest way I’ve found to convert the text in the lists above into the correct format is in a text editor (like Notepad++) to replace the marks with \” and then MS Word to replace all paragraph marks (under Special…) with \n, and tab characters (also under Special…) with spaces.  When you’re done, the tests will look like this:

Basic Phrases:\n1. Say \"Alexa, start Roll Some Dice and roll a die.\"  Alexa will generate a random number between 1 and 6 and say, for example, \"You said roll 1 dice. I rolled a three.\"\n2. Say \"Alexa, start Roll Some Dice and roll 10 dice.\"  Alexa will generate 10 random numbers between 1 and 6 and report the results, for example, \"You said roll 10 dice. I rolled 3 ones, 4 threes, a four, a five and a six.\"\nWith a modifier:\n1. Say \"Alexa, start Roll Some Dice and roll a die plus one.\"  Alexa will generate a random number between 1 and 6 and add 1, and say, for example, \"You said roll 1 dice plus 1. I rolled a two.\"\n2. Say \"Alexa, start Roll Some Dice and roll a die minus one.\" Alexa will generate a random number between 1 and 6 and subtract 1, and say, for example, \"You said roll 1 dice minus 1. I rolled a three.\"\nWith a modifier using synonyms:\n1. Say \"Alexa, start Roll Some Dice and roll a die add one.\"  Alexa will generate a random number between 1 and 6 and add 1, and say, for example, \"You said roll 1 dice plus 1. I rolled a six.\"\n2. Say \"Alexa, start Roll Some Dice and roll a die subtract one.\" Alexa will generate a random number between 1 and 6 and subtract 1, and say, for example, \"You said roll 1 dice minus 1. I rolled a three.\"\nWith a modifier, testing the edge/limits we put in:\n1. Say \"Alexa, start Roll Some Dice and roll a die plus seven.\"  Alexa will generate a random number between 1 and 6 and add 7, maxing out at 6, and say, for example, \"You said roll 1 dice plus 7. I rolled a six.\"\n2. Say \"Alexa, start Roll Some Dice and roll a die minus seven.\" Alexa will generate a random number between 1 and 6 and subtract 7, with a minimum value of 0, and say, for example, \"You said roll 1 dice minus 1. I rolled a zero.\"\nTesting missing slots and default values:\n1. Say \"Alexa, start Roll Some Dice and roll dice.\"  Alexa will generate a random number between 1 and 6 and say, for example, \"You said roll 1 dice. I rolled a three.\"\n2. Say \"Alexa, start Roll some Dice and roll a die plus.\"  Alexa will generate a random number between 1 and 6 and say, for example, \"You said roll 1 dice. I rolled a three.\"\n3. Say \"Alexa, start Roll some Dice and roll 1 die frog 3.\"  Alexa will not understand and should respond, \"Sorry, I can't understand the command.\"\n

Now you can plug the new string in the place of Sample Testing Instructions.  Like so:

"isAvailableWorldwide": true,
"testingInstructions": "Basic Phrases:\n1. Say \"Alexa, start Roll Some Dice and roll a die.\"  Alexa will generate a random number between 1 and 6 and say, for example, \"You said roll 1 dice. I rolled a three.\"\n2. Say \"Alexa, start Roll Some Dice and roll 10 dice.\"  Alexa will generate 10 random numbers between 1 and 6 and report the results, for example, \"You said roll 10 dice. I rolled 3 ones, 4 threes, a four, a five and a six.\"\nWith a modifier:\n1. Say \"Alexa, start Roll Some Dice and roll a die plus one.\"  Alexa will generate a random number between 1 and 6 and add 1, and say, for example, \"You said roll 1 dice plus 1. I rolled a two.\"\n2. Say \"Alexa, start Roll Some Dice and roll a die minus one.\" Alexa will generate a random number between 1 and 6 and subtract 1, and say, for example, \"You said roll 1 dice minus 1. I rolled a three.\"\nWith a modifier using synonyms:\n1. Say \"Alexa, start Roll Some Dice and roll a die add one.\"  Alexa will generate a random number between 1 and 6 and add 1, and say, for example, \"You said roll 1 dice plus 1. I rolled a six.\"\n2. Say \"Alexa, start Roll Some Dice and roll a die subtract one.\" Alexa will generate a random number between 1 and 6 and subtract 1, and say, for example, \"You said roll 1 dice minus 1. I rolled a three.\"\nWith a modifier, testing the edge/limits we put in:\n1. Say \"Alexa, start Roll Some Dice and roll a die plus seven.\"  Alexa will generate a random number between 1 and 6 and add 7, maxing out at 6, and say, for example, \"You said roll 1 dice plus 7. I rolled a six.\"\n2. Say \"Alexa, start Roll Some Dice and roll a die minus seven.\" Alexa will generate a random number between 1 and 6 and subtract 7, with a minimum value of 0, and say, for example, \"You said roll 1 dice minus 1. I rolled a zero.\"\nTesting missing slots and default values:\n1. Say \"Alexa, start Roll Some Dice and roll dice.\"  Alexa will generate a random number between 1 and 6 and say, for example, \"You said roll 1 dice. I rolled a three.\"\n2. Say \"Alexa, start Roll some Dice and roll a die plus.\"  Alexa will generate a random number between 1 and 6 and say, for example, \"You said roll 1 dice. I rolled a three.\"\n3. Say \"Alexa, start Roll some Dice and roll 1 die frog 3.\"  Alexa will not understand and should respond, \"Sorry, I can't understand the command.\"\n",
"category": "GAME_INFO_AND_ACCESSORY",

Now, with all that in place, you should be able to push the skill to Amazon again.   At a PowerShell command prompt, from the root folder of your skill, enter the following command:

ask deploy --profile "default" --target "all"

Assuming your skill deployed properly and passes all your tests, we are ready to go through the Distribution and Certification steps in the Alexa Developer Console.

On the first page of Distribution, we can upload the icon files we found earlier.  Simply add them here:

Now click Save and Continue.

Then, because we already filled all this in the skill.json, you can just click Save and Continue again.

And again.

Now, you’re at the validation stage.  Your skill should pass validation.

Click on Functional Test, then click Run.

It passes!! Your skill is ready for Submission.  Go ahead.  Click that Submit button and relax for a bit.  Depending on the promotions and backlog, your skill may or may not get reviewed within the next 1-3 business days.

That’s it for now.  


A few days later…  WOOHOO!

An Alexa Skill in Javascript – Part 5

Finally, the last post in the series.  Here, we will show Alexa how to Roll Some Dice with a modifier so that we can get our skill working properly.

We’re going to do this in two steps:

  1. Create a function that will take the diceCount, plusMinus and modifier parameters and return the results as speech text.
  2. We’ll modify the RollSomeDiceIntentHandler to pull those parameters from the Request and call the function we created in the first step.

Create a Function that can Roll Some Dice

To contain our function, we’ll create a new JavaScript file in the lambda\custom folder of our project.  Right-click on the lambda\custom folder and select New File from the menu.  Enter rollSomeDiceFunction.js as the file name.

In the new file, let’s stub out our function.  We need to export the function to be able to access it from the other file, index.js.  It will accept three parameters.  Like so:

exports.rollSomeDice = function rollSomeDice(diceCountParm, 
plusMinusParm, modifierParm) {

}

Next, we need to verify that the diceCount Slot parameter (diceCountParm) has been provided (i.e. is not null):

if (diceCountParm == null) {
    speechOutput = "Sorry, I did not hear that.  Please say something like roll 2 dice.";
    return (speechOutput);
}

Then, we need to convert the string parameters into numbers.  Slot values are always provided as strings.  We need to verify that the diceCount and modifier contain numeric values and parse the strings to actual numbers.

var diceCount = (isNaN(diceCountParm)) ? null :
    parseInt(diceCountParm);
const diceSize = 6;
var modifier = (isNaN(modifierParm)) ? 0 :
    parseInt(modifierParm);

Now, we need to check again that diceCount is not null:

if (diceCount == null) {
    speechOutput = "Sorry, I did not hear that.  Please say something like roll 2 dice.";
    return (speechOutput);
}

Next, we’re going to set up an array of possible dice rolls so we can keep track of what we roll:

var buckets = [0, 0, 0, 0, 0, 0, 0];
var bucketSlots = ['zero', 'one', 'two', 'three', 'four', 'five', 'six'];

And then we can finally roll the dice:

for (var i = 0; i < diceCount; i++) {
    let roll = 0;
    roll = Math.floor(Math.random() * diceSize) + 1;

And if the user supplied a plusMinus Slot value (in plusMinusParm) and a modifier value, then we need to add or subtract the modifier to/from the dice roll:

if (plusMinusParm != null && modifier != 0) {
    // add or subtract the modifier to each roll
    if (plusMinusParm == 'plus') {
        roll += modifier;
    } else {
        roll -= modifier;
    }
}

Next, we need to put the roll in the correct bucket.  Note that because of the modifier, we could roll less than 1 or more than 6, so we need to handle those values too:

if (roll < 1) {     buckets[0]++; } else if (roll > 5) {
    buckets[6]++;
} else {
    buckets[roll]++;
}

Now, we’ve completed the for loop that loops over the diceCount and we can start putting together the speech phrases that we want Alexa to say in her response.  First, we’ll tackle the buckets so she can say “I rolled 3 ones, 2 twos, a four and 3 sixes.”  Note:  This code snippet uses apostrophes ( ‘ ‘ ) and backward tick marks ( ` ` ) to create the right strings.

var bucketsPhrase = 'I rolled ';
for (let i = 0; i < 7; i++) {     if (buckets[i] > 1) {
        if (i < 6) {
            bucketsPhrase += `${buckets[i]} ${bucketSlots[i]}s, `;
        } else {
            bucketsPhrase += `and ${buckets[i]} ${bucketSlots[i]}es `;
        }
    } else if (buckets[i] == 1) {
        if (i < 6) {
            bucketsPhrase += `a ${bucketSlots[i]}, `;
        } else {
            bucketsPhrase += `and a ${bucketSlots[i]} `;
        }
    }
}

The above code handles the fact that six is the only plural that ends in ‘es’.  And that six is the last number in the set, so put an ‘and’ in front of it.  It also differentiates between ‘a six’ and ‘two sixes’.

The next phrase to put together is the entire speech that we want Alexa to say.  We have two options:  with modifier and without, so the code looks like this:

if (modifier == 0 && target == null) {
    speechOutput = `You said roll ${diceCount} d ${diceSize}. ${bucketsPhrase}.`;
} else if (target == null) {
    speechOutput = `You said roll ${diceCount} d ${diceSize} ${plusMinusParm} ${modifier}. ${bucketsPhrase}.`;
}

Lastly, we return the speechOutput to Alexa:

return (speechOutput);

The Finished Function

Putting it all together, we get the following:

exports.rollSomeDice = function rollSomeDice(diceCountParm, plusMinusParm, modifierParm) {

    var speechOutput = "";
    if (diceCountParm == null) {
        speechOutput = "Sorry, I did not hear that.  Please say something like roll 2 dice.";
        return (speechOutput);
    }
    var diceCount = (isNaN(diceCountParm)) ? null :
        parseInt(diceCountParm);
    const diceSize = 6;
    var modifier = (isNaN(modifierParm)) ? 0 :
        parseInt(modifierParm);

    if (diceCount == null) {
        speechOutput = "Sorry, I did not hear the number of dice to roll.  Please say something like roll 2 dice.";
        return (speechOutput);
    }

    var buckets = [0, 0, 0, 0, 0, 0, 0];
    var bucketSlots = ['zero', 'one', 'two', 'three', 'four', 'five', 'six'];

    for (var i = 0; i < diceCount; i++) {
        let roll = 0;
        roll = Math.floor(Math.random() * diceSize) + 1;

        if (plusMinusParm != null && modifier != 0) {
            // add or subtract the modifier to each roll
            if (plusMinusParm == 'plus') {
                roll += modifier;
            } else {
                roll -= modifier;
            }
        }

        if (roll < 1) {             buckets[0]++;         } else if (roll > 5) {
            buckets[6]++;
        } else {
            buckets[roll]++;
        }
    }

    var bucketsPhrase = 'I rolled ';
    for (let i = 0; i < 7; i++) {         if (buckets[i] > 1) {
            if (i < 6) {
                bucketsPhrase += `${buckets[i]} ${bucketSlots[i]}s, `;
            } else {
                bucketsPhrase += `and ${buckets[i]} ${bucketSlots[i]}es `;
            }
        } else if (buckets[i] == 1) {
            if (i < 6) {
                bucketsPhrase += `a ${bucketSlots[i]}, `;
            } else {
                bucketsPhrase += `and a ${bucketSlots[i]} `;
            }
        }
    }

    if (modifier == 0) {
        speechOutput = `You said roll ${diceCount} dice. ${bucketsPhrase}.`;
    } else if (target == null) {
        speechOutput = `You said roll ${diceCount} dice ${plusMinusParm} ${modifier}. ${bucketsPhrase}.`;
    }

    return (speechOutput);
}

Modify the RollSomeDiceIntentHandler

Now that we have a function that can roll some dice, we need to wire it up to the RollSomeDiceIntentHandler we stubbed out in the basic template code in index.js.

Open index.js, right at the top we’re going to import the function we just created above, like so:

const Alexa = require('ask-sdk-core');
const i18n = require('i18next');
const sprintf = require('i18next-sprintf-postprocessor');
const diceRoller = require("./rollSomeDiceFunction.js");

Next, find the RollSomeDiceIntentHandler.  We’re going to replace the red, bold text in this function:

const RollSomeDiceIntentHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest' &&
            handlerInput.requestEnvelope.request.intent.name === 'RollSomeDiceIntent';
    },
    handle(handlerInput) {

        const speechText = 'Hello World!';

        return handlerInput.responseBuilder
            .speak(speechText)
            .withSimpleCard('Roll Some Dice', speechText)
            .getResponse();
    },
};

First, delete the line const speechText = ‘Hello World!’;

Next, we need to pull the Slot values out of the request:

var diceCount = handlerInput.requestEnvelope.request.intent.slots["diceCount"].value;
var plusMinusSlot = handlerInput.requestEnvelope.request.intent.slots["plusMinus"];
var plusMinus = '';
if (plusMinusSlot.resolutions) {
    plusMinus = plusMinusSlot.resolutions.resolutionsPerAuthority[0].values[0].value.name;
}
var modifier = handlerInput.requestEnvelope.request.intent.slots["modifier"].value;

Next, we need to make sure the user supplied values for the Slots.  If not, we will assign a default value:

if (!(diceCount)) {
    diceCount = '1';
}
if (!(plusMinus)) {
    plusMinus = 'plus';
}
if (!(modifier)) {
    modifier = '0';
}

Next, we need to get the speech from the RollSomeDice() function we created earlier.

const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
sessionAttributes.speakOutput = diceRoller.rollSomeDice(diceCount, plusMinus, modifier) + " ... Now, what shall I roll?";
sessionAttributes.repromptSpeech = 'What shall I roll?';

Lastly, we need to return the speech to Alexa:

return handlerInput.responseBuilder
    .speak(sessionAttributes.speakOutput)
    .reprompt(sessionAttributes.repromptSpeech)
    .withSimpleCard('Roll Some Dice', sessionAttributes.speakOutput)
    .getResponse();

The Completed RollSomeDiceIntentHandler

Putting it all together, we get:

const RollSomeDiceIntentHandler = {
    canHandle(handlerInput) {
        return handlerInput.requestEnvelope.request.type === 'IntentRequest' &&
            handlerInput.requestEnvelope.request.intent.name === 'RollSomeDiceIntent';
    },
    handle(handlerInput) {

        var diceCount = handlerInput.requestEnvelope.request.intent.slots["diceCount"].value;
        var plusMinusSlot = handlerInput.requestEnvelope.request.intent.slots["plusMinus"];
        var plusMinus = '';
        if (plusMinusSlot.resolutions) {
            plusMinus = plusMinusSlot.resolutions.resolutionsPerAuthority[0].values[0].value.name;
        }
        var modifier = handlerInput.requestEnvelope.request.intent.slots["modifier"].value;

        if (!(diceCount)) {
            diceCount = '1';
        }
        if (!(plusMinus)) {
            plusMinus = 'plus';
        }
        if (!(modifier)) {
            modifier = '0';
        }

        const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
        sessionAttributes.speakOutput = diceRoller.rollSomeDice(diceCount, plusMinus, modifier) + " ... Now, what shall I roll?";
        sessionAttributes.repromptSpeech = 'What shall I roll?';

        return handlerInput.responseBuilder
            .speak(sessionAttributes.speakOutput)
            .reprompt(sessionAttributes.repromptSpeech)
            .withSimpleCard('Roll Some Dice', sessionAttributes.speakOutput)
            .getResponse();
    },
};

Publish the Code to Alexa and AWS Lambda

Now that the RollSomeDice() function and the RollSomeDiceIntentHandler are written, we can publish the skill to Alexa and AWS Lambda.

In VS Code, open the Command Palette (View | Command Palette…).  Type ASK.  Select Deploy the skill.

snip_20181106045852

Wait a moment while the ASK initializes, then select the default profile:

snip_20181106045953

Then select “All”:

snip_20181106050011

Now, it will try, and probably fail, to deploy. If it succeeds, great.  If it fails, you probably need to change the working directory in the Terminal window at the bottom right of VS Code.  This is done with the CD command, like so:

snip_20181106050219

Once you’ve changed the directory to the one with your skill in it, press the up arrow on the keyboard a couple of times to get the “ask deploy” command back.  Then press enter.

If all goes well, a few moments later, your skill will be deployed:

snip_20181106050943

Now that your skill is deployed, we can switch over to the Alexa Developer Console to test it.  If you still have your template project open from earlier, click “Your Skills” in the top left corner.  Then you will see your deployed skill at the top of the list:

snip_20181106051315

Click the Edit link on the far right.  On the Build tab, you should see a little popup saying your build was successful:

snip_20181106051456

Click on the Test tab.  If it’s not enabled, enable testing for this skill:

snip_20181106051713

In the Alexa Simulator, type in “start Roll Some Dice and roll 2 dice”.  Press enter.

snip_20181106051938

Alexa should say that she rolled some dice and list the results:

snip_20181109075156

I just realized, there’s one last step:  Submitting Your Skill for Amazon Approval.  This will be covered in my next blog entry.

An Alexa Skill in Javascript – Part 4

So far we’ve defined, gathered and installed the requisite tools in Part 1.  We’ve defined the Skill we’re creating in Part 2.  And, we’ve created the Intents for our skill in Part 3.

Now, we will code the Lambda function that is the brains of our skill in this entry, Part 4.

What is a Lambda Function?

Amazon Web Services (AWS) calls the functions you create in their cloud “Lambda Functions.”  For the purposes of Alexa skills, these functions are the brains behind the skill.  Alexa takes care of the speech part of the skill, and figures out how to interpret the Alexa User’s spoken words and which intent to choose and slots to fill based on those words, but you then have to make your Alexa skill actually do something to fulfill the intent you created on the Alexa side of your Skill development process.  In my case, that means writing a function that can roll some dice and add or subtract and specified modifier to the rolls.

Lambda functions can be written in a variety of languages.  I’ve blogged before about using C# to do this.  (Note:  Using C# is now SOOO much easier as the Lambda Function tools in AWS have been updated to use .Net Core as a standard platform.)  Today, I am using JavaScript (node.js).  Other options include Python, Java and Go.

A Little More Cleanup First

In our VS Code project, in the \lambda\custom folder is a file named package.json.  We need to correct the name of our package here.  My skill is called “Roll Some Dice” so I’ll have to name my code package “roll-some-dice”.  Note the lower case and replacing spaces with dashes.

{
  "name": "hello-world",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",

I’m going to simply replace “hello-world” with “roll-some-dice” and save and close the file.

{
  "name": "roll-some-dice",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",

In that same folder, is a file named package-lock.json.  We need to make the same edit to that file.  So:

{
  "name": "hello-world",
  "version": "1.0.0",
  "lockfileVersion": 1,

Becomes:

{
  "name": "roll-some-dice",
  "version": "1.0.0",
  "lockfileVersion": 1,

One More Thing Before We Can Code

In order to roll a dice, we need a random number generator.  This can be found in the node.js module named i18next.  We will also need the module named i18next-sprintf-postprocessor.  To get these, we will use the npm package manager.

On the left side of the VS Code screen, right click on the “custom” folder in the basic skill template and choose “Open in Terminal”:

snip_20181105201412

In the bottom right of the VS Code screen is the Terminal panel.  When you get to the command prompt:

snip_20181105202241

Type in the commands “npm install i18next” and then “npm install i18next-sprintf-postprocessor“:

snip_20181105203203

Once completed, you should have a couple of new folders in the “custom\node_modules” folder of your project:

snip_20181105203632

Finally, the Brains of the Operation (index.js)

Since we just added the modules above to the project, let’s also add them to index.js, then I’ll discuss what’s in there and what we need to do.

Include the i18next Modules in index.js

At the top of the index.js file, we need to include the i18next modules.  This is done by adding new constants for them below the Alexa constant, like so:

const Alexa = require('ask-sdk-core');
const i18n = require('i18next');
const sprintf = require('i18next-sprintf-postprocessor');

A Brief Tour of index.js

After the constants declared at the top of the file to include the required modules, there are several “Handler” functions.  The first is the LaunchRequestHandler:

const LaunchRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
  },
  handle(handlerInput) {
    const speechText = 'Welcome to the Alexa Skills Kit, you can say hello!';
    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(speechText)
      .withSimpleCard('Hello World', speechText)
      .getResponse();
  },
};

Each of the Handler functions handles one specific request from the user to Alexa.  In this case, it the LaunchRequestHandler can handle requests with a type of “LaunchRequest”.  When this Handler is fired, it builds a response that is sent back to the user.  This response includes some speech (what Alexa will say), a reprompt (what she will say to remind the user what to do, and a Card (to be displayed on the Echo Show and other devices with screens).

The other Handler functions are set up to handle the different intents of the skill:

  • HelloWorldIntentHandler  –  The main intent handler
  • HelpIntentHandler  –  Handles the case where the user asks Alexa for help
  • CancelAndStopIntentHandler  –  Handles Alexa, Stop and Alexa, Cancel\
  • SessionEndedRequestHandler  –  Handles the final request sent to the skill when the session ends
  • ErrorHandler  –  Handles any error situations

Next, we get to the lines that export the various Handlers so that the Alexa SkillBuilder knows which functions to call:

const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
  .addRequestHandlers(
    LaunchRequestHandler,
    HelloWorldIntentHandler,
    HelpIntentHandler,
    CancelAndStopIntentHandler,
    SessionEndedRequestHandler
  )
  .addErrorHandlers(ErrorHandler)
  .lambda();

What We Need to Change

First, we will change the LaunchRequestHandler, as shown in bold, blue text below:

const LaunchRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
  },
  handle(handlerInput) {
    const speechText = 'Welcome to Roll Some Dice.  You can say, Roll 2 Dice, or Roll 4 Dice plus 1!';
    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(speechText)
      .withSimpleCard('Roll Some Dice', speechText)
      .getResponse();
  },
};

Next, we will fix the Card lines in all the other intents so that this:

.withSimpleCard('Hello World', speechText)

becomes:

.withSimpleCard('Roll Some Dice', speechText)

Next, we will change the Help Speech Text in the HelpIntentHandler to:

const speechText = 'You can say roll 2 dice, roll 3 dice plus 1, roll 6 dice minus 1 or any number of dice with any modifier.';

Next, we will completely change the HelloWorldIntentHandler.  We will do this in stages.  First, we need to change the name of the Handler and its corresponding entry in the SkillBuilder at the bottom of the file, like so:

const RollSomeDiceIntentHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === 'RollSomeDiceIntent';
  },
  handle(handlerInput) {
    var speechText = 'Hello World!';
    return handlerInput.responseBuilder
      .speak(speechText)
      .withSimpleCard('Roll Some Dice', speechText)
      .getResponse();
  },
};

...

const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
  .addRequestHandlers(
    LaunchRequestHandler,
    RollSomeDiceIntentHandler,
    HelpIntentHandler,
    CancelAndStopIntentHandler,
    SessionEndedRequestHandler
  )
  .addErrorHandlers(ErrorHandler)
  .lambda();

Now, we have a Handler for our Intent that doesn’t actually do what it needs to do.
But, we do have a Handler.  At this point, we can deploy and test our Skill.

Deploying Your Skill to Alexa Developer Console and Amazon Web Services

It turns out, that with the ASK in VS Code, deploying our Skill to Alexa and Amazon is quite easy.  Open the Command Palette (View | Command Palette…).  Type ASK.  Select Deploy the skill.

snip_20181106045852

Wait a moment while the ASK initializes, then select the default profile:

snip_20181106045953

Then select “All”:

snip_20181106050011

Now, it will try, and probably fail, to deploy. If it succeeds, great.  If it fails, you probably need to change the working directory in the Terminal window at the bottom right of VS Code.  This is done with the CD command, like so:

snip_20181106050219

Once you’ve changed the directory to the one with your skill in it, press the up arrow on the keyboard a couple of times to get the “ask deploy” command back.  Then press enter.

If all goes well, a few moments later, your skill will be deployed:

snip_20181106050943

Now  that your skill is deployed, we can switch over to the Alexa Developer Console to test it.  If you still have your template project open from earlier, click “Your Skills” in the top left corner.  Then you will see your newly deployed skill at the top of the list:

snip_20181106051315

Click the Edit link on the far right.  On the Build tab, you should see a little popup saying your build was successful:

snip_20181106051456

Click on the Test tab.  If it’s not enabled, enable testing for this skill:

snip_20181106051713

In the Alexa Simulator, type in “start Roll Some Dice and roll 2 dice”.  Press enter.

snip_20181106051938

Alexa should say, “Hello World”.  (Remember, we haven’t actually told her how to roll some dice yet.)

snip_20181106052130

Notice the JSON Output from your Skill code in index.js:

snip_20181106052146

And scroll down to see the Card visual that would be shown on the Echo Show:

snip_20181106052221

That’s it for now.  In the final post in this series, I will teach Alexa to roll dice with a modifier and report the results.

An Alexa Skill in Javascript – Part 3

The Skill Model (en-US.json)

Open the en-US.json file in the models folder.  Notice the areas I’ve highlighted in bold, red text.  These are things we will change.

{
  "interactionModel": {
    "languageModel": {
      "invocationName": "greeter",
      "types": [
      ],
      "intents": [
        {
          "name": "AMAZON.CancelIntent",
          "samples": [
          ]
        },
        {
          "name": "AMAZON.HelpIntent",
          "samples": [
          ]
        },
        {
          "name": "AMAZON.StopIntent",
          "samples": [
          ]
        },
        {
          "name": "HelloWorldIntent",
          "slots": [
          ],
          "samples": [
            "hello",
            "say hello",
            "say hello world"
          ]
        }
      ]
    }
  }
}

First, the invocation name.  This is the name by which users will invoke your skill and it should be the same as the name of the skill you put in the skill manifest.  In my case, in Part 2 I named the skill “Roll some dice”.  The invocation name has to follow these rules:

  1. Your invocation name should be two or more words
  2. Can contain only lower-case alphabetic characters, spaces between words, possessive apostrophes (for example, “sam’s science trivia”), or periods used in abbreviations (for example, “a. b. c.”).
  3. Other characters like numbers must be spelled out. For example, “twenty one”.
  4. Invocation names cannot contain any of the Alexa skill launch phrases.

I will enter the invocation name as “roll some dice”.

"invocationName": "roll some dice",

There are three AMAZON intents in the basic skill template.  Those are fine the way they are and should not be modified.

The meat of the skill model is your intent.  In the basic skill template, this is the HelloWorldIntent.  We will change this.

Using the Alexa Developer Console to build the JSON for an Intent

The easiest way to get the correct syntax for the Skill Intent is to use the Alexa Developer Console.

1.  Log in and click Create Skill.  Enter the name “My Template”. Pick Custom as the type.  On the next page, click Start from Scratch as the template.  You should end up here:

snip_20181103080102

2.  Next to Intents, click Add.  Intent name can only contain case-insensitive alphabetical characters and underscores, and it must begin and end with an alphabetic character. Numbers, spaces, or other special characters are not allowed.  I will name my intent “RollSomeDiceIntent”:

snip_20181105212919

3.  Next, you enter the sample utterances.  This is what the Alexa User needs to say to make your skill work.  In my case, I have entered four utterances:

snip_20181105212943

Notice how I used braces { } to create “slots” (or variables).  These slots are placeholders for where the user can say a matching word.  For example, “Roll 10 dice plus 1” matches the second utterance “roll {diceCount} dice {plusMinus} {modifier}“.

4.  Now we need to define the slot types for the slots we named in the utterances.  This is done at the bottom of the sample utterances page.  Scroll down a bit and you will see this:

snip_20181103081409

For the Slot Type, the first and third slot (diceCount and modifier) are both numeric, so pick AMAZON.Number from the drop down.  You can type AMAZON.N and it will show AMAZON.Number as the only choice if you want to save on scrolling.

For the other slot, plusMinus, we will want to make a custom slot type where it only responds to “plus” and “minus”.  Do this by clicking the Add button next to the Slot Type menu on the left side of the screen:

snip_20181103081624

Give your new slot a name.  Note:  You cannot use a period in your name.  Amazon can, but you can’t.  So use an underscore.  I will name my slot: OMWTM_PlusMinus:

snip_20181103082100

Next, enter the words that are valid in your slot.  For me, that is plus and minus.  I will also add the synonyms add and subtract, just in case the user gets creative.  Note: Make sure you click the plus sign next to the synonym so it actually gets saved into the slot.  The slot ends up looking like this:

snip_20181103082135

Finally, click on a the {plusMinus} slot in the left panel and select your custom slot type as the slot type:

snip_20181105213145

  1. Now we’ve defined the intent, with sample utterances and slots.  Next, we need to get the JSON for the intent and copy it over to the en-US.json model file in VS Code.  The JSON for your intent is in the Alexa console under the JSON Editor menu option on the left side:

snip_20181105213232

We want ONLY the custom intent and the slots, so scroll down past the AMAZON intents and find the section that defines your intent:

snip_20181105213354

Copy the highlighted section over to the model file in VS Code.  Note:  When you paste it in, you will be replacing the last braces of the intents section.  If you don’t, your JSON file won’t have the right number of braces.  I.e.  Delete the HelloWorldIntent in its entirety and delete the extra square brace below it that ends the set of intents:

snip_20181103084258

Also, the basic skill template inserts a blank types section at the top.  Delete this too:

snip_20181103084343

Now, back at the bottom of the file, paste in the copied text from the Alexa console:

snip_20181103085025

The finished intent model should look like this:

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "roll some dice",
            "intents": [{
                    "name": "AMAZON.CancelIntent",
                    "samples": [
                    ]
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": [

                    ]
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": [

                    ]
                },
                {
                    "name": "RollSomeDiceIntent",
                    "slots": [{
                            "name": "diceCount",
                            "type": "AMAZON.NUMBER"
                        },
                        {
                            "name": "plusMinus",
                            "type": "OMWTM_PlusMinus"
                        },
                        {
                            "name": "modifier",
                            "type": "AMAZON.NUMBER"
                        }
                    ],
                    "samples": [
                        "roll a die {plusMinus} {modifier}",
                        "roll {diceCount} dice {plusMinus} {modifier}",
                        "roll {diceCount} dice",
                        "roll a die"
                    ]
                }
            ],
            "types": [{
                "name": "OMWTM_PlusMinus",
                "values": [{
                        "name": {
                            "value": "minus",
                            "synonyms": [
                                "subtract"
                            ]
                        }
                    },
                    {
                        "name": {
                            "value": "plus",
                            "synonyms": [
                                "add"
                            ]
                        }
                    }
                ]
            }]
        }
    }
}

That’s it for now.  In the next post, we’ll start looking at the Lambda function files and what needs to be changed there to get this skill working.

Bye for now.

 

An Alexa Skill in JavaScript – Part 2

Now that we have the tools and a basic project, let’s see what the Alexa Skills Kit (ASK) has created for us.

snip_20181102043136What’s in the Basic Project?

The ASK Config file contains the info the ASK needs to publish your skill.

The lambda folder contains your JavaScript files that are the code behind your skill.  The node_modules folder contains the downloaded node modules you use.  index.js is the main code file for your skill.  package.json and package-lock.json are files that describe some of the technical aspects of your code, such as dependencies.

The models folder contains the various language versions of your Json skill description, including the intents and slots.

The skill.json file is the skill manifest and is where you describe the skill for your end users and the Amazon publishing process.

Where to Start?

In the image above, we’ll start at the bottom with the skill manifest, then the model, then a couple of minor changes to the package files, then we’ll write a couple of lines of JavaScript code and finally check the .ask\config.

The Skill Manifest (skill.json)

Open the skill.json file.  Notice the areas I’ve highlighted in bold, red text.  These are things we will change.

{
  "manifest": {
    "publishingInformation": {
      "locales": {
        "en-US": {
          "summary": "Sample Short Description",
          "examplePhrases": [
            "Alexa open hello world",
            "Alexa tell hello world hello",
            "Alexa ask hello world say hello"
          ],
          "name": "omwtm-roll-a-dice",
          "description": "Sample Full Description"
        }
      },
      "isAvailableWorldwide": true,
      "testingInstructions": "Sample Testing Instructions.",
      "category": "EDUCATION_AND_REFERENCE",
      "distributionCountries": []
    },
    "apis": {
      "custom": {
        "endpoint": {
          "sourceDir": "lambda/custom"
        }
      }
    },
    "manifestVersion": "1.0"
  }
}

The “summary” entry should be a short description of your skill, for example:

"summary": "Roll some dice, optionally adding a modifier to each die",

The “examplePhrases”: section contains 3, and only 3, sample phrases.  I’ll have two main intents:  “Roll {diceCount} dice” and “Roll {diceCount} dice {plusMinus} {modifier}”, so I want to show those in the example phrases.  For example:

"examplePhrases": [
    "Alexa open roll some dice",
    "Alexa tell roll some dice to roll 2 dice",
    "Alexa ask roll some dice to roll 3 dice plus 1"
],

The “name” entry should be the plain, human-readable, name of your skill that people see in the Alexa Skills Catalog.  Note:  This does not have to be unique in the Catalog.  For example:

"name": "Roll Some Dice",

The “description” entry should describe your skill.  This can be a paragraph or two and will also display in the Alexa Skills Catalog.  Notice the description is all on one line.  In VS Code, you can turn on Word Wrap (View | Toggle Word Wrap) to see the entire description on screen.  For example:

"description": "Roll Some Dice will roll any number of standard dice (d 6's) and optionally add or subtract a modifier from each dice.  Alexa will then tell you the total of the rolls plus or minus the modifiers.  For example, you might say 'Roll 3 dice plus 1' and Alexa will roll 3 d 6, getting, say, 3, 4, and 6, then add 1 to each roll, getting 4, 5, and 7, and will tell you the total, 16.",

“testingInstructions” is something we’ll come back to later.  This is the instructions for the Alexa Skill evaluators to follow to test your skill intents thoroughly.  For now, I’ll leave it as is.

Lastly, the “category” entry is used to classify your skill in the Alexa Skills Catalog.  For this skill, I will pick:

"category": "GAME_INFO_AND_ACCESSORY",

There are a couple of additional settings you will want to add to your skill, if appropriate.  After the “manifest” setting, add this code:

"manifestVersion": "1.0",
"permissions": [],
"privacyAndCompliance": {
    "allowsPurchases": false,
    "isExportCompliant": true,
    "containsAds": false,
    "isChildDirected": false,
    "usesPersonalInfo": false
}

So, the completed file looks like this for now:

{
    "manifest": {
        "publishingInformation": {
            "locales": {
                "en-US": {
                    "summary": "Roll some dice, optionally adding a modifier to each die",
                    "examplePhrases": [
                        "Alexa open roll some dice",
                        "Alexa tell roll some dice to roll 2 dice",
                        "Alexa ask roll some dice to roll 3 dice plus 1"
                    ],
                    "name": "Roll Some Dice",
                    "description": "Roll Some Dice will roll any number of standard dice (d 6's) and optionally add or subtract a modifier from each dice.  Alexa will then tell you the total of the rolls plus or minus the modifiers.  For example, you might say 'Roll 3 dice plus 1' and Alexa will roll 3 d 6, getting, say, 3, 4, and 6, then add 1 to each roll, getting 4, 5, and 7, and will tell you the total, 16."
                }
            },
            "isAvailableWorldwide": true,
            "testingInstructions": "Sample Testing Instructions.",
            "category": "GAME_INFO_AND_ACCESSORY",
            "distributionCountries": []
        },
        "apis": {
            "custom": {
                "endpoint": {
                    "sourceDir": "lambda/custom"
                }
            }
        },
        "manifestVersion": "1.0",
        "permissions": [],
        "privacyAndCompliance": {
            "allowsPurchases": false,
            "isExportCompliant": true,
            "containsAds": false,
            "isChildDirected": false,
            "usesPersonalInfo": false
        }
    }
}

Next up, the skill model, where you define your intents and slots.

Bye for now.

 

 

 

 

An Alexa Skill in JavaScript – Part 1

So I finally decided to stop fighting it…  Building Alexa Skills in C# is just difficult.  With the newly released Visual Studio Code plugin for Alexa ( ) the language of choice is JavaScript.  Ugh.  But, it turns out that Google is still my friend (even though the Google Home is a horrible platform for voice skill development).  A quick search turned up all sorts of free JavaScript training.  A few hours of interaction later and I’m a pro beginning to be barely capable in JavaScript.  So, what’s a Microsoft Developer to do to code an Alexa Skill?

Getting the Tools

Step 1 – From the command line (Start | cmd in Windows), run npm to install the ASK CLI:

npm install -g ask-cli

snip_20180915064344

This command takes 2-5 minutes to run and doesn’t appear to be doing anything while it’s running.

TIP:  It’s a good idea to run that npm command every month or so to get the latest version of the ASK-CLI.  It is updated quite frequently.

Step 2 – Install Git, if you haven’t already.

Step 2 – Install Visual Studio Code if you haven’t already.  (I recommend the 64-bit User version for Windows developers.)

Step 3 – In VS Code, select the Help | Welcome menu.  On the right-hand side, under Customize, under Tools and languages, install support for JavaScript.

Step 4 – In VS Code, select the View | Extensions menu.  Search for Alexa Skills Kit (currently – 09/15/18 – in beta).  Install it.

I think that’s all I had to do to get the tools.

Configuring for Alexa Skill Development

AWS Lambda Credentials

Since we will be using an AWS Lambda function as the back-end for our skill, we need to set up the credentials in AWS IAM.

Add a User.  Give the user a name.  Select Programmatic access.  Click Next.

snip_20181101181244

For this example, I’m going to Attach existing policies directly and select Administrator Access, but this is NOT best practice.  (I should create a user group that has the specific policies this account needs, but that’s a different blog entry.)  Click Next.

snip_20181101181336

Click Create User.

snip_20181101181404

Download the .csv.  Do this.

IMPORTANT:  This is the ONLY time you can Download the .csv, so do it now.

snip_20181101181516

Click Close.

Initialize ASK CLI

In VS Code, view the Command Palette (Ctrl-Shift-P) or select the View | Command Palette menu.  Enter:  ASK in the palette and choose the “ASK: Initialize / Configure the ASK CLI” option.

snip_20180915060653

Accept the default profile name.  Sign in to Amazon in the browser provided USING THE ACCOUNT YOU JUST CREATED ABOVE.  It should say “Profile [default] initialized successfully.”

snip_20180915072056

If not, go here for assistance.

Starting the Alexa Skill

Create a folder for Alexa Skills.

View the Command Palette (Ctrl-Shift-P) or select the View | Command Palette menu.

Enter:  ASK in the palette and choose the “ASK: Create a basic skill package” option.

snip_20181101174552

It should come back with an option to select your AWS profile.  Choose the profile you created above.  This profile needs to be linked to an IAM user who has the right to publish Lambda functions.  (Which is why I cheated above and gave it AdministratorAccess.)

snip_20180915071206

Now it will ask you to enter a skill name.  I’ll be calling mine “OMWTM Roll A Dice”.

snip_20181101174716

 

ASK will then create and run a command in the Terminal window at the bottom right of VS Code:

snip_20181101175829

Once it’s finished, VS Code will open a folder with your basic skill defined:

snip_20181101180914

In the next blog entry, we’ll go through the basic skill definition and customize it.

Bye for now.

Unit Testing an Alexa Skill in C# – Step 3a

In Step 3, we created the Lambda function that will provide the functionality of the Alexa Skill we defined in Step 1, we wired everything up and then we tested our Skill.  So far so good.  However, that’s an awful long way round to test the Skill Request and Response.  It would be nice if we could set up a unit test project and unit test our Lambda function without having to deploy it.

It turns out, we can.

When we created the Lambda function project in Step 3, we selected the AWS Lambda Project with Tests template.  So we already have a Tests project and a stubbed out xunit test.  (Note: Because we are using the .Net Core for our Lambda function, the normal Microsoft Unit Testing Framework doesn’t work (because it uses the full .Net platform) and so the AWS template uses xunit.)

The tricky part of Unit Testing our Lambda function is that we need to test them FunctionHandler method, which takes a SkillRequest and a Context as parameters:

public SkillResponse FunctionHandler(SkillRequest input, ILambdaContext ctx)

In order to Unit Test our simple GetTodaysDateIntent, we will need to set up a SkillRequest that names that Intent.  Like so:

using AlexaAPI;
using AlexaAPI.Request;
using AlexaAPI.Response;
using Amazon.Lambda.TestUtilities;
using System.Collections.Generic;
using Xunit;
var intent = new Intent();
intent.Name = "GetTodaysDateIntent";
intent.ConfirmationStatus = "NONE";
var request = new Request();
request.Intent = intent;
request.Locale = "en-US";
request.Type = AlexaConstants.IntentRequest;
var interfaces = new Dictionary<string, object>();
var device = new Device();
device.SupportedInterfaces = interfaces;
var sysObj = new SystemObject();
sysObj.Device = device;
var skillContext = new Context();
skillContext.System = sysObj;
var session = new Session();
var skillRequest = new SkillRequest();
skillRequest.Request = request;
skillRequest.Context = skillContext;
skillRequest.Session = session;

With that code to create the skillRequest, this line will create the Lambda Context:

var context = new TestLambdaContext();

Now we can create the Function instance:

var function = new MyAlexaSkill.Lambda.Function();

And then we can call the FunctionHandler method to test the Intent:

var result = function.FunctionHandler(skillRequest, context);

A few Assertions will make sure we got the response we are looking for:

Assert.NotNull(result);
Assert.NotNull(result.Response);
Assert.NotNull(result.Response.OutputSpeech);
 
Assert.Equal("<speak>Today's date is 5/15/2018 12:00:00 AM</speak>", 
    (result.Response.OutputSpeech as SsmlOutputSpeech).Ssml);

Putting it all together, we get this Unit Test:

[Fact]
public void TestGetTodaysDateIntent()
{
 
    var intent = new Intent();
    intent.Name = "GetTodaysDateIntent";
    intent.ConfirmationStatus = "NONE";
    var request = new Request();
    request.Intent = intent;
    request.Locale = "en-US";
    request.Type = AlexaConstants.IntentRequest;
    var interfaces = new Dictionary<string, object>();
    var device = new Device();
    device.SupportedInterfaces = interfaces;
    var sysObj = new SystemObject();
    sysObj.Device = device;
    var skillContext = new Context();
    skillContext.System = sysObj;
    var session = new Session();
    var skillRequest = new SkillRequest();
    skillRequest.Request = request;
    skillRequest.Context = skillContext;
    skillRequest.Session = session;
            
    var context = new TestLambdaContext();
 
    var function = new MyAlexaSkill.Lambda.Function();
 
    var result = function.FunctionHandler(skillRequest, context);
 
    Assert.NotNull(result);
    Assert.NotNull(result.Response);
    Assert.NotNull(result.Response.OutputSpeech);
 
    Assert.Equal("<speak>Today's date is 5/15/2018 12:00:00 AM</speak>", 
        (result.Response.OutputSpeech as SsmlOutputSpeech).Ssml);
}

And there you have it, a Unit Test to test a simple Alexa Skill Intent.