Search code examples
amazon-web-servicesalexa-skills-kit

Unable to execute intents in Alexa Skills


For some reason I am unable to execute a few of my intents in my Alexa skill. Here is the flow of discussion as it is.

  1. 'open my passwords'

Alexa: what is your passphrase?

  1. 'my passphrase is test'

Alexa: You're in.

  1. 'what is my wifi password?'

Alexa: There was a problem with the requested skill's response.

Here is a screenshot of the conversation.

enter image description here

And here are my acceptable utterances, where type is of slot type AMAZON.SearchQuery.

enter image description here

At this point I am just trying to reach GetPasswordHandler and have her say 'hello world'. But I am unable to log or reach this intent. I was reaching it at one point and was able to execute this intent but for some reason it's not working now and I just get the generic There was a problem with the requested skill's response error.

I tried moving around the intents because I thought maybe the order in which they were listed was the problem but I have yet to find an order that works. I also tried using CloudWatch to log whatever the issue might be but I am pretty new to it and I might be using it incorrectly because I feel like the information isn't very helpful aside from the fact that alarms. All I have been able to find out from the JSON Input in the test panel is that the response was invalid. Here is what the error looks like in the input JSON for the SessionEndRequest.

"error": {
            "type": "INVALID_RESPONSE",
            "message": "An exception occurred while dispatching the request to the skill."
        }

This is the input JSON for the initial GetPassword request.

"request": {
        "type": "IntentRequest",
        "requestId": "amzn1.echo-api.request.bdae78eb-3c92-49a8-b3af-c590e284b842",
        "timestamp": "2020-02-05T17:23:03Z",
        "locale": "en-US",
        "intent": {
            "name": "GetPassword",
            "confirmationStatus": "NONE",
            "slots": {
                "type": {
                    "name": "type",
                    "value": "WiFi",
                    "confirmationStatus": "NONE",
                    "source": "USER"
                }
            }
        }
    }

Here is my Lambda code.

// This sample demonstrates handling intents from an Alexa skill using the Alexa Skills Kit SDK (v2).
// Please visit https://alexa.design/cookbook for additional examples on implementing slots, dialog management,
// session persistence, api calls, and more.
const Alexa = require('ask-sdk-core');

const passphrase = 'test';

const instructions = `You can access existing passwords or create a new password. 
            Just specify password type, such as wifi, laptop or cellphone.`;

// the intent being invoked or included it in the skill builder below.


 const LoginHandler = {
     canHandle(handlerInput) {
         return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
             && handlerInput.requestEnvelope.request.intent.name === "Login";
     },
     handle(handlerInput) {
         console.log('test');
         const request  = handlerInput.requestEnvelope.request;
         const responseBuilder = handlerInput.responseBuilder;
          let slotValues = handlerInput.requestEnvelope.request.intent.slots

         if (slotValues && slotValues.passphrase.value === passphrase){
             var attributes = handlerInput.attributesManager.getSessionAttributes()
             attributes.isLoggedIn = true
             const speakOutput = "You're in.";
             return handlerInput.responseBuilder
             .speak(speakOutput)
             .reprompt(speakOutput)
             .getResponse();  

         } else {
             const speakOutput = `Passphrase not recognized. What is your passphrase?`;

             return handlerInput.responseBuilder
             .speak(speakOutput)
             .reprompt(speakOutput)
             .getResponse();  
         }
     }
 };

const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    },
    handle(handlerInput) {
        var attributes = handlerInput.attributesManager.getSessionAttributes();
        if (attributes.isLoggedIn){
            const speakOutput = `Welcome to your passwords. ${instructions}`;
            return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse(); 
        } else {
            const speakOutput = `What is your pass phrase?`;
            return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse();     
        }

    }
};


// THIS IS THE INTENT THAT DOES NOT WORK
const GetPasswordHandler = {
    canHandle(handlerInput) {
        return (Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && handlerInput.requestEnvelope.request.intent.name === "GetPassword");
    },
    handle(handlerInput) {
        console.log('yes');

        const speakOutput = 'hello world';
            return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse();  
    }
};


const HelpIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.HelpIntent';
    },
    handle(handlerInput) {
        const speakOutput = 'You can say hello to me! How can I help?';

        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse();
    }
};

const CancelAndStopIntentHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
            && (Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.CancelIntent'
                || Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.StopIntent');
    },
    handle(handlerInput) {
        const speakOutput = 'Goodbye!';
        handlerInput.sessionAttributes.isLoggedIn = false 
        return handlerInput.responseBuilder
            .speak(speakOutput)
            .getResponse();
    }
};

const SessionEndedRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'SessionEndedRequest';
    },
    handle(handlerInput) {
        // Any cleanup logic goes here.
        handlerInput.sessionAttributes.isLoggedIn = false 
        return handlerInput.responseBuilder.getResponse();
    }
};

// The intent reflector is used for interaction model testing and debugging.
// It will simply repeat the intent the user said. You can create custom handlers
// for your intents by defining them above, then also adding them to the request
// handler chain below.
const IntentReflectorHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest';
    },
    handle(handlerInput) {
        const intentName = Alexa.getIntentName(handlerInput.requestEnvelope);
        const speakOutput = `You just triggered ${intentName}`;

        return handlerInput.responseBuilder
            .speak(speakOutput)
            //.reprompt('add a reprompt if you want to keep the session open for the user to respond')
            .getResponse();
    }
};

// Generic error handling to capture any syntax or routing errors. If you receive an error
// stating the request handler chain is not found, you have not implemented a handler for
// the intent being invoked or included it in the skill builder below.
const ErrorHandler = {
    canHandle() {
        return true;
    },
    handle(handlerInput, error) {
        handlerInput.sessionAttributes.isLoggedIn = false 
        console.log(`~~~~ Error handled: ${error.stack}`);
        const speakOutput = `Sorry, I had trouble doing what you asked. Please try again. ${error.stack}`;

        return handlerInput.responseBuilder
            .speak(speakOutput)
            .reprompt(speakOutput)
            .getResponse();
    }
};


// The SkillBuilder acts as the entry point for your skill, routing all request and response
// payloads to the handlers above. Make sure any new handlers or interceptors you've
// defined are included below. The order matters - they're processed top to bottom.
exports.handler = Alexa.SkillBuilders.custom()
    .addRequestHandlers(
        LaunchRequestHandler,
        CancelAndStopIntentHandler,
        SessionEndedRequestHandler,
        LoginHandler,
        GetPasswordHandler,
        HelpIntentHandler,
        IntentReflectorHandler, // make sure IntentReflectorHandler is last so it doesn't override your custom intent handlers
    )
    .addErrorHandlers(
        ErrorHandler,
    )
    .lambda();

And here is my JSON.

{
    "interactionModel": {
        "languageModel": {
            "invocationName": "my passwords",
            "intents": [
                {
                    "name": "AMAZON.CancelIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.HelpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.StopIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NavigateHomeIntent",
                    "samples": []
                },
                {
                    "name": "GetPassword",
                    "slots": [
                        {
                            "name": "type",
                            "type": "AMAZON.SearchQuery"
                        }
                    ],
                    "samples": [
                        "password for my {type}",
                        "{type} password",
                        "what is my {type} password"
                    ]
                },
                {
                    "name": "AMAZON.MoreIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NavigateSettingsIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.NextIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.PauseIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.ResumeIntent",
                    "samples": []
                },
                {
                    "name": "Login",
                    "slots": [
                        {
                            "name": "passphrase",
                            "type": "AMAZON.SearchQuery"
                        }
                    ],
                    "samples": [
                        "my passphrase is {passphrase}"
                    ]
                },
                {
                    "name": "AMAZON.PageUpIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.PageDownIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.PreviousIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.ScrollRightIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.ScrollDownIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.ScrollLeftIntent",
                    "samples": []
                },
                {
                    "name": "AMAZON.ScrollUpIntent",
                    "samples": []
                }
            ],
            "types": []
        }
    }
}

Solution

  • I ended up just rewriting the intents and they work now. I'm not sure exactly what was wrong but I noticed that when I added the new intents they were added to the bottom of my skill manifest as opposed to the previous order. I am not 100% sure that this was the issue but it is the only thing I noticed changing when I remade the intentions.