How To Build A Custom Amazon Alexa Skill with AWS Lambda as a backend.

Prasoon Singh
Analytics Vidhya
Published in
9 min readMar 29, 2020
Welcome to the Alexa Skills Kit, you can say hello!

Hello everyone, a came across developing this Alexa skill project for my company and was struggling to get a smooth head start so I write this blog so as to help others. Hope this helps you. :)

Setting Up the ASK SDK

This guide describes how to install the ASK SDK for Python in preparation for developing an Alexa skill. I have used the AWS lambda function for backend because you can debug here as compared to the Alexa developer console and lots of other cool things.

Prerequisites

The ASK SDK for Python requires Python 2 (>= 2.7) or Python 3 (>= 3.6). Before continuing, make sure you have a supported version of Python installed. To show the version, from a command prompt run the following command:

$ python --version
Python 3.6.5

Adding the ASK SDK for Python to Your Project

Many Python developers prefer to work in a virtual environment, so do I, so in this blog, I’ll proceed with that only. The virtual environment is an isolated Python environment that helps manage project dependencies and package versions. The easiest way to get started is to install the SDK in a virtual environment.

$ pip install virtualenv

Next, create a new folder for your Alexa skill and navigate to the folder:

$ mkdir skill
$ cd skill

Next, create a virtual environment called skill_env by issuing the following command:

$ virtualenv skill_env

Next, activate your virtual environment and install the SDK.

Run the following command to activate your virtual environment:

$ skill_env\Scripts\activate

The command prompt should now be prefixed with (skill_env), indicating that you are working inside the virtual environment. Use the following command to install the ASK Python SDK:

(skill_env)$ pip install ask-sdk

The SDK will be installed in the skill\Lib\site-packages folder. The site-packages folder is populated with directories including:

ask_sdk
ask_sdk_core
ask_sdk_dynamodb
ask_sdk_model
boto3
...

Developing Your First Skill

Prerequisites

In addition to an installed version of the ASK SDK for Python you need:

Creating Hello World

You’ll write your Hello World in a single python file named hello_world.py. In the skill the folder that you have created earlier, use your favorite text editor or IDE to create a file named hello_world.py.

Implementing Hello World

Request handlers

A custom skill needs to respond to events sent by the Alexa service. For instance, when you ask your Alexa device (e.g. Echo, Echo Dot, Echo Show, etc.) to “open hello world,” your skill needs to respond to the LaunchRequest that is sent to your Hello World skill. With the ASK SDK for Python, you simply need to write a request handler, which is code to handle incoming requests and return a response. Your code is responsible for making sure that the right request handler is used to process incoming requests and for providing a response.

Start by creating a skill builder object. The skill builder object helps in adding components responsible for handling input requests and generating custom responses for your skill.

Type or paste the following code into your hello_world.py file.

from ask_sdk_core.skill_builder import SkillBuildersb = SkillBuilder()

To use handler classes, each request handler is written as a class that implements two methods of the AbstractRequestHandler class; can_handle and handle.

The can_handle the method returns a Boolean value indicating if the request handler can create an appropriate response for the request. The can_handle method has access to the request type and additional attributes that the skill may have set in previous requests or even saved from a previous interaction. The Hello World skill only needs to reference the request information to decide if each handler can respond to an incoming request.

LaunchRequest handler

The following code example shows how to configure a handler to be invoked when the skill receives a LaunchRequest. The LaunchRequest event occurs when the skill is invoked without specific intent.

Type or paste the following code into your hello_world.py file, after the previous code.

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_request_type, is_intent_name
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response
from ask_sdk_model.ui import SimpleCard
class LaunchRequestHandler(AbstractRequestHandler):
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_request_type("LaunchRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speech_text = "Welcome to the Alexa Skills Kit, you can say hello!"
handler_input.response_builder.speak(speech_text).set_card(
SimpleCard("Hello World", speech_text)).set_should_end_session(
False)
return handler_input.response_builder.response

The can_handle function returns True if the incoming request is a LaunchRequest. The handle function generates and returns a basic greeting response.

HelloWorldIntent handler

The following code example shows how to configure a handler to be invoked when the skill receives an intent request with the name HelloWorldIntent. Type or paste the following code into your hello_world.py file, after the previous handler.

class HelloWorldIntentHandler(AbstractRequestHandler):
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_intent_name("HelloWorldIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speech_text = "Hello World"
handler_input.response_builder.speak(speech_text).set_card(
SimpleCard("Hello World", speech_text)).set_should_end_session(
True)
return handler_input.response_builder.response

The can_handle function detects if the incoming request is an IntentRequest, and returns True if the intent name is HelloWorldIntent. The handle function generates and returns a basic “Hello World” response.

HelpIntent handler

The following code example shows how to configure a handler to be invoked when the skill receives the built-in intent AMAZON.HelpIntent. Type or paste the following code into your hello_world.py file, after the previous handler.

class HelpIntentHandler(AbstractRequestHandler):
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_intent_name("AMAZON.HelpIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speech_text = "You can say hello to me!"
handler_input.response_builder.speak(speech_text).ask(speech_text).set_card(
SimpleCard("Hello World", speech_text))
return handler_input.response_builder.response

Similar to the previous handler, this handler matches an IntentRequest with the expected intent name. Basic help instructions are returned, and .ask(speech_text) causes the user's microphone to open up for the user to respond.

CancelAndStopIntent handler

The CancelAndStopIntentHandler is similar to the HelpIntent handler, as it is also triggered by the built-In AMAZON.CancelIntent or AMAZON.StopIntent Intents. The following example uses a single handler to respond to both intents. Type or paste the following code into your hello_world.py file, after the previous handler.

class CancelAndStopIntentHandler(AbstractRequestHandler):
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_intent_name("AMAZON.CancelIntent")(handler_input)
or is_intent_name("AMAZON.StopIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
speech_text = "Goodbye!"
handler_input.response_builder.speak(speech_text).set_card(
SimpleCard("Hello World", speech_text)).set_should_end_session(True)
return handler_input.response_builder.response

The response to both intents is the same, so having a single handler reduces repetitive code.

SessionEndedRequest handler

Although you cannot return a response with any speech, card or directives after receiving a SessionEndedRequest, the SessionEndedRequestHandler is a good place to put your cleanup logic. Type or paste the following code into your hello_world.py file, after the previous handler.

class SessionEndedRequestHandler(AbstractRequestHandler):
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_request_type("SessionEndedRequest")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
# any cleanup logic goes here
return handler_input.response_builder.response

Implementing exception handlers

The following sample adds a catch-all exception handler to your skill, to ensure the skill returns a meaningful message for all exceptions. Type or paste the following code into your hello_world.py file, after the previous handler.

from ask_sdk_core.dispatch_components import AbstractExceptionHandlerclass AllExceptionHandler(AbstractExceptionHandler):    def can_handle(self, handler_input, exception):
# type: (HandlerInput, Exception) -> bool
return True
def handle(self, handler_input, exception):
# type: (HandlerInput, Exception) -> Response
# Log the exception in CloudWatch Logs
print(exception)
speech = "Sorry, I didn't get it. Can you please say it again!!"
handler_input.response_builder.speak(speech).ask(speech)
return handler_input.response_builder.response

Creating the Lambda handler

The Lambda handler is the entry point for your AWS Lambda function. The following code example creates a Lambda handler function to route all inbound requests to your skill. The Lambda handler function creates an SDK skill instance configured with the request handlers that you just created. Type or paste the following code into your hello_world.py file, after the previous handler.

sb.add_request_handler(LaunchRequestHandler())
sb.add_request_handler(HelloWorldIntentHandler())
sb.add_request_handler(HelpIntentHandler())
sb.add_request_handler(CancelAndStopIntentHandler())
sb.add_request_handler(SessionEndedRequestHandler())
sb.add_exception_handler(AllExceptionHandler())handler = sb.lambda_handler()

Once you’ve created your AWS Lambda function, it’s time to give the Alexa service the ability to invoke it. To do this, navigate to the Triggers tabs in your Lambda’s configuration, and add Alexa Skills Kit as the trigger type. Once this is done, upload the skill.zip the file produced in the previous step and fill in the handler information with module_name.handler which is hello_world.handler for this example.

Configuring and testing your skill

Now that the skill code has been uploaded to AWS Lambda, you can configure the skill with Alexa.

  • Create a new skill by following these steps:
  1. Log in to the Alexa Skills Kit Developer Console.
  2. Click the Create Skill button in the upper right.
  3. Enter “mark1” as your skill name and click Next.
  4. For the model, select Custom and click Create skill.
Here the skill name is “mark1”.
  • Next, define the interaction model for the skill. Select the Invocation option from the sidebar and enter “greeter” for the Skill Invocation Name.
Invocation name “mark one”.
  • Next, add an intent called HelloWorldIntent to the interaction model. Click the Add button under the Intents section of the Interaction Model. Leave Create custom intent selected, enter HelloWorldIntent for the intent name, and create the intent. On the intent detail page, add some sample utterances that users can say to invoke the intent. For this example, consider the following sample utterances, and feel free to add others.
  • Since AMAZON.CancelIntent, AMAZON.HelpIntent, and AMAZON.StopIntent are built-in Alexa intents, you do not need to provide sample utterances for them.
  • Once you are done editing the interaction model, be sure to save and build the model.
  • Next, configure the endpoint for the skill. To do this, follow these steps:

Open the AWS Developer Console in a new tab.

Navigate to the AWS Lambda function created in the previous step.

From the Designer menu, add the Alexa Skills Kit trigger menu, and scroll down to paste the skill ID into the Skill ID Verification configuration. Click Add and save once completed to update the AWS Lambda function.

Copy the AWS Lambda function ARN from the top right corner of the page. An ARN is a unique resource number that helps Alexa service identify the AWS Lambda function it needs to call during skill invocation.

Navigate to the Alexa Skills Kit Developer Console, and click on your mark1 skill.

Under your skill, click Endpoint tab, select AWS Lambda ARN and paste in the ARN under Default Region field.

The rest of the settings can be left at their default values. Click Save Endpoints.

Click Invocation tab, save and build the model.

At this point, you can test the skill. In the top navigation, click Test. Make sure that the Test is enabled for this skill option is enabled. You can use the Test page to simulate requests, in text and voice form.

Use the invocation name along with one of the sample utterances as a guide. For example, tell greeters to say hello should result in your skill responding with “Hello World” voice and “Hello World” card on devices with a display. You can also open the Alexa app on your phone or at https://alexa.amazon.com and see your skills listed under Your Skills.

Feel free to start experimenting with your intents as well as the corresponding request handlers in your skill code. Once you’re finished iterating, optionally move on to getting your skill certified and published so it can be used by customers worldwide.

You can find the full code of the above here.

--

--

Analytics Vidhya
Analytics Vidhya

Published in Analytics Vidhya

Analytics Vidhya is a community of Generative AI and Data Science professionals. We are building the next-gen data science ecosystem https://www.analyticsvidhya.com