Skip to content

Instantly share code, notes, and snippets.

@habuma
Created March 6, 2020 04:08
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save habuma/675a4efb4a657391a4b0159e9fda78f5 to your computer and use it in GitHub Desktop.
Save habuma/675a4efb4a657391a4b0159e9fda78f5 to your computer and use it in GitHub Desktop.
Handling Yes/No Intents in an Alexa Skill

An Alexa skill may ask a user a Yes/No question and the response handled by request handlers for the built-in AMAZON.YesIntent and AMAZON.NoIntent intents. (This is different than dialog confirmation where Yes/No confirmation is handled by the dialog.)

It’s easy to setup these intents and their respective intent handlers. Just like any intent, declare them in the interaction model:

{
  "name": "AMAZON.YesIntent",
  "samples": []
},
{
  "name": "AMAZON.NoIntent",
  "samples": []
},

And then create request handlers in the fulfillment code:

const YesIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.YesIntent';
    },
    handle(handlerInput) {
        .... // handle yes intent
    }
}

const NoIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.NoIntent';
    },
    handle(handlerInput) {
        .... // handle no intent
    }
}

Easy peasy, right?

Except for one thing: How do these intent handlers know what the user is saying yes or no to? What if the skill asks more than one yes/no question? How can the intent handler correlate the yes or no answer to a specific question? Also, what’s to stop a user from uttering "Yes" or "No" randomly and triggering these intent handlers, without being asked a question?

We need to set some context by stowing the asked question in a session attribute. To do that, define the following function:

function setQuestion(handlerInput, questionAsked) {
  const sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
  sessionAttributes.questionAsked = questionAsked;
  handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
}

Then, in the request handler that poses the question, call setQuestion() to set the context:

handle(handlerInput) {
    const speakOutput = handlerInput.t('ASK_QUESTION');
    setQuestion(handlerInput, 'IsItSunnyOutToday');
    return handlerInput.responseBuilder
        .speak(speakOutput)
        .reprompt(speakOutput)
        .getResponse();
}

Now, change the canHandle() function of the yes/no intent handlers to check for that session attribute (shown here for AMAZON.YesIntent, but the same change applies for the AMAZON.NoIntent request handler):

canHandle(handlerInput) {
    return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
        && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.YesIntent'
        && handlerInput.attributesManager.getSessionAttributes().questionAsked === 'IsItSunnyOutToday';
},

Now when the user says "Yes" or "No", the request handler will only be invoked if the question asked can be determined from the questionAsked session attribute. If the attribute is null or doesn’t match the value expected, then it will remain unhandled. (You could also define a pair of catch-all handlers to tell the user that you don’t know what they were saying yes or no to in that case.)

When handling the yes and no intents, be sure to clear out the session attribute:

setQuestion(handlerInput, null);

This is especially important if the skill may go on to ask more questions to avoid a mishandling of the yes/no intents.

@johnatanDM
Copy link

johnatanDM commented Sep 18, 2020

Amazing tutorial. Would include one more step. Add Yes/No Intent on exports.handler. I aways forget this.

Copy link

ghost commented Sep 4, 2022

Super helpful tutorial!

@hamid842
Copy link

Thanks a lot, I was looking for this for 2 days
.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment