I am using the ASK SDK 2.0 for Node.js. I have a skill that uses a dialog model to prompt the user for a series of inputs, all of which are required slots with the type AMAZON.NUMBER. When a user gives a numerical response, everything works fine. However, if the user gives a non-numeric response, such as "yellow", the slot value is filled in with:
"value": "?"
and moves on to propmpt the user for the input for the next slot. How can I get it to reprompt the user for that slot again if they provide an invalid response? I've poured over the documentation and can't find anything. Ideally I would want the skill to reprompt the user until a valid input is given (i.e., the value isn't "?")
(Strangely, if i set the type to AMAZON.DATE, it will automatically reprompt once, and then if an invalid type is provided a second time the skill will just quit out.)
My response looks like this:
"response": {
"directives": [{
"type": "Dialog.Delegate",
"updatedIntent": {
"name": "MRRIntent",
"confirmationStatus": "NONE",
"slots": {
"growthValue": {
"name": "growthValue",
"value": "?",
"confirmationStatus": "NONE"
},
"churnValue": {
"name": "churnValue",
"value": "?",
"confirmationStatus": "NONE"
},
"startingValue": {
"name": "startingValue",
"value": "10",
"confirmationStatus": "NONE"
}
}
}
}]
}
Where in this example startingValue was given a numerical response, but the other two (growthValue and churnValue) were given non-number responses.
Where in the intent handler would I be able to check for this value and reprompt on the particular slots that are failing? I am using the Dialog.Directive which the docs say not to use reprompt with ( https://developer.amazon.com/docs/custom-skills/dialog-interface-reference.html#details ), unless I am misunderstanding it.
My handlers look like this:
const InProgressPlanMyTripHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' &&
request.intent.name === 'MRRIntent' &&
request.dialogState !== 'COMPLETED';
},
handle(handlerInput) {
const currentIntent = handlerInput.requestEnvelope.request.intent;
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse();
},
};
const CompletedPlanMyTripHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' && request.intent.name === 'MRRIntent';
},
handle(handlerInput) {
const responseBuilder = handlerInput.responseBuilder;
const filledSlots = handlerInput.requestEnvelope.request.intent.slots;
const slotValues = getSlotValues(filledSlots);
let speechOutput = `Your values are: startingValue: ${slotValues.startingValue.synonym} growthValue: ${slotValues.growthValue.synonym}, and churnValue: ${slotValues.churnValue.synonym}`
return responseBuilder
.speak(speechOutput)
.getResponse();
},
};
I used the Plan My Trip example as my starting point, so the vast majority of my code is going to be identical to it: https://github.com/alexa/alexa-cookbook/tree/master/feature-demos/skill-demo-plan-my-trip
What am I missing / not understanding? Thanks
Always validate slots in your backend, and whenever your number-slot is not returning a numeric value, do not delegate, instead use Dialog.ElicitSlot directive to make Alexa ask for that particular slot.
Ex:
// if number-slot validation fails
return handlerInput.responseBuilder
.addElicitSlotDirective(slotToElicit)
.speak("Please provide a number")
.reprompt("Please provide a number")
.getResponse();
With Dialog.Delegate directive you cannot send outputSpeech or reprompt from your code. Instead those defined in interaction model will be used. However, at any point, you can take over the dialog rather than continuing to delegate to Alexa.
More on Dialog directives here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With