Alexa Tutorial 2016
Learn how to create an Alexa skill! Follow this simple Alexa skill tutorial to build, test and launch your own Alexa skill. This Alexa skill guide is great for beginners and seasoned developers alike. Get started for free today!
Dec 15, 2018 • 12 Minute Read
Important information about how Alexa works. - WORK IN PROGRESS!
Alexa is based on a question->response similar to Siri and Google Now services.
To create a skill we will need to Create an Alexa skill to capture the request like "Alexa, Ask HackGuides what time is it?"
This will then get translated from the Alexa Skill API into a method call into the Amazon AWS Lambda Services that is is then sent back to the user through the Alexa Skill.
Lets get started
To create a skill you will need to create for developer.amazon.com::
Now that you have an account you can begin to Add a new Skill:
Skill Information
- Update the Name with "Hack Guides SKill Demo"
- Update the Invocation Name with "code hack" (so it's easy to pronounce)
Interaction Model
Back to "Configuration" in Alexa SKill Kit
Test
{
"intents": [
{
"intent": "GetChoresIntent",
"slots": [
{
"name": "firstName",
"type" : "AMAZON.US_FIRST_NAME"
}
]
},
{
"intent": "AMAZON.HelpIntent"
},
{
"intent": "AMAZON.StopIntent"
},
{
"intent": "AMAZON.CancelIntent"
}
]
}
GetChoresIntent what chore is for {firstName}
GetChoresIntent {firstName} needs a chore
GetChoresIntent give me a chore for {firstName}
Configuration
- First we need to create a Lambda Expression before filling out this part
Navigate to this website and create the necessary account Lambda Expression Website
Select Blueprint
Configure event sources
Configure Function
You will probably need to create a new Role so click to "Create new role".
Review
In the top right corner of your Lambda Function you will now have a ARN that provides the connction for Alexa Skill.
// Route the incoming request based on type (LaunchRequest, IntentRequest,
// etc.) The JSON body of the request is provided in the event parameter.
exports.handler = function (event, context) {
try {
console.log("event.session.application.applicationId=" + event.session.application.applicationId);
/**
* Uncomment this if statement and populate with your skill's application ID to
* prevent someone else from configuring a skill that sends requests to this function.
*/
/*
if (event.session.application.applicationId !== "amzn1.echo-sdk-ams.app.[unique-value-here]") {
context.fail("Invalid Application ID");
}
*/
if (event.session.new) {
onSessionStarted({requestId: event.request.requestId}, event.session);
}
if (event.request.type === "LaunchRequest") {
onLaunch(event.request,
event.session,
function callback(sessionAttributes, speechletResponse) {
context.succeed(buildResponse(sessionAttributes, speechletResponse));
});
} else if (event.request.type === "IntentRequest") {
onIntent(event.request,
event.session,
function callback(sessionAttributes, speechletResponse) {
context.succeed(buildResponse(sessionAttributes, speechletResponse));
});
} else if (event.request.type === "SessionEndedRequest") {
onSessionEnded(event.request, event.session);
context.succeed();
}
} catch (e) {
context.fail("Exception: " + e);
}
};
/**
* Called when the session starts.
*/
function onSessionStarted(sessionStartedRequest, session) {
console.log("onSessionStarted requestId=" + sessionStartedRequest.requestId +
", sessionId=" + session.sessionId);
}
/**
* Called when the user launches the skill without specifying what they want.
*/
function onLaunch(launchRequest, session, callback) {
console.log("onLaunch requestId=" + launchRequest.requestId +
", sessionId=" + session.sessionId);
// Dispatch to your skill's launch.
getWelcomeResponse(callback);
}
/**
* Called when the user specifies an intent for this skill.
*/
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 ("GetChoresIntent" === intentName) {
getChoreResponse(intent, session, callback);
} else if ("AMAZON.HelpIntent" === intentName) {
getWelcomeResponse(callback);
} else if ("AMAZON.StopIntent" === intentName || "AMAZON.CancelIntent" === intentName) {
handleSessionEndRequest(callback);
} else {
throw "Invalid intent";
}
}
/**
* Called when the user ends the session.
* Is not called when the skill returns shouldEndSession=true.
*/
function onSessionEnded(sessionEndedRequest, session) {
console.log("onSessionEnded requestId=" + sessionEndedRequest.requestId +
", sessionId=" + session.sessionId);
// Add cleanup logic here
}
// --------------- Functions that control the skill's behavior -----------------------
function getWelcomeResponse(callback) {
// If we wanted to initialize the session to have some attributes we could add those here.
var sessionAttributes = {};
var cardTitle = "Welcome";
var speechOutput = "Welcome to the Hack Guides demo. " +
"Please ask for a chore by saying: give me a chore for name";
var repromptText = "Please ask for a chore by saying: give me a chore for name";
var shouldEndSession = false;
callback(sessionAttributes,
buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
function handleSessionEndRequest(callback) {
var cardTitle = "Session Ended";
var speechOutput = "Thank you for trying the Hack Guides demo. Have an Amazon day!";
// Setting this to true ends the session and exits the skill.
var shouldEndSession = true;
callback({}, buildSpeechletResponse(cardTitle, speechOutput, null, shouldEndSession));
}
/**
* Sets the color in the session and prepares the speech to reply to the user.
*/
function getChoreResponse(intent, session, callback) {
var cardTitle = intent.name;
var fistNameSlot = intent.slots.firstName;
var repromptText = "";
var sessionAttributes = {};
var shouldEndSession = false;
var speechOutput = "";
if (fistNameSlot) {
var miscResponses = [
'I think <break time="1s"/> {firstNameSlot} should work on Sweeping and moping!',
'I think {firstNameSlot} should work on <break time="1s"/> dishes!',
'{firstNameSlot}! should work on making their bed!',
'Maybe, nope definitely {firstNameSlot} should work on vacuuming the house',
'I think this time {firstNameSlot} should work on cleaning the toilets!',
'{firstNameSlot} should <break time="1s"/> work on clearing the table'
];
var firstNameValue = fistNameSlot.value;
var randomInt = getRandomInt(0, miscResponses.length - 1);
console.log(randomInt);
speechOutput = miscResponses[randomInt].replace(/{firstNameSlot}/g, firstNameValue);
repromptText = "Please ask for a chore by saying: give me a chore for name";
} else {
speechOutput = "I didn't catch that name you tell me again";
repromptText = "Please ask for a chore by saying: give me a chore for name";
}
callback(sessionAttributes,
buildSpeechletResponse(cardTitle, speechOutput, repromptText, shouldEndSession));
}
function getRandomInt(min, max) {
console.log("max:" + max + " min:" + min);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// --------------- Helpers that build all of the responses -----------------------
function buildSpeechletResponse(title, output, repromptText, shouldEndSession) {
return {
outputSpeech: {
type: "PlainText",
text: output
},
card: {
type: "Simple",
title: "SessionSpeechlet - " + title,
content: "SessionSpeechlet - " + output
},
reprompt: {
outputSpeech: {
type: "PlainText",
text: repromptText
}
},
shouldEndSession: shouldEndSession
};
}
function buildResponse(sessionAttributes, speechletResponse) {
return {
version: "1.0",
sessionAttributes: sessionAttributes,
response: speechletResponse
};
}
Test
Alexa has been made popular by the Amazon Echo, Amazon Tap, Amazon Dot, and now Pebble Core
QUICK URLS and ACCOUNTS NECCESSARY: