Alexa Skills Kit Tutorial: The Guide To Build Your Alexa Skill

Alexa Skills Kit Tutorial: The Guide To Build Your Alexa Skill

When Quentin told me about his project to publish a Skill for Anythings, I must admit that I was a bit scared. It returned out that building an Alexa Skill for Amazon Echo is not that hard. With this Alexa Skills Kit tutorial, I will give you the path and some hints to create your own Alexa Skill with Alexa Skills Kit. Feel free to comment with your questions if you get in trouble during your development phase.

Update: Make sure to try our new skill SMS With Molly. It lets you send free text messages to your friends and family.

Ideation Phase

This first phase is capital, you have to think about the conversation that your potential user will have with Alexa. What are the questions your skill will have to answer? Which data do you want to expose to users? Is this data fixed or dynamic? In other words can it be written directly in your code or will you have to pass requests and wait for response from your database?

Start writing on a sheet of paper the questions and then the answers that Alexa will say. 

Designing Your Requests

Your question can contain custom words that Alexa can recognize or pre-build group of words provided to you by the Amazon Team. For instance for our skill we needed to answer this question “What are the smart devices compatible with {Amazon Echo}” 

Here, Alexa should recognize the name of the product given by the user. We should give our skill a list of products that Alexa will pass to our code.

In order to make the life of the developer easier Amazon provides some preconfigured speech element. Alexa is specifically trained to recognize those words so that you will not have to give the list of all possible words.

For instance Alexa can recognize all the US Cities and pass it directly to your code. Those speech input data types are called “Slot Types”.

You can find a list of all the built-in slot types here.

Setup steps

First, you have to subscribe to the Amazon Developer ProgramIt is totally free contrary to the Apple developer program. On the front page go to the “Apps and Services” menu, and then just click on “Alexa Skills Kit” – the Get started button.

Then you will get access to a page that lists all the skills you have developed, you can add a new one by clicking on “Add a new Skill”.

On the next screen you will be asked for the basic information about your skill.

  • The name is the name of the Skill.
  • The invocation name is as important as the previous one. Amazon Echo‘s users will say this word to load your skill. In our case it’s “Anythings”. Amazon gives some guidelines about the choice of this. Of course two skills cannot have the same invocation name. But you might face also copyright infringement, if you choose a brand name… 
  • The version is an optional parameter. I suggest you use this versioning model: MAJOR#.MINOR#.PATCH#.
  • The endpoint is a crucial part. You have two choices build your own endpoint on your server or upload an Amazon Lambda Function. The first method will not be covered in this article, because it’s not the easiest way, as you would have to be sure that your system will have a very limited response time, in addition to that you would have to enable HTTP over SSL, accept requests on the 443 port… With the lambda function option you can benefit from a very good response time and an easy to use interface. What’s more, you can benefit from a code blueprint in NodeJS!

Configuring your skill: endpoint with a Lambda function

If you don’t have an Amazon Web Service Account, you will need to create one. It’s free for one year! Accept the conditions, and then go to the console by clicking on this link : https://console.aws.amazon.com/console/home?region=us-east-1

Next, You will have to click on the “Lambda” button:

IMPORTANT: select on the right in the navbar the “US East (N. Virginia)” option. Otherwise, your lambda function will not be able to response to Amazon Echo intents.

Click next on “Create a Lambda Function”. On the next screen you have several blueprints available. (A blueprint is a code model proposed by Amazon to make it easier for you to start).

On the filter input, just type “Alexa”.

Select “alexa-skills-kit-color-expert”  for nodejs. 

We chose this language but you have also the opportunity to choose the blueprint in python.

Then click next and check that the event source type is set to “Alexa Skills Kit”. It will fire your code in response to a user intent on the Amazon device.

Give it a name, and select “nodejs for the runtime.

Then you should enter the “Handler”. Let it set to “index.handler”. For the role, you will have to create a new one. Just select “Basic Execution Role” if it’s your first time with lambda functions. In my case I’ve set this new role before so I can select directly “lambda_basic_execution”.

The advanced setting are important, especially the timeout parameter. If you plan to connect to a database or to make some API requests you should increase its number to more than 3 seconds. Otherwise, your lambda function will end before all your code has been executed.

Click “Next” and on the following screen press the button “Create function”. 

You have two options:

  • If you need additional node modules, you will have to download your functions and edit them on your computer.
  • If you plan to serve just static content, you can edit it online directly on your web browser.

We will focus on the first method, because we need to connect to our database, hence I needed a node module.

Developing your Lambda function endpoint: set your environment

The first step is to copy paste the blueprint. Save it on a file named “index.js”. You should name your file exactly like the first part of the handler. If the handler parameter is set to “index.handler”, the file should be named “index.js”.
Put this file in a new folder on your computer. Install Nodejs if you don’t have it yet.
If you need to install a module, open Terminal on MAC or cmd.exe with Windows:

////

$ cd your_directory_name
$ npm install module_name

////

The last instruction will install your module and will create a “node_nodule” folder in your folder.

In our case, I had to install the “pg” module, to make a connection to a postgres database.

Just write at the beginning of your file the instruction to require your module:

var pg = require(‘pg’);

The handler: where the standard logic of the skill is

After that you will be able to use it in your code. Please note that you must make your connection before executing the rest of the code. If you do it asynchronously, your lambda function will finish its execution before the connection is established. This tip is valable for other steps that might take time to execute (an API request for instance or an intensive computation).

The first group of instruction inside ” exports.handler = function (event, context) { ”  and ” }; ” will route the incoming instruction send by Amazon Echo.

You have three major functions that will be executed depending on the request received:

  • onSessionStarted: it’s executed if the session is new.
  • onLaunch: this is executed if the user do not ask a specific question, this function redirects to another one « getWelcomeResponse ». This last function will fire the welcome message.
  • onIntent: this is executed if the user ask a question recognized by your skill. 

For each question you want Alexa to answer you have to define what is called an intent. This intent has a name that you have to define in the developper portal. We will set it later.

In our example we want to answer a single question “What are the best new smart devices ?”. Then we will have a single « intent » possibility. Here we have named this intent “GetBestNewSmartDevices“. As a consequence the onIntent function will look like that:

////

function onIntent(intentRequest, session, callback) {

    console.log(“onIntent requestId=” + intentRequest.requestId +

        “, sessionId=” + session.sessionId);

    var intent = intentRequest.intent,

        intentName = intentRequest.intent.name;

    // Dispatch to your skill’s intent handlers

    if (“GetBestNewSmartDevices” === intentName) {

        response_to_intent_GetBestNewSmartDevices(intent, session, callback);

    } else if (“AMAZON.HelpIntent” === intentName) {

        getWelcomeResponse(callback);

    } else {

        throw “Invalid intent”;

    }

////

Basically this code will get the intent name which is stored in “intentRequest.intent.name”. The code will just check for the function to execute on this request. In our case we have defined a new function response_to_intent_GetBestNewSmartDevices.

This function will have the standard parameters (intent, session, callback). In the variable intent we will find the word pronounced by the user, if you choose to set a question with a parameter.

Let’s see our function that will be execute on that simple intent:

////

function response_to_intent_GetBestNewSmartDevices (intent, session, callback)

{

    if (no_res_GetBestNewSmartDevices || no_db_con)

    { // If the request to get the answers for the intent GetBestNewSmartDevices has failed OR the databse connexion has failed

        var cardTitle = “Sorry, Something Wrong Occured”;

        var sessionAttributes = {};

        var repromptText = “”;

        var speechOutput = “”;

        var shouldEndSession = true;

        if (no_res_GetBestNewSmartDevices)

        {

            // If the request has failed or there is no result

            speechOutput = “I’m sorry the server of Anythings.co are overloaded. Please try again later”;

            speechOutput = “I’m sorry the server of Anythings.co are overloaded. Please try again later”;

        }

        else if  (no_db_con)

        {

            // IF the database connection could not be made

            speechOutput = “I’m sorry the server of Anythings.co are overloaded. Please try again later”;

            speechOutput = “I’m sorry the server of Anythings.co are overloaded. Please try again later”;

        } else

        {

            speechOutput = “I’m sorry the server of Anythings.co are overloaded. Please try again later”;

            speechOutput = “I’m sorry the server of Anythings.co are overloaded. Please try again later”;

        }

                callback(sessionAttributes,

             buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));

    }

    else

    { // If there is no error

        var cardTitle = “Top 3 IoT Devices”;

        var sessionAttributes = {};

        var repromptText=””;

        var speechOutput=””;

        var shouldEndSession = true;

        speechOutput = “The best three new smart devices today are: “+product1name+”, “+product1tagline+”. “+product2name+”, “+product2tagline+”. “+product3name+”, “+product3tagline+”. See you later on Anythings.co !”;

        

        

        repromptText = “The best three new smart devices today are: “+product1name+”, “+product1tagline+”. “+product2name+”, “+product2tagline+”. “+product3name+”, “+product3tagline+”. See you later on Anythings.co !”;

        callback(sessionAttributes,

             buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));

    }

}

////

Note that we have made the following instructions before this function is executed:

  • Connect to our database: if this step is successful the flag variable « no_db_con »  is set to its initial value: false. If there is a connection error it’s set to true. 
  • Make our request: if this step is successful the flag variable « no_res_GetBestNewSmartDevices »  is set to its initial value: false. if there is an error or no results it’s set to true. 

The defined flag enables us to have an answer in each case (even if we get no connection or no results to the request).

At the end of each case you will just define some variables:

 cardTitle: the title displayed on the Alexa App

 repromptText: this text will be read again if the user has made an error in its response to a question, or if he doesn’t answer.

 speechOutput: the text that Alexa has to read.

 shouldEndSession: this boolean attribute helps you to define if the skill should end or if you want to interact again with the user. If set to false, the skill will be ended.

Here we set error messages if something wrong occurred, else we construct our text by putting our dynamic text in the speechOutput variable.

Amazon has defined in this blueprint very useful helpers like the buildSpeechletResponse function. This function will send the response to the intent.

The blueprint is very well coded so basically you will have to make just single modification:

  • Add your intent on the onIntent function.
  • Define a specific function for each intent. This function will send the text to be read to the user.
  • Modify the getWelcomeResponse function to define the message you want to serve if no intent is made.

When your code is ready, zip it with the node_module folder and upload it on the AWS Lambda screen.

That’s all. But there are some more configuration to make before it can work.Configuration of the interaction model

Go back to your Alexa configuration screen.

On the endpoint input just paste the reference to the Lambda you just created. This reference starts with arn:aws:lambda:us-east-XXXXX. You can find it on the right corner of the Lambda configuration screen. This is the «  ARN » in the Amazon Terminology.

Click on the next button. You then have to define the interaction model.

The intent Schema: this is a JSON like variable that describes all the intent and give them a unique name. Those name will be transferred to your Lambda function in order to treat the request.

Here is our example:

{

  “intents”: [

    {

      “intent”: “GetWhatWorksWith”,

      “slots”: [

        {

          “name”: “Product”,

          “type”: “LIST_OF_PRODUCTS”

        }

      ]

    },

    {

      “intent”: “GetBestNewSmartDevices”

    }

  ]

}

We have defined 2 intents: GetWhatWorksWith and GetBestNewSmartDevices. The second one is the easier, there is no parameter (called slots in the Amazon terminology). It means that the question that the user ask contains no content that has to be transmitted to the code to make a proper answer.

The second one has a « slot » because the question that the user asks contains a parameter that has to be transmitted. 

We have defined a custom Slot type, « LIST_OF_PRODUCTS ». We also give it a name – it’s mandatory.

It’s pretty easy to define a custom slot. Just click on “Add Slot Type”, copy paste the name you have chosen before. In our case it is LIST_OF_PRODUCTS. And then enter the values – separated by line breaks – that should be recognized and pass to your code.  In our case a list of products.

Then you have to define the Sample Utterances. This is basically a list of sample questions. It helps the Amazon algorithm to recognize which question match with which intent.

For instance:

 GetBestNewSmartDevices what the best smart devices are

GetWhatWorksWith what works with {Product} 

Notice that you do not have to put the punctuation. You must here signal to the system the part of the question that will contain the variable parameter. ex: what pairs with {Product}. Here product is the parameter. Alexa will recognize it, will try to match what is said by the user with the list in the custom slot type, and then it will pass it. Note that if there is no match it will be pass “as it” to the code.

Common mistakes / tips 

Here is a list of the trouble I had during development. It might help you.

1. Asynchronous programming style: nodejs is not like PHP, your code will not wait for the execution of a specific instruction. Thus, you have to keep that in mind and execute asynchronously the connection instructions, or the long requests. Otherwise, your Lambda function will end before.

2. Timeout: Set properly the timeout parameter in order to give enough time to your lambda to execute.

3. If you upload your code on the lambda interface and you cannot execute it: check that your file name matches the handler parameter. Check that you have not forgotten the node_modules folder, otherwise Lambda will not find your modules.

4. Custom Slots are an interesting feature, but keep in mind that it should contain a limited number of occurrences (the limitation is 5.000). You should also be able to treat the parameter send to your code. In our case we have to delete this intent because Alexa recognized not well the product name, and it passes to the code wrong parameters. In order to make it work we tried to send a request to Algolia to match the product with what is given by Alexa. It was better than a full-text search in SQL but there was too much error… 

 

I hope that Alexa Skills Kit tutorial will help you save time building your own Alexa Skill. Don’t forget to share this post to the Skills builders you know. If you need some assistance, you can ask questions in the comment section I will be happy to help.

  • Ulichka Vsepoluchitsya

    Hello!
    Thanks for a good blog-post.
    Could you give me your email,please? Or another ways to contact with you? I think,that I have an interesting offer for you .
    Regards,Ulichka

  • polunzh

    I think you made a mistake: duplicate `speechOutput` assignment in the `if (no_res_GetBestNewSmartDevices)` clause.