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.

View the skill ID from the skill list
View the skill ID from the skill list

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.

Copied to clipboard.

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();

Copied to clipboard.

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()

Copied to clipboard.

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());
    }

}


Copied to clipboard.

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 called StartNewGameIntent.
  • 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?

Alexa.Presentation.APL.*

Applies when you use the Alexa.Presentation.APL to send content to devices with screens such as an Echo Show.

Yes, when you use Alexa.Presentation.APL. See Alexa.Presentation.APL Interface Reference for possible requests your skill must handle.

AudioPlayer.*

Applies if you use the AudioPlayer interface to stream audio. Requests are sent to notify your skill about playback status.

Yes if you use AudioPlayer to stream long-form audio.

CanFulfillIntentRequest

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 IntentRequest. See Understand Name-free Interactions

Yes if you have enabled the CanFulfillIntentRequest option for the skill.

Connections.Response (purchaseResult)

Applies when you use Connections.SendRequest to start a purchase flow with in-skill purchasing (ISP).

Yes if you implement in-skill purchasing (ISP)

IntentRequest

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.

LaunchRequest

Sent when the user invokes the skill but does not provide a specific command. For example:

User: Alexa, open Daily Horoscopes

Yes.

Messaging

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.

PlaybackController.*

Applies if you use the AudioPlayer interface to stream audio. Requests are sent when the user interacts with the device using hardware buttons, such as a remote control.

Yes if you use AudioPlayer to stream audio.

SessionEndedRequest

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 is HelloWorld.
  • Dialog state data from the request, such as a handler responsible for any IntentRequest where the intent name is PlanMyTrip and the dialogState is IN_PROGRESS.
  • Specific slot values, such as a handler responsible for any IntentRequest where the intent name is OrderIntent, and the value of the drink 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.

Copied to clipboard.

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...
};

Copied to clipboard.

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

Copied to clipboard.

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...
}

Copied to clipboard.

In the JSON sent to the skill, the request type "LaunchRequest" is provided in the request.typeproperty. 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:

Copied to clipboard.

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();
  },
};

Copied to clipboard.

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

Copied to clipboard.

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();
    }
}

Copied to clipboard.

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

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:

Copied to clipboard.

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();
  }
};

Copied to clipboard.

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

Copied to clipboard.

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();
    }
}

Copied to clipboard.

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.

Copied to clipboard.

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();

Copied to clipboard.

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

Copied to clipboard.

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();
}

Copied to clipboard.

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.

Copied to clipboard.

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();
  }
}

Copied to clipboard.

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

Copied to clipboard.

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();
}

Copied to clipboard.

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 to false.
  • 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 the reprompt object.
    • To provide audio built with APL for audio, pass the Alexa.Presentation.APLA.RenderDocument directive in the directives array within the reprompt object.
    • You can provide both outputSpeech and the directive. Alexa speaks the speech first, then plays the audio.

This is the typical sequence of events when you ask Alexa to listen for the user's response:

  1. Alexa sends your skill an IntentRequest or LaunchRequest.
  2. Your skill responds with:
    • Text to speak in the outputSpeech object
    • shouldEndSession set to false
    • Reprompt text or audio in the reprompt object.
  3. 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.
  4. 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.

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.

Copied to clipboard.

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();
  }
};

Copied to clipboard.

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

Copied to clipboard.

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();
}    

Copied to clipboard.

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:

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.


Was this page helpful?

Last updated: Apr 04, 2024