如何管控Amazon Alexa问答技能不同流程阶段可激活的意图?
Great question! This is a super common pain point when building Alexa skills—you want to enforce a structured conversation so users can't jump ahead and break your intended flow. Your idea of using session attributes to track allowed intents is spot-on, and I’ll walk you through exactly how to implement it to fix your Quiz Skill issue.
Core Approach: Track Allowed Intents with Session Attributes
The key is to use session attributes to keep track of which intents are permitted at each stage of the conversation. Before processing any intent, you’ll validate if it’s allowed in the current state. If not, you’ll redirect the user back to the correct part of the flow.
Step 1: Initialize Allowed Intents on Launch
When the skill starts via Alexa, start Quiz Skill, set up session attributes that only allow the initial confirmation intents (AMAZON.YesIntent and AMAZON.NoIntent):
const LaunchRequestHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest'; }, handle(handlerInput) { // Initialize session attributes to lock to confirmation intents const sessionAttributes = handlerInput.attributesManager.getSessionAttributes(); sessionAttributes.allowedIntents = ['AMAZON.YesIntent', 'AMAZON.NoIntent']; const speakOutput = 'Are you ready to start the quiz?'; return handlerInput.responseBuilder .speak(speakOutput) .reprompt(speakOutput) .getResponse(); } };
Step 2: Create a Validation Helper Function
Make a reusable function to check if the triggered intent is allowed in the current session state:
function isIntentAllowed(handlerInput, intentName) { const sessionAttributes = handlerInput.attributesManager.getSessionAttributes(); return sessionAttributes.allowedIntents?.includes(intentName); }
Step 3: Validate Intents Before Processing
In every intent handler, first check if the intent is permitted. If not, redirect the user back to the appropriate starting point:
Example: YesIntent Handler
const YesIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.YesIntent'; }, handle(handlerInput) { // Block access if user tries to trigger this intent out of order if (!isIntentAllowed(handlerInput, 'AMAZON.YesIntent')) { return handlerInput.responseBuilder .speak("Let's start from the beginning first—are you ready to start the quiz?") .reprompt("Are you ready to start the quiz?") .getResponse(); } // Update allowed intents to now accept quiz answers const sessionAttributes = handlerInput.attributesManager.getSessionAttributes(); sessionAttributes.allowedIntents = ['QuizAnswerIntent']; // Replace with your answer intent name sessionAttributes.currentQuestion = 0; // Track progress through questions const firstQuestion = "First question: What is the capital of France? A) London B) Paris C) Berlin"; return handlerInput.responseBuilder .speak(firstQuestion) .reprompt(firstQuestion) .getResponse(); } };
Example: Quiz Answer Intent Handler
const QuizAnswerIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'QuizAnswerIntent'; }, handle(handlerInput) { // Prevent users from answering before starting the quiz if (!isIntentAllowed(handlerInput, 'QuizAnswerIntent')) { return handlerInput.responseBuilder .speak("Hold on—let's start the quiz first! Are you ready to begin?") .reprompt("Are you ready to start the quiz?") .getResponse(); } // Process the user's answer logic here... const speakOutput = "That's correct! Next question: What is the largest ocean on Earth? A) Atlantic B) Pacific C) Indian"; return handlerInput.responseBuilder .speak(speakOutput) .reprompt(speakOutput) .getResponse(); } };
Step 4: Handle NoIntent and Cleanup
For the AMAZON.NoIntent, either end the session or reset the allowed intents if you want to let the user try again:
const NoIntentHandler = { canHandle(handlerInput) { return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest' && Alexa.getIntentName(handlerInput.requestEnvelope) === 'AMAZON.NoIntent'; }, handle(handlerInput) { if (!isIntentAllowed(handlerInput, 'AMAZON.NoIntent')) { return handlerInput.responseBuilder .speak("Let's start over—are you ready to begin the quiz?") .reprompt("Are you ready to start the quiz?") .getResponse(); } const speakOutput = "No problem! Feel free to come back when you're ready. Goodbye!"; return handlerInput.responseBuilder .speak(speakOutput) .getResponse(); } };
Why This Works
By tracking allowed intents in session attributes, you create a "gatekeeper" for every user interaction. When someone tries to trigger AMAZON.YesIntent via Alexa, ask Quiz Skill yes, the validation check will fail (since the session wasn’t initialized with that intent allowed yet) and redirect them back to the initial prompt.
Bonus Tips
- Don’t forget to handle
AMAZON.StopIntentandAMAZON.CancelIntentby ending the session cleanly. - If your quiz has multiple rounds, update the
allowedIntentsattribute as needed (e.g., keepQuizAnswerIntentallowed until the quiz finishes). - For more complex flows, you can expand the session attributes to track a "conversation state" (like
INITIAL,QUIZ_IN_PROGRESS,RESULTS) instead of just allowed intents—this scales better for larger skills.
内容的提问来源于stack exchange,提问作者peachykeen

