Request Processing


Standard Request

Alexa communicates with the skill service via a request-response mechanism using HTTP over SSL/TLS. When a user interacts with an Alexa skill, your service receives a POST request containing a JSON body. The request body contains the parameters necessary for the service to perform its logic and generate a JSON-formatted response. The documentation on JSON structure of the request body can be found here.

Though Python can handle JSON natively as dict objects, for providing type support, they are deserialized into model objects (ask-sdk-model package) for skill consumption.

Handler Input

Request Handlers, Request and Response Interceptors, and Exception Handlers are all passed a global HandlerInput object during invocation. This object exposes various entities useful in request processing, including:

  • request_envelope: Contains the entire request body sent to skill, session information and some context information about the input request. Interface details: ask_sdk_model.request_envelope.RequestEnvelope
  • attributes_manager: Provides access to request, session, and persistent attributes. Interface details: ask_sdk_core.attributes_manager.AttributesManager
  • service_client_factory: Constructs service clients capable of calling Alexa APIs. Interface details: ask_sdk_model.services.service_client_factory.ServiceClientFactory
  • response_builder: Contains helper function to build responses. Interface details: ask_sdk_core.response_helper.ResponseFactory
  • context: Provides an optional, context object passed in by the host container. For example, for skills running on AWS Lambda, this is the context object for the AWS Lambda function.

Request Handlers

Request handlers are responsible for handling one or more types of incoming Alexa requests. There are two ways of creating custom request handlers:

  • By implementing the AbstractRequestHandler class.
  • By decorating a custom handle function using the Skill Builder request_handler decorator.

Interface

If you plan on using the AbstractRequestHandler class, you will need to implement the following methods:

  • can_handle: can_handle method is called by the SDK to determine if the given handler is capable of processing the incoming request. This function accepts a Handler Input object and expects a boolean to be returned. If the method returns True, then the handler is supposed to handle the request successfully. If it returns False, the handler is not supposed to handle the input request and hence not run to completion. Because of the various attributes in HandlerInput object, you can write any condition to let SDK know whether the request can be handled gracefully or not.
  • handle: handle method is called by the SDK when invoking the request handler. This function contains the handler's request processing logic, accepts Handler Input and returns a Response object.
class AbstractRequestHandler(object):
    @abstractmethod
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        pass

    @abstractmethod
    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
        pass

The request_handler decorator from SkillBuilder class is a custom wrapper on top of the AbstractRequestHandler class and provides the same functionality to any custom decorated function. However, there are couple of things to take into consideration, before using the decorator:

  • The decorator expects a can_handle_func parameter. This is similar to the can_handle method in AbstractRequestHandler. The value passed should be a function that accepts a Handler Input object and returns a boolean value.
  • The decorated function should accept only one parameter, which is the Handler Input object and may return a Response object.
class SkillBuilder(object):
    ....
    def request_handler(self, can_handle_func):
        def wrapper(handle_func):
            # wrap the can_handle and handle into a class
            # add the class into request handlers list
            ....
        return wrapper

Code Sample

The following example shows a request handler class that can handle the HelloWorldIntent.

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name
from ask_sdk_model.ui import SimpleCard

class HelloWorldIntentHandler(AbstractRequestHandler):
    def can_handle(self, handler_input):
        return is_intent_name("HelloWorldIntent")(handler_input)

    def handle(self, handler_input):
        speech_text = "Hello World";

        return handler_input.response_builder.speak(speech_text).set_card(
            SimpleCard("Hello World", speech_text)).response

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

from ask_sdk_core.utils import is_intent_name
from ask_sdk_model.ui import SimpleCard
from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

@sb.request_handler(can_handle_func = is_intent_name("HelloWorldIntent"))
def hello_world_intent_handler(handler_input):
    speech_text = "Hello World!"

    return handler_input.response_builder.speak(speech_text).set_card(
        SimpleCard("Hello World", speech_text)).response

The is_intent_name function accepts a string parameter and returns an anonymous function which accepts a HandlerInput as input parameter and checks if the incoming request in HandlerInput is an IntentRequest and returns if the intent name is the passed in string, which is HelloWorldIntent in this example. The handle function generates and returns a basic "Hello World" response.

Registering and Processing the Request Handlers

The SDK calls the can_handle function on its request handlers in the order in which they were provided to the Skill builder.

If you are following the AbstractRequestHandler class approach, then you can register the request handlers in the following way:

from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

# Implement FooHandler, BarHandler, BazHandler classes

sb.add_request_handler(FooHandler())
sb.add_request_handler(BarHandler())
sb.add_request_handler(BazHandler())

If you are following the request_handler decorator approach, then there is no need to explicitly register the handler functions, since they are already decorated using a skill builder instance.

from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

# decorate foo_handler, bar_handler, baz_handler functions

Exception Handlers

Exception handlers are similar to request handlers, but are instead responsible for handling one or more types of exceptions. They are invoked by the SDK when an unhandled exception is thrown during the course of request processing.

In addition to the Handler Input object, the handler also has access to the exception raised during handling the input request, thus making it easier for the handler to figure out how to handle the corresponding exception.

Similar to Request Handlers, exception handlers can be implemented in two ways:

  • By implementing the AbstractExceptionHandler class.
  • By decorating a custom exception handling function using the Skill Builder exception_handler decorator.

Interface

If you plan on using the AbstractExceptionHandler class, you will need to implement the following methods:

  • can_handle: can_handle method, which is called by the SDK to determine if the given handler is capable of handling the exception. This function returns True if the handler can handle the exception, or False if not. Return True in all cases to create a catch-all handler.
  • handle: handle method, which is called by the SDK when invoking the exception handler. This function contains all exception handling logic, and returns a Response object.
class AbstractExceptionHandler(object):
    @abstractmethod
    def can_handle(self, handler_input, exception):
        # type: (HandlerInput, Exception) -bool
        pass

    @abstractmethod
    def handle(self, handler_input, exception):
        # type: (HandlerInput, Exception) -Response
        pass

The exception_handler decorator from SkillBuilder class is a custom wrapper on top of the AbstractExceptionHandler class and provides the same functionality to any custom decorated function. However, there are couple of things to take into consideration, before using the decorator:

  • The decorator expects a can_handle_func parameter. This is similar to the can_handle method in AbstractExceptionHandler. The value passed should be a function that accepts a Handler Input object, an Exception instance and returns a boolean value.
  • The decorated function should accept only two parameters, the Handler Input object and Exception object. It may return a Response object.
class SkillBuilder(object):
    ....
    def exception_handler(self, can_handle_func):
        def wrapper(handle_func):
            # wrap the can_handle and handle into a class
            # add the class into exception handlers list
            ....
        return wrapper

Code Sample

The following example shows an exception handler that can handle any exception with name that contains "AskSdk".

class AskExceptionHandler(AbstractExceptionHandler):
    def can_handle(self, handler_input, exception):
        return 'AskSdk' in exception.__class__.__name__

    def handle(self, handler_input, exception):
        speech_text = "Sorry, I am unable to figure out what to do. Try again later!!"

        return handler_input.response_builder.speak(speech_text).response

The handler's can_handle method returns True if the incoming exception has a name that starts with "AskSdk". The handle method returns a graceful exception response to the user.

from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

@sb.exception_handler(can_handle_func = lambda i, e: 'AskSdk' in e.__class__.__name__)
def ask_exception_intent_handler(handler_input, exception):
    speech_text = "Sorry, I am unable to figure out what to do. Try again later!!"

    return handler_input.response_builder.speak(speech_text).response

Registering and Processing the Exception Handlers

from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

# Implement FooExceptionHandler, BarExceptionHandler, BazExceptionHandler classes

sb.add_exception_handler(FooExceptionHandler())
sb.add_exception_handler(BarExceptionHandler())
sb.add_exception_handler(BazExceptionHandler())
from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

# decorate foo_exception_handler, bar_exception_handler, baz_exception_handler functions

Request and Response Interceptors

The SDK supports Global Request and Response Interceptors that run before and after the matching RequestHandler, respectively.

Request Interceptors

The Global Request Interceptor accepts a Handler Input object and processes it, before processing any of the registered request handlers. Similar to Request Handlers, custom request interceptors can be implemented in two ways:

  • By implementing the AbstractRequestInterceptor class.
  • By decorating a custom process function using the Skill Builder global_request_interceptor decorator.

Interface

The AbstractRequestInterceptor class usage needs you to implement the process method. This method takes a Handler Input instance and doesn't return anything.

class AbstractRequestInterceptor(object):
    @abstractmethod
    def process(self, handler_input):
        # type: (HandlerInput) -None
        pass

The global_request_interceptor decorator from SkillBuilder class is a custom wrapper on top of the AbstractRequestInterceptor class and provides the same functionality to any custom decorated function. However, there are couple of things to take into consideration, before using the decorator:

  • The decorator should be invoked as a function rather than as a function name, since it requires the skill builder instance, to register the interceptor.
  • The decorated function should accept only one parameter, which is the Handler Input object and the return value from the function is not captured.
class SkillBuilder(object):
    ....
    def global_request_interceptor(self):
        def wrapper(process_func):
            # wrap the process_func into a class
            # add the class into request interceptors list
            ....
        return wrapper

Code Sample

The following example shows a request interceptor class that can print the request received by Alexa service, in AWS CloudWatch logs, before handling it.

from ask_sdk_core.dispatch_components import AbstractRequestInterceptor

class LoggingRequestInterceptor(AbstractRequestInterceptor):
    def process(self, handler_input):
        print("Request received: {}".format(handler_input.request_envelope.request))
from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

@sb.global_request_interceptor()
def request_logger(handler_input):
    print("Request received: {}".format(handler_input.request_envelope.request))

Registering and Processing the Request Interceptors

Request interceptors are invoked immediately before execution of the request handler for an incoming request. Request attributes in Handler Input's Attribute Manager provide a way for request interceptors to pass data and entities on to other request interceptors and request handlers.

from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

# Implement FooInterceptor, BarInterceptor, BazInterceptor classes

sb.add_global_request_interceptor(FooInterceptor())
sb.add_global_request_interceptor(BarInterceptor())
sb.add_global_request_interceptor(BazInterceptor())
from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()
# decorate foo_interceptor, bar_interceptor, baz_interceptor functions

Response Interceptors

The Global Response Interceptor accepts a Handler Input object, a Response and processes them, after executing the supported request handler. Similar to Request Interceptors, custom response interceptors can be implemented in two ways:

  • By implementing the AbstractResponseInterceptor class.
  • By decorating a custom process function using the Skill Builder global_response_interceptor decorator.

Interface

The AbstractResponseInterceptor class usage needs you to implement the process method. This method takes a Handler Input instance, a Response object that is returned by the request handler. The method doesn't return anything.

class AbstractResponseInterceptor(object):
    @abstractmethod
    def process(self, handler_input, response):
        # type: (HandlerInput, Response) -None
        pass

The global_response_interceptor decorator from SkillBuilder class is a custom wrapper on top of the AbstractResponseInterceptor class and provides the same functionality to any custom decorated function. However, there are couple of things to take into consideration, before using the decorator:

  • The decorator should be invoked as a function rather than as a function name, since it requires the skill builder instance, to register the interceptor.
  • The decorated function should accept two parameters, which are the Handler Input object and Response object respectively. The return value from the function is not captured.
class SkillBuilder(object):
    ....
    def global_response_interceptor(self):
        def wrapper(process_func):
            # wrap the process_func into a class
            # add the class into response interceptors list
            ....
        return wrapper

Code Sample

The following example shows a response interceptor class that can print the response received from successfully handling the request, in AWS CloudWatch logs, before returning it to the Alexa service.

from ask_sdk_core.dispatch_components import AbstractResponseInterceptor

class LoggingResponseInterceptor(AbstractResponseInterceptor):
    def process(handler_input, response):
        print("Response generated: {}".format(response))
from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

@sb.global_response_interceptor()
def response_logger(handler_input, response):
    print("Response generated: {}".format(response))

Registering and Processing the Response Interceptors

Response interceptors are invoked immediately after execution of the request handler for an incoming request.

from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

# Implement FooInterceptor, BarInterceptor, BazInterceptor classes

sb.add_global_response_interceptor(FooInterceptor())
sb.add_global_response_interceptor(BarInterceptor())
sb.add_global_response_interceptor(BazInterceptor())
from ask_sdk_core.skill_builder import SkillBuilder

sb = SkillBuilder()

# decorate foo_interceptor, bar_interceptor, baz_interceptor functions

Was this page helpful?

Last updated: Nov 28, 2023