Manage the Skill Session and Session Attributes


Your skill can keep the skill session open to conduct a back-and-forth interaction with the user. While the session is open, the user does not need to use your invocation name to talk to your skill.

Lifecycle of a skill session

  1. A skill session begins when a user invokes your skill and Alexa sends your skill a request. The request contains a session object that uses a Boolean value called new to indicate that this is a new session.

  2. Your skill receives the request and returns a response for Alexa to speak to the user.

  3. What happens next depends on the value of the shouldEndSession parameter in your skill's response:

    • true – The session ends. Alexa, not the skill, handles any further speech from the user. If the user re-invokes the skill, Alexa creates a new session. Refer back to step 1.
    • false or null – The session stays open and Alexa opens the microphone to indicate that the skill expects the user to respond. If the user's response maps to your interaction model, Alexa sends a new intent to the skill and the process goes back to step 2.

      However, if a few seconds elapse without a response from the user, Alexa closes the microphone. If the skill specified a reprompt, Alexa reprompts the user to speak and opens the microphone for a few more seconds. If the user still doesn't respond, the session ends.

      The session might remain open for a short time with the microphone closed if the user uses the skill on a device with a screen as described in How devices with screens affect the skill session.

      One exception overrides these rules. When you use skill connections to request a task from Amazon or another provider skill, you hand over control to the requested task and the session ends. Depending on the task, Alexa can hand control back to your skill. For example, the directives to start the purchase flow task for in-skill purchasing and paid skills automatically end the session, regardless of the shouldEndSession value. After the purchase flow completes, you use persistent storage to resume the skill. For details, see Skill Connections.

    • undefined (not set) – The session behavior depends on the type of Echo device. If the device has a screen and the skill response includes screen content, the session stays open for up to 30 more seconds, without opening the microphone to prompt the user for input. For details, see How devices with screens affect the skill session. If the user speaks and precedes their request with the wake word (such as "Alexa,") Alexa sends the request to the skill. Otherwise, Alexa ignores the user's speech. If an Alexa Gadgets event handler is active, the session continues to stay open until the skill calls CustomInterfaceController.StopEventHandler or the event handler expires.

How devices with screens affect the skill session

When the user invokes a skill on a device with a screen, the session can remain open for up to 30 additional seconds with the microphone closed. The user continues to see content related to the skill on the screen. To continue interacting with the skill, the user can use the wake word to speak to Alexa, followed by an utterance that maps to the interaction model for the skill.

This extended session occurs when all the following conditions are true:

  • The user invokes the skill with a device with a screen (such as an Echo Show).
  • The skill configuration supports devices with screens. This means that one of these options on the Build > Interfaces page in the developer console is enabled:
    • Alexa Presentation Language
    • Display Interface (deprecated)
  • The skill response includes content to display on the screen. The visual content can be one of the following:
    • An Alexa Presentation Language document, displayed when you return the Alexa.Presentation.APL.RenderDocument directive.
    • An Alexa app card, displayed when you include a card object. Although cards are intended for the Alexa app, screen devices display card content when you don't provide any other screen content.
    • A display template, displayed when you return the Display.RenderTemplate directive.
  • The shouldEndSession value in the response is either false or undefined (not set).
    • When undefined, the extended session remains open for approximately 30 seconds.
    • When false, the extended session occurs after the user fails to respond to the reprompt. Here, the session remains open for between 20 and 30 seconds.

For example, a skill configured to support screen devices and display content on the screen could have the following interaction on a device with a screen:

User: Open Spacey.

Skill gets a LaunchRequest, then responds with the text to speak and shouldEndSession set to false.
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?
The screen displays content related to Spacey, such as an APL document sent via the RenderDocument directive.
User: (User says nothing. A few seconds elapse.)

Alexa: Try asking me to tell you something about space. (Alexa speaks the reprompt provided with the response.)
User: Um…

More time passes.
Microphone closes, but the session remains open. Content about Spacey continues to display.
User: Alexa, tell me about Mars. (User interacts with the skill without using the invocation name, since the skill session is still active.)

Alexa sends the skill a PlanetFacts intent. The request shows that this is a continuing session, not a new session.
Alexa: On Mars…

Save data during the session

To retain data during the session, use session attributes. Create a map of key/value pairs with the data you need to save. Include this map in the sessionAttributes property of your response. When Alexa sends the next request as part of the same session, the same map is included in the session.attributes property of the request. Use the keys you defined to retrieve the data from the map.

For example:

…earlier utterances to start this interaction.
User: My favorite color is blue

Alexa sends the skill the FavoriteColorIntent with the favoriteColor slot set to "blue". The skill responds with text to speak and a session attribute with the key favoriteColor and the value "blue".
Alexa: I now know your favorite color is blue.
User: What was that color again?

Alexa sends the skill the WhatsMyColorIntent intent. The request includes the favoriteColor session attribute. The skill retrieves this attribute to build the response.
Alexa: Your favorite color is blue.

The Alexa Skills Kit SDKs provide an AttributesManager to add session attributes to your response, and then retrieve the attributes from an incoming request.

This example shows how an intent handler can save data into the session attributes. In this example, the FavoriteColorIntent has a single, required slot called favoriteColor. The intent is configured with auto-delegation, so Alexa prompts the user to fill the slot if the user does not provide a value initially.

Copied to clipboard.

This sample code uses the Alexa Skills Kit SDK for Node.js (v2).

const FavoriteColorIntentHandler = {
  canHandle(handlerInput) {
    getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
    && getIntentName(handlerInput.requestEnvelope) === 'FavoriteColorIntent'
    && getDialogState(handlerInput.requestEnvelope) === 'COMPLETED';
  },
  handle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    const favoriteColor = getSlotValue(handlerInput.requestEnvelope, 'favoriteColor')
    sessionAttributes.favoriteColor = favoriteColor;
    handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
 
    const speechText = `I saved the value ${favoriteColor} in the session attributes.
    Ask me for your favorite color to demonstrate retrieving the attributes.`;
    const repromptText = `You can ask me, what's my favorite color?`;
 
    return handlerInput.responseBuilder
      .speak(speechText)
      .reprompt(repromptText)
      .getResponse();
  }
};

Copied to clipboard.

This sample code uses the Alexa Skills Kit SDK for Python.

from ask_sdk_core.dispatch_components import AbstractRequestHandler
from ask_sdk_core.utils import is_intent_name, get_dialog_state, get_slot_value
from ask_sdk_core.handler_input import HandlerInput
from ask_sdk_model import Response, DialogState
 
 
class FavoriteColorIntentHandler(AbstractRequestHandler):
    """Handler for FavoriteColorIntent."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_intent_name("FavoriteColorIntent")(
            handler_input) and get_dialog_state(
            handler_input=handler_input) == DialogState.COMPLETED
 
    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
 
        # Get any existing attributes from the incoming request
        session_attr = handler_input.attributes_manager.session_attributes
 
        # Get the slot value from the request and add it to the session 
        # attributes dictionary. Because of the dialog model and dialog 
        # delegation, this code only ever runs when the favoriteColor slot 
        # contains a value, so a null check is not necessary.
        fav_color = get_slot_value("favoriteColor")
        session_attr["favoriteColor"] = fav_color
 
        # The SDK automatically saves the attributes to the session, 
        # so that the value is available to the next intent
 
        speech_text = ("I saved the value {} in the session attributes. "
                       "Ask me for your favorite color to demonstrate "
                       "retrieving the attributes.").format(fav_color)
 
        reprompt_text = "You can ask me, what's my favorite color?"
 
        return handler_input.response_builder.speak(speech_text).ask(
            reprompt_text).response

Copied to clipboard.

This sample code uses the Alexa Skills Kit SDK for Java.

package handlers;

import static com.amazon.ask.request.Predicates.intentName;

import java.util.Map;
import java.util.Optional;

import com.amazon.ask.attributes.AttributesManager;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.impl.IntentRequestHandler;
import com.amazon.ask.model.DialogState;
import com.amazon.ask.model.IntentRequest;
import com.amazon.ask.model.Response;
import com.amazon.ask.request.RequestHelper;

public class FavoriteColorIntentHandler implements IntentRequestHandler {
    @Override
    public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
        // This intent is configured with required slots and auto-delegation,
        // so the handler only needs to handle completed dialogs.
        return handlerInput.matches(intentName("FavoriteColorIntent"))
                && intentRequest.getDialogState() == DialogState.COMPLETED;        
    }

    @Override
    public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {

        RequestHelper requestHelper = RequestHelper.forHandlerInput(handlerInput);

        // Get any existing attributes from the incoming request
        AttributesManager attributesManager = handlerInput.getAttributesManager();
        Map<String,Object> attributes = attributesManager.getSessionAttributes();
        
        // Get the slot value from the request and add to a map for the attributes.
        // Because of the dialog model and dialog delegation, this code only ever
        // runs when the favoriteColor slot contains a value, so a null check
        // is not necessary.
        Optional<String> favoriteColor = requestHelper.getSlotValue("favoriteColor");                
        attributes.put("favoriteColor", favoriteColor.get());
        
        // This saves the attributes to the session, so the value is available
        // to the next intent.
        attributesManager.setSessionAttributes(attributes);

        // Include a reprompt in the response to automatically set 
        // shouldEndSession to false.
        return handlerInput.getResponseBuilder()
                .withSpeech("I saved the value " + favoriteColor.get() + 
                    " in the session attributes. Ask me for your favorite color" +
                    " to demonstrate retrieving the attributes." )
                .withReprompt("You can ask me, what's my favorite color?")
                .build();
    }
}

Copied to clipboard.

This is the JSON response sent by the FavoriteColorIntentHandler. Note that the sessionAttributes object includes the favoriteColor attribute:

{
  "version": "1.0",
  "sessionAttributes": {
    "favoriteColor": "blue"
  },
  "response": {
    "outputSpeech": {
      "type": "SSML",
      "ssml": "<speak>I saved the value blue in the session attributes. Ask me for your favorite color to demonstrate retrieving the attributes.</speak>"
    },
    "reprompt": {
      "outputSpeech": {
        "type": "SSML",
        "ssml": "<speak>You can ask me, what's my favorite color?</speak>"
      }
    },
    "shouldEndSession": false
  }
}

This example shows how an intent handler can access data from the session attributes. In this example, the WhatsMyColorIntent has no slots. It retrieves previously set data from the session attributes to respond. If the data doesn't yet exist (because the user invoked this intent before invoking FavoriteColorIntent), the handler uses the Dialog.ElicitSlot directive to invoke FavoriteColorIntent and prompt for the missing data.

Copied to clipboard.

This sample code uses the Alexa Skills Kit SDK for Node.js (v2).

const WhatsMyColorIntentHandler = {
  canHandle(handlerInput) {
    getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
    && getIntentName(handlerInput.requestEnvelope) === 'WhatsMyColorIntent';
  },
  handle(handlerInput) {
    const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    if (sessionAttributes.favoriteColor) {
      return handlerInput.responseBuilder
        .speak(`Your favorite color is ${sessionAttributes.favoriteColor}`)
        .getResponse();
    } else {
      return handlerInput.responseBuilder
        .speak('You need to tell me your favorite color first.')
        .reprompt('Please tell me your favorite color.')
        .addElicitSlotDirective('favoriteColor')
        .getResponse();
    }
  }
}

Copied to clipboard.

This sample code uses the Alexa Skills Kit SDK for Python.

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, Intent
from ask_sdk_model.dialog import ElicitSlotDirective
 
 
class WhatsMyColorIntentHandler(AbstractRequestHandler):
    """Handler for WhatsMyColorIntent."""
    def can_handle(self, handler_input):
        # type: (HandlerInput) -> bool
        return is_intent_name("WhatsMyColorIntent")(handler_input)
 
    def handle(self, handler_input):
        # type: (HandlerInput) -> Response
 
        session_attr = handler_input.attributes_manager.session_attributes
 
        # The user could invoke this intent before they set their favorite 
        # color, so check for the session attribute first.
        if "favoriteColor" in session_attr:
            fav_color = session_attr["favoriteColor"]
 
            return handler_input.response_builder.speak(
                "Your favorite color is {}. Goodbye".format(
                    fav_color)).set_should_end_session(True).response
        else:
            # The user must have invoked this intent before they set their color. 
            # Trigger the FavoriteColorIntent and ask the user to fill in the 
            # favoriteColor slot. Note that the skill must have a *dialog model* 
            # to use the ElicitSlot Directive.
 
            return handler_input.response_builder.speak(
                "You need to tell me your favorite color first.").ask(
                "please tell me your favorite color.").add_directive(
                directive=ElicitSlotDirective(
                    updated_intent=Intent(
                        name="FavoriteColorIntent"), 
                    slot_to_elicit="favoriteColor")).response

Copied to clipboard.

This sample code uses the Alexa Skills Kit SDK for Java.

package handlers;

import static com.amazon.ask.request.Predicates.intentName;

import java.util.Map;
import java.util.Optional;

import com.amazon.ask.attributes.AttributesManager;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.impl.IntentRequestHandler;
import com.amazon.ask.model.Intent;
import com.amazon.ask.model.IntentRequest;
import com.amazon.ask.model.Response;

public class WhatsMyColorIntentHandler implements IntentRequestHandler {
    @Override
    public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
        return handlerInput.matches(intentName("WhatsMyColorIntent"));
    }

    @Override
    public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {

        AttributesManager attributesManager = handlerInput.getAttributesManager();
        Map <String,Object> attributes = attributesManager.getSessionAttributes();

        // The user could invoke this intent before they set their favorite
        // color, so check for the session attribute first.
        if (attributes.containsKey("favoriteColor")){
            String favoriteColor = attributes.get("favoriteColor").toString();

            return handlerInput.getResponseBuilder()
                    .withSpeech("Your favorite color is " + favoriteColor + ". Goodbye")
                    .withShouldEndSession(true)
                    .build();
        } else {
            // The user must have invoked this intent before they set their color.
            // Trigger the FavoriteColorIntent and ask the user to fill in the 
            // favoriteColor slot. Note that the skill must have a *dialog model*
            // to use the ElicitSlot directive.

            // Create the intent.
            Intent intent = Intent.builder()
                .withName("FavoriteColorIntent")
                .build();

            return handlerInput.getResponseBuilder()
                    .withSpeech("You need to tell me your favorite color first.")
                    .withReprompt("Please tell me your favorite color.")
                    .addElicitSlotDirective("favoriteColor", intent)
                    .build();
        }

    }
}

Copied to clipboard.

This JSON shows the incoming IntentRequest when the user has already provided the name of a color. Note the values in session.attributes.

{
  "version": "1.0",
  "session": {
    "new": false,
    "sessionId": "amzn1.echo-api.session.1",
    "application": {
      "applicationId": "amzn1.ask.skill.1"
    },
    "attributes": {
      "favoriteColor": "blue"
    },
    "user": {
      "userId": "amzn1.ask.account.1"
    }
  },
  "context": {},
  "request": {
    "type": "IntentRequest",
    "requestId": "amzn1.echo-api.request.1",
    "timestamp": "2019-02-13T04:22:36Z",
    "locale": "en-US",
    "intent": {
      "name": "WhatsMyColorIntent",
      "confirmationStatus": "NONE"
    }
  }
}

Session attributes are useful for several scenarios:

  • Keep track of state data to handle different skill states, such as a state attribute to indicate whether the user is already in a game or ready to start a new game. Use the attribute as criteria in the code that determines whether a handler can handle a particular request. This can be especially useful if your skill asks the user multiple yes/no questions, since the response "yes" or "no" may have a different meaning depending on skill state.
  • Keep track of game scores and counters.
  • Save slot values that the user has provided as you continue to prompt for additional values. Note that as an alternative, you can use a dialog model and delegate the dialog to accomplish this without session attributes. See Delegate the Dialog to Alexa.

Structure of session attributes

You can pass along more complex data in the session attributes if necessary, as long as you can structure the data into a key/value map. For example, a quiz game skill might need attributes to keep track of the current state of the game, the user's current score, and the correct answer to the question that was just asked. In this example, the quizitem attribute represents the correct answers to the current question.

  {
  "sessionAttributes": {
    "quizscore": 0,
    "quizproperty": "STATEHOOD_YEAR",
    "response": "OK.  I will ask you 10 questions about the United States. ",
    "state": "_QUIZ",
    "counter": 1,
    "quizitem": {
      "name": "Nevada",
      "abbreviation": "NV",
      "capital": "Carson City",
      "statehoodYear": "1864",
      "statehoodOrder": "36"
    }
  }
}

For a full sample skill that illustrates more complex session attributes for game state, see Quiz game sample skill.

Save data between sessions

Session attributes exist while the session is open. Once the session ends, any attributes associated with that session are lost. If your skill needs to remember data across multiple sessions, you need to save that data in persistent storage such as DynamoDB or S3.

You can use the userId provided in each request to identify the user. The userId for a given user is generated when the user enables your skill in the Alexa app. Every subsequent request from that user to your skill contains the same userId unless the user disables the skill.

Persisting attributes between skill sessions is built in to the ASK SDKs for Node.js, Java, and Python. For details, see ASK SDK documentation about managing attributes.

For a sample skill that illustrates persisting user attributes, see High Low Game.


Was this page helpful?

Last updated: Dec 08, 2021