Alexa SDK V2 StateHandler - Multiple intents sharing the same slot value

651 Views Asked by At

I am writing an Alexa skill that captures age from one intent and captures weight from different intent. and Basically, these two are of type number.

When I am trying to enter a number for weight, it is being captured in the first Intent's slot. Here is my intent schema.

{
  "intents": [
    {
      "slots": [
        {
          "name": "AGE",
          "type": "AMAZON.NUMBER"
        }
      ],
      "intent": "AgeIntent"
    },
    {
      "slots": [
        {
          "name": "WEIGHT",
          "type": "AMAZON.NUMBER"
        }
      ],
      "intent": "WeightIntent"
    }
  ]
}

And my sample utterances are

AgeIntent

My age is {AGE}
{AGE}

WeightIntent

My weight is {WEIGHT}
{WEIGHT}

Conversation

User : open my test skill
Alexa: what is your age
User: 28
Alexa: what is your weight
User: 68

Here when user give his weight input 68, instead of matching WeightIntent, it is matching with AgeIntent. I am getting AgeIntent in my request.intent.name.

I know it will work with my weight is 68; and Also I can make it working with StateHandler feature of Alexa-SDK-V1, But I am using Alexa-SDK-V2

So the problem here is: Skill is always sending intentName of first matching intent (i.e. AgeIntent) from interaction model, and I am expecting to get second matching IntentName (i.e. WeightIntent) for my second question.

1

There are 1 best solutions below

2
On

The solution is simple either you make only 1 intent and use dialog management to get all the slot values you need OR If you need to make them separate intents then use a state variable in session of the skill and make sure you to set and update state in both intents. You can do it as:

const AgeIntentHandler = {
  canHandle(handlerInput) {
    let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === 'AgeIntent'
        && sessionAttributes.state !== 'WEIGHT';
  },
  handle(handlerInput) {
  
    let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    sessionAttributes.state = 'WEIGHT';
    handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
    
    const speechText = 'Age intent is called!';

    return handlerInput.responseBuilder
      .speak(speechText)
      .withSimpleCard('Hello World', speechText)
      .getResponse();
  },
};

const WeightIntentHandler = {
  canHandle(handlerInput) {
    let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    
    return handlerInput.requestEnvelope.request.type === 'IntentRequest'
      && handlerInput.requestEnvelope.request.intent.name === 'WeightIntent'
        && sessionAttributes.state === 'WEIGHT';
  },
  handle(handlerInput) {
  
    let sessionAttributes = handlerInput.attributesManager.getSessionAttributes();
    sessionAttributes.state = '';
    handlerInput.attributesManager.setSessionAttributes(sessionAttributes);
    
    const speechText = 'Weight intent is called!';

    return handlerInput.responseBuilder
      .speak(speechText)
      .withSimpleCard('Hello World', speechText)
      .getResponse();
  },
};

Although it is better to use Dialogs to have no confusion in states and you can add more slots later easily.