Handle Requests Sent by Alexa
When you create a custom skill, you create either an AWS Lambda function or a web service that can handle requests from Alexa. The code you write for this service needs to:
- Recognize each incoming request that Alexa sends
- Return an appropriate response
This document provides details and code examples that show how to process requests and return responses.
Verify that the request came from your skill
Before your web service or Lambda function accepts a request, verify that the request came from your skill. This prevents a malicious developer from configuring a skill with your endpoint and then using that skill to send requests to your service.
To do this validation, every request sent by Alexa includes a unique skill ID. You can check the skill ID in the request against your actual skill ID to ensure that the request was intended for your service.
Get the skill ID for your skill
You can find your Skill ID in the Alexa developer console. The ID for your skill is displayed in the developer console. To see your list of skills, sign in to the Alexa developer console. Each skill has a Copy Skill ID link below the name. Click to view and copy the ID.
The skill ID is also displayed on the Endpoint page, along with a Copy to Clipboard button.
Do skill ID verification in code
The Alexa Skills Kit SDKs can automatically handle the skill ID verification when you provide your skill ID as shown in the following example. If you do not use the SDK, get the ID from the JSON request and do the comparison in your own code.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
To verify your skill ID in code, pass the skill ID to the SkillBuilder.withSkillId
method when you configure your skill instance. In this example, the code rejects any requests where the skill ID does not match "amzn1.ask.skill.1"
.
const skillBuilder = Alexa.SkillBuilders.custom();
exports.handler = skillBuilder
.withSkillId("amzn1.ask.skill.1")
.addRequestHandlers(
HelloWorldIntentHandler,
LaunchRequestHandler,
HelpIntentHandler,
CancelAndStopIntentHandler,
SessionEndedRequestHandler,
)
.addErrorHandlers(ErrorHandler)
.addRequestInterceptors(LoggingRequestInterceptor)
.addResponseInterceptors(LoggingResponseInterceptor)
.lambda();
This code example uses the Alexa Skills Kit SDK for Python.
To verify your skill ID in code, set the skill_id
attribute on the SkillBuilder
object when you configure your skill instance. In this example, the code rejects any requests where the skill ID does not match "amzn1.ask.skill.1"
.
from ask_sdk_core.skill_builder import SkillBuilder
sb = SkillBuilder()
# Set the skill id
sb.skill_id = "amzn.ask.skill.1"
# Add all request handlers to the skill.
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_request_handler(FallbackIntentHandler())
# Add exception handler to the skill.
sb.add_exception_handler(CatchAllExceptionHandler())
# Add log request interceptor to the skill.
sb.add_global_request_interceptor(LogRequestInterceptor())
# Add log response interceptor to the skill.
sb.add_global_request_interceptor(LogResponseInterceptor())
# Expose the lambda handler to register in AWS Lambda.
lambda_handler = sb.lambda_handler()
This code example uses the Alexa Skills Kit SDK for Java.
To verify your skill ID in code, pass the skill ID to the SkillBuilder.withSkillId
method when you configure your skill instance. In this example, the code rejects any requests where the skill ID does not match "amzn1.ask.skill.1"
.
import com.amazon.ask.Skill;
import com.amazon.ask.SkillStreamHandler;
import com.amazon.ask.Skills;
import handlers.*;
import interceptors.*;
public class HandleReqCodeSamplesStreamHandler extends SkillStreamHandler {
private static Skill getSkill() {
return Skills.standard()
.withSkillId("amzn1.ask.skill.1")
.addRequestHandlers(
new HelloWorldIntentHandler(),
new LaunchRequestHandler(),
new HelpIntentHandler(),
new CancelandStopIntentHandler(),
new SessionEndedRequestHandler(),
new FallbackIntentHandler())
.addRequestInterceptors(
new LogRequestInterceptor()
)
.addResponseInterceptors(
new LogResponseInterceptor()
)
.build();
}
public HandleReqCodeSamplesStreamHandler() {
super(getSkill());
}
}
You can access the skill ID in the incoming request in the context.System.application.applicationId
property. The value is also available within the session
object, but not all incoming requests include session
, while they all have context
.
In this example, the skill ID is amzn1.ask.skill.1
. For brevity, the request
object is not shown in this example.
{
"version": "1.0",
"context": {
"AudioPlayer": {
"playerActivity": "IDLE"
},
"System": {
"application": {
"applicationId": "amzn1.ask.skill.1"
},
"user": {
"userId": "amzn1.ask.account.1"
},
"device": {
"supportedInterfaces": {
"AudioPlayer": {}
}
}
}
},
"session": {
"new": true,
"sessionId": "amzn1.echo-api.session.1",
"application": {
"applicationId": "amzn1.ask.skill.1"
},
"user": {
"userId": "amzn1.ask.account.1"
},
"attributes": {}
},
"request": {}
}
Types of requests your skill needs to handle
Alexa sends your skill different types of requests. A request represents one of the following:
- Something the user wants to do. For example, for a game skill, the user might want to start a new game. This could be represented to your skill as an
IntentRequest
calledStartNewGameIntent
. - An event sent by Alexa instead of the user. For example, an
AudioPlayer.PlaybackStarted
request notifies your skill that Alexa has begun playing an audio stream that your skill initiated.
Your skill needs to provide a valid response to all requests it receives.
About requests and request types
A request sent to a custom skill includes a request
object that provides the type
and other details about the request. For example, your skill receives a LaunchRequest
when a user invokes your skill without asking your skill to do anything specific. The JSON for this request looks like this (for brevity, this example does not show the full session
and context
objects). Note that the type
is set to the request type LaunchRequest
.
{
"version": "1.0",
"request": {
"type": "LaunchRequest",
"requestId": "amzn1.echo-api.request.1",
"timestamp": "2016-10-27T18:21:44Z",
"locale": "en-US"
},
"session": {},
"context": {}
}
Possible request types
You need to handle the request types for the features or interfaces that your skill uses. The following table summarizes the request types and indicates when you need to handle them.
Request type | Description | Required to handle? |
---|---|---|
Applies when you use the |
Yes, when you use |
|
Applies if you use the |
Yes if you use |
|
Sent when a user makes a request that could potentially be handled by your skill. Alexa sends this request to ask your skill if it can understand and fulfill the intent request with detected slots, before actually asking the skill to take action via a normal |
Yes if you have enabled the CanFulfillIntentRequest option for the skill. |
|
Applies when you use |
Yes if you implement in-skill purchasing (ISP) |
|
Sent when the user speaks a command that maps to one of your intents. The request includes the name of the intent. |
Yes. Your skill must handle each possible intent defined in your interaction model. |
|
Sent when the user invokes the skill but does not provide a specific command. For example: |
Yes. |
|
Handle messages sent to your skill out-of-session. |
Yes, if you expect out-of-session requests, such as skill events or the Skill Messaging REST API. |
|
Applies if you use the |
Yes if you use |
|
Sent when the skill's currently open session is closed because the user exited the skill, the user provided a response your skill can't understand, or an error occurs. |
Yes. |
About request handlers
A request handler is the code responsible for taking action on one or more types of incoming requests.
When you use the Alexa Skills Kit SDKs, you can define these handlers by implementing the RequestHandler
interface. The SDK then automatically routes an incoming request to the correct handler. If you do not use the SDK, you need to code the logic to inspect the incoming request and route it to the correct handler yourself.
Identify the requests the handler can handle
Each request handler needs to identify the requests it can handle. The criteria for a given handler depends on the design and functionality of your skill. It may make sense to write a handler that processes different types of requests if the responses to those requests can share code. Common criteria for handlers include:
- The request type, such as a handler responsible just for requests where the type is
LaunchRequest
. - Additional data from the request, such as as a handler responsible for any
IntentRequest
where the intent name isHelloWorld
. - Dialog state data from the request, such as a handler responsible for any
IntentRequest
where the intent name isPlanMyTrip
and thedialogState
isIN_PROGRESS
. - Specific slot values, such as a handler responsible for any
IntentRequest
where the intent name isOrderIntent
, and the value of thedrink
slot is "coffee". - Other skill state data, such as the value of particular session attributes.
- Any other criteria you can derive from the data in the request.
With the Alexa Skills Kit SDK, you implement a canHandle
method to identify the requests a particular handler can handle. The following example illustrates how you define a simple handler based on the request type.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
This example defines a request handler called LaunchRequestHandler
. The canHandle
method returns true
if the request type is LaunchRequest
.
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
// additional methods for this handler...
};
This code example uses the Alexa Skills Kit SDK for Python.
This example defines a request handler called LaunchRequestHandler
. The canHandle
method returns true
if the request type is LaunchRequest
. The Python SDK provides the utils
class with utility functions to simplify evaluating the incoming request.
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_request_type
class LaunchRequestHandler(AbstractRequestHandler):
"""Handler for skill launch."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_request_type("LaunchRequest")(handler_input)
# Additional methods for this handler
This code example uses the Alexa Skills Kit SDK for Java.
This example defines a request handler called LaunchRequestHandler
. The canHandle
method returns true
if the request type is LaunchRequest
. The Java SDK provides a Predicates
class with static methods to simplify evaluating the incoming request.
package handlers;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.LaunchRequest;
import com.amazon.ask.model.Response;
import java.util.Optional;
import static com.amazon.ask.request.Predicates.requestType;
public class LaunchRequestHandler implements RequestHandler {
@Override
public boolean canHandle(HandlerInput input) {
return input.matches(requestType(LaunchRequest.class));
}
// additional methods for this handler...
}
In the JSON sent to the skill, the request type "LaunchRequest"
is provided in the request.type
property. Your code needs to retrieve this value, evaluate the type, and route the request to an appropriate handler.
{
"version": "1.0",
"request": {
"type": "LaunchRequest",
"requestId": "amzn1.echo-api.request.1",
"timestamp": "2016-10-27T18:21:44Z",
"locale": "en-US"
},
"session": {},
"context": {}
}
Intent handlers are usually the most complex handlers for a skill. See Handle your intents and slots, later, for more details.
Process the request and return a response
Once your skill routes an incoming request to a particular request handler, it is up to that handler to process the request and return a response. Your code here can be whatever your skill needs, such as:
- Analyze the data provided in the user request to determine the right response.
- Ask the user for more information as part of a back-and-forth dialog.
- Call other Alexa REST APIs to get information about the user or perform other functions. Some examples:
- Use the Device Settings API to get the address configured for the device, customer's time zone, and other settings.
- Call the Reminders API to create and update reminders for the user.
- Call other APIs to get the information to fulfill the request. For example, the handler might call a weather service API to get a forecast, or call a flight tracking API to look up flights.
Most handlers return text that Alexa then speaks to the user. Some handlers need to return more specialized responses. For instance, a handler for CanFulfillIntentRequest
needs to return a very specific request format to indicate whether the skill can accept the user request. A handler for incomplete dialogs might return the Dialog.Delegate
directive to delegate the dialog to Alexa.
When you use the Alexa Skills Kit SDKs, you implement a handle
method to process the request and return the result. The handle
method is passed a HandlerInput
object, which contains the complete JSON request sent to your skill. Use this to access the data in the request.
In this example, the handler just tells Alexa to speak a simple welcome message and display a simple card in the Alexa app:
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
The HandlerInput.responseBuilder
method returns a ResponseBuilder
object. Use the methods on this object to create a response with the text to speak and the card to display.
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();
},
};
This code example uses the Alexa Skills Kit SDK for Python.
The handler_input.response_builder
method returns a ResponseFactory
object. Use the methods on this object to create a response with the text to speak and the card to display.
from ask_sdk_core.skill_builder import SkillBuilder
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_request_type
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model.ui import SimpleCard
from ask_sdk_model import Response
class LaunchRequestHandler(AbstractRequestHandler):
"""Handler for Skill Launch."""
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).ask(
"Go ahead and say hello to me!").set_card(
SimpleCard("Hello World", speech_text))
return handler_input.response_builder.response
This code example uses the Alexa Skills Kit SDK for Java.
The HandlerInput.getResponseBuilder()
method returns a ResponseBuilder
object. Use the methods on this object to create a response with the text to speak and the card to display.
package handlers;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.RequestHandler;
import com.amazon.ask.model.LaunchRequest;
import com.amazon.ask.model.Response;
import java.util.Optional;
import static com.amazon.ask.request.Predicates.requestType;
public class LaunchRequestHandler implements RequestHandler {
@Override
public boolean canHandle(HandlerInput input) {
return input.matches(requestType(LaunchRequest.class));
}
@Override
public Optional<Response> handle(HandlerInput input) {
String speechText = "Welcome to the Alexa Skills Kit, you can say hello";
return input.getResponseBuilder()
.withSpeech(speechText)
.withReprompt("Go ahead and say hello to me!")
.build();
}
}
The JSON your skill returns specifies the text Alexa speaks in the response.outputSpeech
property.
{
"response": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>Welcome to the Alexa Skills Kit, you can say hello</speak>"
},
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>Go ahead and say hello to me!</speak>"
}
},
"shouldEndSession": false
},
"version": "1.0",
"sessionAttributes": {}
}
For more about returning responses, see Return a response, later.
Handle your intents and slots
An intent represents the action the user wants to take. You define your intents when you build your interaction model. When a user invokes an intent, the request sent to your skill includes an IntentRequest
with information about the intent:
{
"version": "1.0",
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.1",
"timestamp": "2019-03-21T22:32:09Z",
"locale": "en-US",
"intent": {
"name": "HelloWorldWithNameIntent",
"confirmationStatus": "NONE",
"slots": {
"firstName": {
"name": "firstName",
"value": "Emily",
"confirmationStatus": "NONE"
},
"favoriteColor": {
"name": "favoriteColor",
"confirmationStatus": "NONE"
}
}
},
"dialogState": "STARTED"
},
"session": {},
"context": {}
}
Your skill must handle all of the intents defined in your interaction model. This is typically done with a handler for each intent, although you can create a handler that is used for multiple intents. Refer back to Identify the requests the handler can handle.
See the following sections:
- Get slot values from the request
- Use slot value resolutions
- Use a dialog to collect slot values
- Send a progressive response
Get slot values from the request
An intent can include one more more slots. A slot lets you get variable information from the user, such as the name of a city or a specific date. Slot values often represent critical information you need to fulfill the user's request. For example, a PlanMyTrip
intent needs to know the user's starting city, destination city, and travel date in order to look up flights.
All of the slots you defined for an intent in your interaction model are included in the IntentRequest
in the request.intent.slots
property. The slots
property is a map of key/value pairs where the slot name is the key, and the value is a Slot
object. At a minimum, the Slot
object in the request includes a name
property. The value
property is not present if the user did not provide a value for the slot.
The Alexa Skills Kit SDKs provides utility and helper functions to retrieve slot values more directly, as shown in the following example:
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
This handler uses functions provided with the RequestEnvelopeUtils
to retrieve a slot value. You can also access slots via the intent
object within the request. This is useful if you need data from the slot beyond just the value.
const {
getRequestType,
getIntentName,
getSlotValue,
getDialogState,
} = require('ask-sdk-core');
const HelloWorldWithNameIntentHandler = {
canHandle(handlerInput) {
return getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& getIntentName(handlerInput.requestEnvelope) === 'HelloWorldWithNameIntent';
},
handle(handlerInput) {
const firstNameValue = getSlotValue(handlerInput.requestEnvelope, 'firstName');
const speechText = firstNameValue
? `Hello, ${firstNameValue}!`
: `Hello World! I'm sorry, I don't yet know your name.`;
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
}
};
This code example uses the Alexa Skills Kit SDK for Python.
This handler uses the get_slot_value
method to retrieve a slot value. You can also use the get_slot
method if you want data beyond just the value.
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name, get_slot_value
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response
class HelloWorldIntentHandler(AbstractRequestHandler):
"""Handler for Hello World Intent."""
def can_handle(self, handler_input):
# type: (HandlerInput) -> bool
return is_intent_name("HelloWorldIntent")(handler_input)
def handle(self, handler_input):
# type: (HandlerInput) -> Response
# This handler greets the user by name if it is provided
# Otherwise just do a generic Hello World response
first_name_value = get_slot_value(
handler_input=handler_input, slot_name="firstName")
if first_name_value:
speech_text = "Hello, {}!".format(first_name_value)
else:
speech_text = "Hello World! I'm sorry, I don't yet know your name."
return handler_input.response_builder.speak(speech_text).response
This code example uses the Alexa Skills Kit SDK for Java.
This handler uses a RequestHelper
method to retrieve a slot value. You can also access slots via the Intent
object included in the request. This is useful if you need other data from the slot beyond just the value.
package handlers;
import static com.amazon.ask.request.Predicates.intentName;
import java.util.Optional;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.impl.IntentRequestHandler;
import com.amazon.ask.model.IntentRequest;
import com.amazon.ask.model.Response;
import com.amazon.ask.request.RequestHelper;
public class HelloWorldWithNameIntentHandler implements IntentRequestHandler {
// Since this handler only needs to handle IntentRequest requests, it implement
// the typed request handler interface (IntentRequestHandler) instead
// of the generic interface (RequestHandler). This eliminates the need to
// retrieve the request, check its type, and cast to the correct type.
@Override
public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
return handlerInput.matches(intentName("HelloWorldWithNameIntent"));
}
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
// This handler greets the user by name if it was provided, otherwise
// just do a generic Hello World response
RequestHelper requestHelper = RequestHelper.forHandlerInput(handlerInput);
// Use a helper method to get the slot value wrapped in an Optional.
Optional<String> firstNameValue = requestHelper.getSlotValue("firstName");
// Use the Optional.map() method to build different responses depending on
// whether the slot contained a value.
String speechText = firstNameValue.map(firstName -> "Hello, " + firstName + "!")
.orElse("Hello World! I'm sorry, I don't yet know your name.");
return handlerInput.getResponseBuilder()
.withSpeech(speechText)
.build();
}
}
The following example shows the JSON for a request with two slots. The slot firstName
has a value
property, while favoriteColor
does not. In this example, the user provided a value for the firstName
slot but left favoriteColor
empty.
{
"version": "1.0",
"session": {},
"context": {},
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.e8d12d6f-bb5b-48f2-8899-7cbbd764bf26",
"timestamp": "2019-02-07T21:21:06Z",
"locale": "en-US",
"intent": {
"name": "HelloWithNameIntent",
"slots": {
"firstName": {
"name": "firstName",
"value": "Sara",
"confirmationStatus": "NONE"
},
"favoriteColor": {
"name": "favoriteColor",
"confirmationStatus": "NONE"
}
},
"confirmationStatus": "NONE"
}
}
}
Use slot value resolutions
For a slot that supports entity resolution, the Slot
object includes a Resolutions
object. This object contains the results of entity resolution for the slot. When your custom slot type values include synonyms and unique identifiers, the entity resolution results can be very useful, as you can map multiple synonyms to a single ID that you then use as an enumeration in your code.
For details about entity resolution, see Entity Resolution.
Use a dialog to collect slot values
In many skills, you cannot expect users to provide all the required slot values in a single utterance. Instead, you may need to do a back-and-forth dialog to ask the user for the additional values. One way to do this is to configure a dialog model and then delegate the dialog to Alexa. This can simplify your code, as your intent handler can safely assume that the required slot values are filled with valid values.
For examples and details about delegating the dialog, see Delegate the Dialog to Alexa.
Send a progressive response
Your skill can call an Alexa API to send interstitial SSML content (including text-to-speech and short audio files) before returning a full response to the user's request. This is useful for skills that need to do intensive processing before constructing a full response.
For example, your skill could have an interaction like this:
User: Alexa, ask Ride Hailer to book a ride to the airport. (Normal IntentRequest
sent to the Ride Hailer skill.)
Additional back-and-forth to collect all the information needed to fulfill this intent.
Alexa: OK, please wait while I look up details for your ride… (Progressive response while the skill prepares the full response.)
Alexa: OK, I've reserved your ride. It should arrive at your home in thirty minutes. (Normal response to the IntentRequest
)
The progressive response can help keep users engaged while they wait for the full response.
To send a progressive response, call the Progressive Response API and send a directive
with the SSML or plain text Alexa should say to the user. You can send up to five directives to the Progressive Response API before returning your full response.
When you use the Progressive Response API, you handler makes an API call for the progressive response. You still need to return a final response to Alexa, just as for any other request.
For details, see Send the User a Progressive Response.
Return a response
After the handler for a particular request completes its processing, the handler sends a response back to Alexa. The response is a JSON structure that tells Alexa what to do. At a minimum, the response to the LaunchRequest
and IntentRequest
request types is usually a string of text that Alexa converts to speech and speaks to the user. Some skills send other information in the response, such as cards to display in the Alexa app, or directives to play audio or display information on a device with a screen. Some types of requests only allow specific types of responses.
When you use the Alexa Skills Kit SDKs, your handle
method returns the response for your skill. The SDKs provide a ResponseBuilder
object and helper methods to simplify building the JSON response format. For details about the full JSON response format, see Response Format.
Respond with speech and cards
A typical response includes text to convert to speech, and sometimes a card to display in the Alexa app. You provide these in the outputSpeech
and card
properties in the response. For more details about how to format your output speech, see Best Practices for Text Responses.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
Use the speak
and withSimpleCard
methods on the ResponseBuilder
object to define the speech and card text. The getResponse()
method returns the response with the specified properties.
return handlerInput.responseBuilder
.speak("This is the text Alexa speaks. Go to the Alexa app to see the card!")
.withSimpleCard(
"This is the Title of the Card",
"This is the card content. This card just has plain text content.\r\nThe content is formated with line breaks to improve readability.")
.getResponse();
This code example uses the Alexa Skills Kit SDK for Python.
Use the speak
and set_card
methods on the ResponseFactory
object to define the speech and the card text in the response.
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import 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 HelloWorldIntentHandler(AbstractRequestHandler):
"""Handler for Hello World Intent."""
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 = "This is the text Alexa speaks. Go to the Alexa app to see the card!"
card_title = "This is the Title of the Card"
card_text = "This is the card content. This card just has plain text content.\r\nThe content is formated with line breaks to improve readability."
return handler_input.response_builder.speak(speech_text).set_card(
SimpleCard(card_title, card_text)).response
This code example uses the Alexa Skills Kit SDK for Java.
Use the withSpeech()
and withSimpleCard
methods on the ResponseBuilder
object to define the speech and card text. The build()
method returns the response with the specified properties.
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
String speechText ="This is the text Alexa speaks. Go to the Alexa app to see the card!";
String cardTitle = "This is the Title of the Card";
String cardText = "This is the card content. This card just has plain text content.\r\nThe content is formated with line breaks to improve readability.";
return handlerInput.getResponseBuilder()
.withSpeech(speechText)
.withSimpleCard(cardTitle, cardText)
.build();
}
This JSON response shows how you return a simple plain text outputSpeech
string. The response also includes a card that displays a title and simple content.
{
"version": "1.0",
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "This is the text Alexa speaks. Go to the Alexa app to see the card!"
},
"card": {
"type": "Simple",
"title": "This is the Title of the Card",
"content": "This is the card content. This card just has plain text content.\r\nThe content is formated with line breaks to improve readability."
}
}
}
The outputSpeech
you provide can be in plain text format or Speech Synthesis Markup Language (SSML). SSML provides a standard way to mark up text for the generation of synthetic speech. You can use SSML tags to make Alexa play short sound effects, speak with emphasis, change pronunciation, and do other effects. The Alexa Skills Kit supports a subset of the tags defined in the SSML specification.
When you use SSML in the outputSpeech
, specify your text in the SSML
property, set the type
to SSML
, and wrap the text with the SSML markup in <speak>
tags. The Alexa Skills Kit SDKs do this automatically when you use the helper methods to set the outputSpeech
.
Be sure to escape the quotation marks ("
) used to surround SSML attributes.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
In this example, the speechText
string contains SSML tags to add emphasis to the word "hello" and then use the speechon "woo hoo." The speak
method automatically wraps the string with the <speak>
tags, sets the ssml
property, and sets the type
to SSML
.
const HelloSSMLResponseIntent = {
canHandle(handlerInput){
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloSSMLResponseIntent';
},
handle(handlerInput){
const speechText =
"<emphasis level=\"strong\">Hello</emphasis> World! " +
"<say-as interpret-as=\"interjection\">woo hoo</say-as>!";
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard("Hello World!", "Hello world (with enthusiasm!)")
.getResponse();
}
}
This code example uses the Alexa Skills Kit SDK for Python.
In this example, the speech_text
string contains SSML tags to add emphasis to the word "hello" and then use the speechon "woo hoo." The speak
method automatically wraps the string with the <speak>
tags, sets the ssml
property, and sets the type
to SSML
.
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response
class HelloWorldIntentHandler(AbstractRequestHandler):
"""Handler for Hello World Intent."""
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 = ('<emphasis level="strong">Hello</emphasis> World! '
'<say-as interpret-as="interjection">woo hoo</say-as>!')
return handler_input.response_builder.speak(speech_text).response
This code example uses the Alexa Skills Kit SDK for Java.
In this example, the speechText
string contains SSML tags to add emphasis to the word "hello" and then use the speechon "woo hoo." The withSpeech
method automatically wraps the string with the <speak>
tags, sets the ssml
property, and sets the type
to SSML
.
@Override
public Optional<Response> handle(HandlerInput handlerInput) {
String speechText =
"<emphasis level=\"strong\">Hello</emphasis> World! " +
"<say-as interpret-as=\"interjection\">woo hoo</say-as>!";
return handlerInput.getResponseBuilder()
.withSpeech(speechText)
.build();
}
In this JSON response, the text provided in the outputSpeech
string contains SSML tags to add emphasis to the word "hello" and then use the speechon "woo hoo." For SSML to render correctly, the type
property for the outputSpeech
must be set to SSML
, the text to speak is defined in the ssml
property, and the text is wrapped in <speak>
tags.
{
"version": "1.0",
"response": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak><emphasis level=\"strong\">Hello</emphasis> World! <say-as interpret-as=\"interjection\">woo hoo</say-as>!</speak>"
},
"card": {
"type": "Simple",
"title": "Hello World!",
"content": "Hello world (with enthusiasm!)"
}
}
}
Listen for the user's response and reprompt if necessary
In many skills, the response you return is not the end of the interaction. The skill needs to let the user say something in response, which becomes a new request sent to your skill. It is also common for a response to a LaunchRequest
to provide a brief welcome message and then ask the user what they would like to do. For example:
User: Open Spacey.
Alexa: Welcome to spacey. I know facts about space, how long it takes to travel between two planets and I even know a joke. What do you want to know?
Alexa is now listening for the user's response.
User: What's the weather like on Mars? (This response maps to the GetPlanetWeather
intent.)
Alexa: On Mars, you can expect high of 70 and low of minus 195 Fahrenheit. Sunny with a chance of sandstorms later in the day. (Response from the GetPlanetWeather
intent.)
To tell Alexa to listen for the user's response, do the following:
- Set the property
shouldEndSession
tofalse
. - Provide speech or audio in the
reprompt
property in your response. Alexa speaks this text or plays the provided audio if the user's response is not understood.- To provide text to speak, use the
outputSpeech
property in thereprompt
object. - To provide audio built with APL for audio, pass the
Alexa.Presentation.APLA.RenderDocument
directive in thedirectives
array within thereprompt
object. - You can provide both
outputSpeech
and the directive. Alexa speaks the speech first, then plays the audio.
- To provide text to speak, use the
This is the typical sequence of events when you ask Alexa to listen for the user's response:
- Alexa sends your skill an
IntentRequest
orLaunchRequest
. - Your skill responds with:
- Text to speak in the
outputSpeech
object shouldEndSession
set tofalse
- Reprompt text or audio in the
reprompt
object.
- Text to speak in the
- Alexa speaks the
outputSpeech
you provide, then opens the audio stream and listens for the user's response for a few seconds. On some devices, this means that the blue light ring lights up. - One of the following happens:
- The user says something that matches your interaction model, such as an utterance that maps to one of your intents. In this case, Alexa sends your skill a new request that represents the user's response, such as a new
IntentRequest
. The process begins again at step 1. - The user says nothing. In this case, Alexa prompts the user with your
reprompt
text or audio and re-opens the stream to listen for a few seconds again. - The user says something that doesn't match your interaction model. Again, Alexa prompts the user with your
reprompt
text or audio and re-opens the stream to listen for a few seconds again.
- The user says something that matches your interaction model, such as an utterance that maps to one of your intents. In this case, Alexa sends your skill a new request that represents the user's response, such as a new
Alexa speaks the reprompt just once. If the user's response is still not understood, the entire interaction ends:
User: Open Spacey.
Alexa: Welcome to spacey. I know facts about space, how long it takes to travel between two planets and I even know a joke. What do you want to know?
User: … (User says nothing.)
Alexa: Try asking me to tell you something about space.
User: Um…
Interaction ends.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
The reprompt
method on the ResponseBuilder
object sets the reprompt speech and sets shouldEndSession
to false
. This instructs Alexa to listen for the user's response.
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent';
},
handle(handlerInput) {
const speechText = `Welcome to Spacey. I know facts about space,
how long it takes to travel between two planets and I even
know a joke. What do you want to know?`;
const repromptText = 'Try asking me to tell you something about space.';
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(repromptText)
.getResponse();
}
};
This code example uses the Alexa Skills Kit SDK for Python.
The ask
method on the ResponseFactory
object sets the reprompt speech and sets shouldEndSession
to false
. This instructs Alexa to listen for the user's response.
from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response
class HelloWorldIntentHandler(AbstractRequestHandler):
"""Handler for Hello World Intent."""
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 = ("Welcome to Spacey. I know facts about space, "
"how long it takes to travel between two planets "
"and I even know a joke. What do you want to know?")
reprompt_text = "Try asking me to tell you something about space."
return handler_input.response_builder.speak(speech_text).ask(
reprompt_text).response
This code example uses the Alexa Skills Kit SDK for Java.
The withReprompt
method on the ResponseBuilder
object sets the reprompt speech and sets shouldEndSession
to false
. This instructs Alexa to listen for the user's response.
@Override
public Optional<Response> handle(HandlerInput handlerInput) {
String speechText = "Welcome to Spacey. I know facts about space, " +
"how long it takes to travel between two planets and I even " +
"know a joke. What do you want to know?";
String repromptText = "Try asking me to tell you something about space.";
return handlerInput.getResponseBuilder()
.withSpeech(speechText)
.withReprompt(repromptText)
.build();
}
In the JSON, set the reprompt
property to the text to use for the reprompt and set shouldEndSession
to false
. This instructs Alexa to listen for the user's response.
{
"version": "1.0",
"response": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>Welcome to spacey. I know facts about space, how long it takes to travel between two planets and I even know a joke. What do you want to know?</speak>"
},
"card": {
"type": "Simple",
"title": "Spacey Example",
"content": "Welcome to spacey. I know facts about space, how long it takes to travel between two planets and I even know a joke. What do you want to know?"
},
"reprompt": {
"outputSpeech": {
"type": "SSML",
"ssml": "<speak>Try asking me to tell you something about space.</speak>"
}
},
"shouldEndSession": false
}
}
During this back-and-forth conversation the skill session remains open. After the session closes, the interaction ends. For more details about the skill session, see Manage the Skill Session and Session Attributes.
Respond with directives
Your response can include directives to instruct Alexa to take other actions. Directives are organized into interfaces. For example, the AudioPlayer
interface contains directives for starting and stopping audio file playback. The type of a directive determines the properties you provide.
After you send a directive, your skill may receive requests specific to that interface. For example, after you start audio playback with AudioPlayer.Play
, your skill receives an AudioPlayer.PlaybackStarted
request to notify your skill that the playback began.
For details about available directives and corresponding responses, see the relevant interface reference:
- Alexa.Presentation.APL Interface
- Alexa.Presentation.APLT Interface
- Alexa.Presentation.HTML Interface
- AudioPlayer Interface
- Connections Interface
- Dialog Interface
- Messaging Interface
- PlaybackController Interface
- VideoApp Interface
To include a directive in your response, add the directive to the directives
array in your response. The Alexa Skills Kit SDKs provide helper methods to add directives to the response.
Handle input errors
Unlike a visual interface, a voice interface cannot prevent users from entering invalid data. In addition, misunderstandings when interpreting spoken language may introduce errors in slot values. Your code needs to check for these errors and handle them appropriately.
Custom Slot Type Values
For slots that are defined as custom slot types, it is possible to get values that are not part of the list of values defined for the type.
For example, a custom LIST_OF_SIGNS
slot type might define the twelve Zodiac signs. If the user says "what is the horoscope for blue", Alexa may send your service a request with the word "blue" in the Sign
slot. In this case, your code should test the Sign
value and give the user some indication that they did not provide a valid zodiac sign.
If you want your custom slot type to work more like an enumeration and only ever return values from a specific list, configure slot validation rules on the slot and then delegate the dialog. Alexa then prompts the user if they provide an invalid value.
Empty slot values
When an intent requires several slot values, you can let users provide the information in separate steps, rather than all in a single utterance. For example, a PlanMyTrip
intent has the slots fromCity
, toCity
, and travelDate
. It would be unreasonable to expect users to provide all three of those values in a single utterance, so you would likely define utterances like this:
{
"samples": [
"I want to travel from {fromCity} to {toCity} {travelDate}",
"i want to visit {toCity}",
"i am going on trip on {travelDate}",
"plan a trip starting from {fromCity}"
]
}
If a user says "I want to visit Chicago", the IntentRequest
sent to your skill includes objects for all three slots, but only the toCity
slot has a value. Both fromCity
and travelDate
have no value:
{
"request": {
"type": "IntentRequest",
"requestId": "amzn1.echo-api.request.1",
"timestamp": "2019-03-23T00:34:14Z",
"locale": "en-US",
"intent": {
"name": "PlanMyTrip",
"confirmationStatus": "NONE",
"slots": {
"toCity": {
"name": "toCity",
"value": "Chicago",
"confirmationStatus": "NONE"
},
"travelDate": {
"name": "travelDate",
"confirmationStatus": "NONE"
},
"fromCity": {
"name": "fromCity",
"confirmationStatus": "NONE"
}
}
},
"dialogState": "STARTED"
},
"version": "1.0",
"session": {},
"context": {}
}
Therefore, check for the slot values before you attempt to use them. The example shown earlier in Get slot values from the request illustrates checking that the values are non-null.
Alternatively, you can simplify collecting slot values with the Dialog
directives. See Delegate the Dialog to Alexa.
Related topics
- Manage the Skill Session and Session Attributes
- Delegate the Dialog to Alexa
- Request and Response JSON Reference
- Request Types Reference
Last updated: Apr 04, 2024