Delegate the Dialog to Alexa
To simplify your code to collect and confirm slot values, create a dialog model and delegate the dialog to Alexa. The dialog model identifies the prompts and utterances to collect, validate, and confirm the slot values and intents. When you delegate the dialog to Alexa, Alexa determines the next step in the conversation and uses prompts to ask the user for the information.
- Ways to delegate the dialog to Alexa
- Automatically delegate simple dialogs to Alexa
- Manually delegate to alter the conversation at run-time
- Configure the delegation strategy for your skill and intents
- JSON for auto delegation in the dialog model (Interaction Model Schema)
- Related Topics
Ways to delegate the dialog to Alexa
There are two ways to delegate the dialog:
- Enable auto delegation, either for the entire skill or for specific intents. In this case, Alexa completes all of the dialog steps based on your dialog model. Alexa sends your skill a single
IntentRequest
when the dialog is complete. - Delegate manually with the
Dialog.Delegate
directive. In this case, Alexa sends your skill anIntentRequest
for each turn of the conversation.- The request indicates the current state of the dialog with the
dialogState
set toSTARTED
,IN_PROGRESS
, orCOMPLETED
. - Your skill returns the
Dialog.Delegate
directive for incomplete dialogs. This tells Alexa to check the dialog model for the next step and use a prompt to ask the user for more information as needed. - Once all the steps are complete, your skill receives the final
IntentRequest
withdialogState
set toCOMPLETED
.
- The request indicates the current state of the dialog with the
The right delegation strategy for a specific interaction depends on the complexity of the dialog. Auto delegation is simpler because you do not need to handle any of the dialog in your code. Delegating manually with Dialog.Delegate
is more flexible, because your skill can make run-time decisions such as defaulting values. You can also use Dialog.Delegate
in combination with other Dialog
directives to take complete control over the dialog if necessary.
You can configure an overall delegation strategy for the entire skill, and then also configure the delegation strategy for each intent in the skill. This means you can use auto delegation for some intents, but use manual delegation or no delegation at all for others.
Automatically delegate simple dialogs to Alexa
Configure your skill to delegate simple dialogs where the dialog steps and slots to fill don’t vary based on run-time interaction with the user. For example, consider a skill that answers questions about the planets. An intent in this skill needs to know the name of the planet the user is asking about. This requirement doesn't change based on earlier turns in the dialog, so just delegate this to Alexa.
For example, in this interaction, Alexa sends the skill just one intent, after all the back-and-forth to collect the value for the planet
slot is complete:
User: What is the weather like on other planets?
Alexa: What planet do you want to know about? (Alexa prompts the user with a prompt defined for the planet
slot on the GetPlanetWeather
intent.)
User: The sun (User responds to the prompt with a value that does not meet the validation rules for the planet
slot)
Alexa: We don't think of the sun as having weather, exactly, so please tell me a planet instead. (Because the user's value failed validation, Alexa responds with another prompt to ask for an acceptable value.)
User: Mars.
At this point, the planet
slot contains an acceptable value, so Alexa sends the skill an IntentRequest
. The intent is GetPlanetWeather
intent, which has a single slot planet
containing the value "Mars".
To create an interaction like this, you would do the following:
- Configure the
planet
slot on theGetPlanetWeather
intent as a required slot and provide prompts to ask the user for a planet. - Enable slot validation rules for the
planet
slot. In this case, there are two rules:- Reject a set of values: to reject specific values like "the sun" and provide a more context-aware prompt. This rule is checked first.
- Accept only Slot type’s values and synonyms: to only accept values that are defined in the custom type for the slot. This rule is checked if the user's value passes the first rule.
- Configure the
GetPlanetWeather
intent to automatically delegate the dialog to Alexa.
This example illustrates an intent handler for GetPlanetWeather
for this scenario. The handler does not need to check the dialog state or verify that the planet
slot value identifies a valid planet, because slot validation and auto delegation in the dialog model handle that before the request is ever sent to your skill.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
In this example, details about the planets are stored in a PLANETS
map. This maps properties about the planets to the IDs defined for slot values in the Planet custom slot type.
const GetPlanetWeatherHandler = {
canHandle(handlerInput){
const request = handlerInput.requestEnvelope.request;
return (request.type === 'IntentRequest'
&& request.intent.name === 'GetPlanetWeather');
},
handle(handlerInput){
const intent = handlerInput.requestEnvelope.request.intent;
let planetId = intent.slots.Planet.resolutions.resolutionsPerAuthority[0].values[0].value.id;
let planet = PLANETS[planetId];
let speechOutput = "On " + planet.PrintName + ", you can expect " + planet.Weather;
return handlerInput.responseBuilder
.speak(speechOutput)
.withShouldEndSession (true)
.getResponse();
}
};
This code example uses the Alexa Skills Kit SDK for Java.
In this example, details about the planets are stored in a Planet
enum. This enum has properties for information such as a string describing the weather, and getter methods to retrieve that data. The enum values match the IDs defined for slot values in the Planet custom slot type.
package com.ask.factskill.handlers;
import com.amazon.ask.dispatcher.request.handler.HandlerInput;
import com.amazon.ask.dispatcher.request.handler.impl.IntentRequestHandler;
import com.amazon.ask.model.Intent;
import com.amazon.ask.model.IntentRequest;
import com.amazon.ask.model.Response;
import com.amazon.ask.model.Slot;
import com.ask.factskill.enums.Planet;
import java.util.Optional;
import static com.amazon.ask.request.Predicates.intentName;
import static com.amazon.ask.request.Predicates.requestType;
import static com.ask.factskill.util.Constants.*;
public class GetPlanetWeatherHandler implements IntentRequestHandler {
@Override
public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
return (handlerInput.matches(intentName("GetPlanetWeather")));
}
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
Intent intent = intentRequest.getIntent();
Slot planetSlot = intent.getSlots().get(PLANET_SLOT);
String planetId = planetSlot
.getResolutions()
.getResolutionsPerAuthority().get(0).getValues()
.get(0).getValue().getId();
Planet planet = Planet.valueOf(planetId);
String speechText = "On " + planet.getPrintName() + ", you can expect " +
planet.getPlanetWeather();
return handlerInput.getResponseBuilder()
.withSpeech(speechText)
.build();
}
}
Start another dialog after the first completes
There is one scenario in which you might still use Dialog.Delegate
when auto delegate is enabled. Your intent handler can return Dialog.Delegate
from the completed dialog to tell Alexa to invoke a different intent and start a new dialog.
For example, after completing the dialog for a BookFlight
intent, you could tell Alexa to start the dialog for BookRentalCar
. If auto delegate is enabled for BookRentalCar
, Alexa handles all the steps of the dialog and then sends your skill a finished IntentRequest
for BookRentalCar
. When the dialog completes, your skill gets the single IntentRequest
with dialogState
set to COMPLETED
.
To trigger the second dialog, return Dialog.Delegate
with updatedIntent
set to the new intent. If the new intent is also configured with auto delegate, Alexa handles the entire dialog and your skill again receives a single IntentRequest
with dialogState
set to COMPLETED
when it is finished
See Change the intent or update slot values during the dialog.
Manually delegate to alter the conversation at run-time
Use the Dialog.Delegate
directive when you need more flexibility during the dialog. Your skill receives an IntentRequest
for each turn of the conversation, so your code can make run-time decisions and take other actions before delegating. This is useful for building a more natural conversational flow for more complex dialogs.
Some scenarios that benefit from manual delegation include:
- You need to set defaults for required slots to avoid asking the user for information your service already has.
- You need to make more complex run-time decisions based on the user's responses and use a mix of delegation and manual control of the dialog.
See the following sections for examples of these scenarios.
Manually delegate the dialog to set default values
A PlanMyTripIntent
intent has a fromCity
slot to collect the user's starting city. This slot is required to fulfill the request, but the skill stores the user's preferred default starting city because this usually does not change. If the user has saved this default in your system, auto delegation would ask the user for their starting city every time, which is not a good user experience.
Instead, your code can update the incoming intent to set the fromCity
to a default value, then delegate the dialog to Alexa. Alexa skips the prompts for that slot and continues with the next step in the dialog:
User: Alexa, tell Plan My Trip that I want to visit Portland (Alexa sends the skill an IntentRequest
with the PlanMyTripIntent
intent the value 'Portland' in toCity
but no value in fromCity
.)
The skill looks up the user and determines that their normal default city is "Seattle". Therefore, the skill returns a Dialog.Delegate
directive with updatedIntent.slots.fromCity
set to Seattle
.
Alexa: When are you starting this trip? (Alexa skips the prompts to collect fromCity
because it is now filled, and continues with the remaining slots.)
Interaction continues. Alexa continues to use the prompts to collect the travel date, travel mode, and other information about the trip…
Alexa: OK, so I'm saving your trip from Seattle to Portland on December tenth. (Note that the skill has the fromCity
slot value, even though the user was not asked during this interaction.)
This dialog would work for different scenarios:
- If the user starts the interaction by specifying a city,
fromCity
is filled with that value and the default is not used. - If the user has not previously set a default city, the
fromCity
slot is left empty, so Alexa does prompt the user according to the dialog model.
To create an interaction like this, you would do the following:
- Configure the relevant slots on the
PlanMyTripIntent
intent as required slots (toCity
,fromCity
, andtravelDate
) and provide prompts. - Disable auto delegation for the
PlanMyTripIntent
intent. - Add code to your skill to default the
fromCity
slot when it is not provided and then delegate the rest of the dialog to Alexa.
You can use separate handlers in your code to do this, for example:
StartedPlanMyTripHandler
– handlesPlanMyTripIntent
requests wheredialogState
isSTARTED
.- Check for a value in the
fromCity
slot. If the slot is empty, get the user's normal default starting city and updates thefromCity
slot value on the intent. - Return
Dialog.Delegate
and pass along the updated intent in the directive'supdatedIntent
property. - See Update Slot Values and Confirmation Status During the Dialog for more about changing slot values when returning
Dialog.Delegate
.
- Check for a value in the
InProgressPlanMyTripHandler
– handles requests wheredialogState
isIN_PROGRESS
. Just returnDialog.Delegate
for all requests.CompletedPlanMyTripHandler
– handlePlanMyTripIntent
requests wheredialogState
isCOMPLETED
. Because the dialog is complete, the intent sent to this handler always has all required slots filled in. Use the slot values to complete the user's request.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
const StartedPlanMyTripHandler = {
canHandle(handlerInput){
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' &&
request.intent.name === 'PlanMyTripIntent' &&
request.dialogState === 'STARTED';
},
handle(handlerInput){
const currentIntent = handlerInput.requestEnvelope.request.intent;
let fromCity = currentIntent.slots.fromCity;
// fromCity.value is empty if the user has not filled the slot. In this example,
// getUserDefaultCity() retrieves the user's default city from persistent storage.
if (!fromCity.value) {
currentIntent.slots.fromCity.value = getUserDefaultCity();
}
// Return the Dialog.Delegate directive
return handlerInput.responseBuilder
.addDelegateDirective(currentIntent)
.getResponse();
}
};
const InProgressPlanMyTripHandler = {
canHandle(handlerInput) {
const request = handlerInput.requestEnvelope.request;
return request.type === 'IntentRequest' &&
request.intent.name === 'PlanMyTripIntent' &&
request.dialogState === 'IN_PROGRESS';
},
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 === 'PlanMyTripIntent' &&
request.dialogState === 'COMPLETED';
},
handle(handlerInput) {
// All required slots are filled when this intent is triggered,
// so assemble the data into a response about the trip...
},
};
This code example uses the Alexa Skills Kit SDK for Java.
// Each of these handlers is a separate Java class. For brevity,
// the package and import declarations for each class are not shown.
/**
* *****************************************
* StartedPlanMyTripHandler class
* *****************************************
*/
public class StartedPlanMyTripHandler implements IntentRequestHandler {
@Override
public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
return (handlerInput.matches(intentName("PlanMyTripIntent"))
&& intentRequest.getDialogState() == DialogState.STARTED);
}
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
System.out.println("In StartedPlanMyTripHandler");
Intent intent = intentRequest.getIntent();
Slot fromCitySlot = intent.getSlots().get(FROM_CITY_SLOT_NAME);
if (fromCitySlot.getValue() == null){
// getValue returns null if the user has not filled the
// slot. In this example, getUserDefaultCity() retrieves
// the user's default from persistent storage.
Slot updateSlot = Slot.builder()
.withName(FROM_CITY_SLOT_NAME)
.withValue(getUserDefaultCity())
.build();
// Push the updated slot into the intent object
intent.getSlots().put(FROM_CITY_SLOT_NAME, updateSlot);
}
// Return the Dialog.Delegate directive
return handlerInput.getResponseBuilder()
.addDelegateDirective(intent)
.build();
}
}
/**
* *****************************************
* InProgressPlanMyTripHandler class
* *****************************************
*/
public class InProgressPlanMyTripHandler implements IntentRequestHandler {
@Override
public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
return (handlerInput.matches(intentName("PlanMyTripIntent"))
&& intentRequest.getDialogState() == DialogState.IN_PROGRESS);
}
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
System.out.println("In InProgressPlanMyTripHandler");
return handlerInput.getResponseBuilder()
.addDelegateDirective(intentRequest.getIntent())
.build();
}
}
/**
* *****************************************
* CompletedPlanMyTripHandler class
* *****************************************
*/
public class CompletedPlanMyTripHandler implements IntentRequestHandler {
@Override
public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
return (handlerInput.matches(intentName("PlanMyTripIntent"))
&& intentRequest.getDialogState() == DialogState.COMPLETED);
}
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
System.out.println("In CompletedPlanMyTripHandler");
// All required slots are filled when this intent is triggered,
// so assemble the data into a response about the trip...
}
}
Combine delegation and manual control to handle complex dialogs
A skill for ordering drinks from a coffee shop has an OrderIntent
intent with several slots to collect information about the type of drink the user wants to order. The drink
slot is configured with slot validation to ensure that the drink the user orders is on the menu. The intent has additional slots that must be filled in depending on the value of drink
:
coffeeRoast
if thedrink
is “coffee”teaType
if thedrink
is “tea.”
In this case, the skill needs to make decisions about what values to elicit during the interaction. To manage this, your skill can return Dialog.Delegate
to collect and validate the drink
slot, then manually handle the dialog to fill coffeRoast
and teaType
.
User: Alexa, tell My Coffee Shop to start my order
Alexa: Would you like coffee or tea?
User: shoes (Alexa sends the skill an IntentRequest
with the OrderIntent
. The drink
slot contains the invalid value shoes
.)
Because the dialog is not complete, the skill returns Dialog.Delegate
.
Alexa: Shoes is not an item on the menu. Which you would like, coffee or tea? (Alexa responds with a prompt defined in the slot validation rules for the drink
slot.)
User: Coffee (Alexa sends the skill the OrderIntent
with drink
set to coffee
.)
Now that the drink is determined, the skill takes over the dialog and uses Dialog.ElicitSlot
to ask for the coffeeRoast
value.
Alexa: Which roast would you like, light, medium, medium-dark, or dark? (Prompt provided as part of the Dialog.ElicitSlot
directive.)
Interaction continues…
To create an interaction like this, you would do the following:
- Configure the
drink
slot on theOrderIntent
intent as a required slot and provide prompts to ask the user for this value. The drink-specific slots (coffeeRoast
andteaType
) are not required. - Enable slot validation rules for the
drink
slot. This can use the Accept only the Slot type's values and synonyms rule, assuming the custom type for the slot includes values and synonyms for all the drinks on the menu. - Turn off auto delegation for
OrderIntent
. - Add code to delegate incomplete dialogs where
drink
is not yet provided. - Add code to ask for relevant slots based on the value of
drink
. This uses theDialog.ElicitSlot
directive:- Elicit a value for
coffeeRoast
whendrink
is "coffee". - Elicit a value for
teaType
whendrink
is "tea".
- Elicit a value for
You can use separate handlers to respond to the intent depending on the state of the dialog and the value of the drink
slot:
CoffeeGivenOrderIntentHandler
– handlesOrderIntent
requests wheredrink
is "coffee", butcoffeeRoast
has no value. ReturnsDialog.ElicitSlot
to ask for the coffee roast.TeaGivenOrderIntentHandler
– handlesOrderIntent
requests wheredrink
is "tea", butteaType
has no value. ReturnsDialog.ElicitSlot
to ask for the tea type.-
StartedInProgressOrderIntentHandler
– handlesOrderIntent
requests wheredialogState
is not completed. ReturnsDialog.Delegate
. This ensures that thedrink
slot is filled with a valid drink.In the ASK v2 SDKs, you must register this handler after the coffee and tea handlers to ensure that
StartedInProgressOrderIntentHandler
is used only if none of the other handlers apply. CompletedOrderIntentHandler
– handlesOrderIntent
requests wheredialogState
isCOMPLETED
. At this point, the intent includes values for thedrink
slot and eithercoffeeRoast
orteaType
.
This code example uses the Alexa Skills Kit SDK for Node.js (v2).
const StartedInProgressOrderIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "OrderIntent"
&& handlerInput.requestEnvelope.request.dialogState !== 'COMPLETED';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.addDelegateDirective()
.getResponse();
}
};
const CoffeeGivenOrderIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "OrderIntent"
&& handlerInput.requestEnvelope.request.intent.slots.drink.value
&& handlerInput.requestEnvelope.request.intent.slots.drink.value === 'coffee'
&& !handlerInput.requestEnvelope.request.intent.slots.coffeeRoast.value
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak('Which roast would you like light, medium, medium-dark, or dark?')
.reprompt('Would you like a light, medium, medium-dark, or dark roast?')
.addElicitSlotDirective('coffeeRoast')
.getResponse();
}
};
const TeaGivenOrderIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "OrderIntent"
&& handlerInput.requestEnvelope.request.intent.slots.drink.value
&& handlerInput.requestEnvelope.request.intent.slots.drink.value === 'tea'
&& !handlerInput.requestEnvelope.request.intent.slots.teaType.value
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak("Which would you like black, green, oolong, or white tea?")
.reprompt("Would you like a black, green, oolong, or white tea?")
.addElicitSlotDirective('teaType')
.getResponse();
}
};
const CompletedOrderIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest"
&& handlerInput.requestEnvelope.request.intent.name === "OrderIntent"
&& handlerInput.requestEnvelope.request.dialogState === "COMPLETED";
},
handle(handlerInput){
const drink = handlerInput.requestEnvelope.request.intent.slots.drink.value;
let type;
if (drink === 'coffee') {
type = handlerInput.requestEnvelope.request.intent.slots.coffeeRoast.value;
} else if (drink === 'tea') {
type = handlerInput.requestEnvelope.request.intent.slots.teaType.value;
} else {
type = 'water';
}
const speechText = `It looks like you want ${type} ${drink}`;
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
}
};
This code example uses the Alexa Skills Kit SDK for Java.
// Each of these handlers is a separate Java class. For brevity,
// the package and import declarations for each class are not shown.
/**
* *****************************************
* StartedInProgressOrderIntentHandler class
* *****************************************
*/
public class StartedInProgressOrderIntentHandler implements IntentRequestHandler {
@Override
public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
return handlerInput.matches(intentName("OrderIntent"))
&& intentRequest.getDialogState() != DialogState.COMPLETED;
}
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
System.out.println("In StartedInProgressOrderIntentHandler");
return handlerInput.getResponseBuilder()
.addDelegateDirective(intentRequest.getIntent())
.build();
}
}
/**
* *****************************************
* CoffeeGivenOrderIntentHandler class
* *****************************************
*/
public class CoffeeGivenOrderIntentHandler implements IntentRequestHandler {
@Override
public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
Slot coffeeRoastSlot = intentRequest.getIntent().getSlots().get(COFFEE_ROAST_SLOT_NAME);
return handlerInput.matches(intentName("OrderIntent"))
&& handlerInput.matches(slotValue(DRINK_SLOT_NAME, "coffee"))
&& coffeeRoastSlot.getValue() == null;
}
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
System.out.println("In CoffeeGivenOrderIntentHandler");
String speeechtext = "Which roast would you like, light, medium, medium-dark, or dark?";
String repromptText = "Would you like a light, medium, medium-dark, or dark roast?";
return handlerInput.getResponseBuilder()
.withSpeech(speeechtext)
.withReprompt(repromptText)
.addElicitSlotDirective(COFFEE_ROAST_SLOT_NAME, intentRequest.getIntent())
.build();
}
}
/**
* *****************************************
* TeaGivenOrderIntentHandler class
* *****************************************
*/
public class TeaGivenOrderIntentHandler implements IntentRequestHandler {
@Override
public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
Slot teaTypeSlot = intentRequest.getIntent().getSlots().get(TEA_TYPE_SLOT_NAME);
return handlerInput.matches(intentName("OrderIntent"))
&& handlerInput.matches(slotValue(DRINK_SLOT_NAME, "tea"))
&& teaTypeSlot.getValue() == null;
}
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
System.out.println("In TeaGivenOrderIntentHandler");
String speeechtext = "Which would you like, black, green, oolong, or white tea?";
String repromptText = "Would you like a black, green, oolong, or white tea?";
return handlerInput.getResponseBuilder()
.withSpeech(speeechtext)
.withReprompt(repromptText)
.addElicitSlotDirective(TEA_TYPE_SLOT_NAME, intentRequest.getIntent())
.build();
}
}
/**
* *****************************************
* CompletedOrderIntentHandler class
* *****************************************
*/
public class CompletedOrderIntentHandler implements IntentRequestHandler {
@Override
public boolean canHandle(HandlerInput handlerInput, IntentRequest intentRequest) {
return handlerInput.matches(intentName("OrderIntent"))
&& intentRequest.getDialogState() == DialogState.COMPLETED;
}
@Override
public Optional<Response> handle(HandlerInput handlerInput, IntentRequest intentRequest) {
System.out.println("In CompletedOrderIntentHandler");
Map<String, Slot> slots = intentRequest.getIntent().getSlots();
String drink = slots.get(DRINK_SLOT_NAME).getValue();
System.out.println("Value of drink slot is: " + drink);
String drinkType = "";
if (drink.equals("coffee")){
drinkType = slots.get(COFFEE_ROAST_SLOT_NAME).getValue();
} else if (drink.equals("tea")){
drinkType = slots.get(TEA_TYPE_SLOT_NAME).getValue();
} else {
drinkType = "water";
}
String speechText = String.format(
"It looks like you want %1$s %2$s.",
drinkType,drink);
return handlerInput.getResponseBuilder()
.withSpeech(speechText)
.withShouldEndSession(true)
.build();
}
}
Configure the delegation strategy for your skill and intents
Every skill has a skill-level Auto Delegation setting. This option can be either enabled or disabled. Auto Delegation is enabled by default for a new skill.
Each intent that has a dialog model has an Dialog Delegation Strategy setting. This can be set to one of three options:
- enable auto delegation: use auto delegation for this intent, regardless of the overall skill delegation strategy.
- disable auto delegation: do not use auto delegation for this intent, regardless of the overall delegation strategy.
- fallback to skill strategy: use the Auto Delegation setting for the overall skill. This is the default for an intent when you initially add a dialog model to the intent.
The Dialog Delegation Strategy setting for an intent always takes precedence over the skill-level Auto Delegation setting. For example, if Auto Delegation is enabled for the skill, but the Dialog Delegation Strategy is disabled for a particular intent, delegation is not used for that intent.
Set the overall auto delegation option for the skill
Set the skill-level Auto Delegation option to the setting you plan to use for the majority of your intents, then override it at the intent level where necessary.
- In the developer console, navigate to Build > Custom > Interfaces.
- Enable or disable the Auto Delegation option, then click Save Interfaces. Be sure to click Build Model to re-build your interaction model.
You can also set the auto delegation option in the JSON for your interaction model.
The skill-level Auto Delegation setting is ignored for intents that do not have a dialog model.
Override the skill auto delegation strategy for an intent
The Dialog Delegation Strategy option is disabled for intents that do not have a dialog model.
- Click an intent from the left-hand navigation to open the detail page for the intent.
- Under Dialog Delegation Strategy, select the strategy you want to use for this intent.
You can also set the auto delegation option for an intent in the JSON for your interaction model.
JSON for auto delegation in the dialog model (Interaction Model Schema)
You can see and edit the JSON representation of the auto delegation options within your dialog model in the JSON Editor.
The auto delegation option for the overall skill is defined in interactionModel.dialog.delegationStrategy
.
The auto delegation setting for an intent is set in interactionModel.dialog.intents[].delegationStrategy
. Note that this property is not present if the intent is set to fallback to skill setting.
In the following example, the overall Auto Delegation setting for the skill is turned off. This example shows three intents with dialog models. The IntentWithAutoDelegation
intent overrides the skill setting. The IntentWithoutAutoDelegation
intent explicitly turns off auto delegation, which is redundant with the overall skill setting in this case. The IntentFallbackToSkillSetting
intent falls back to the skill setting so delegationStrategy
is not present.
For brevity, the languageModel
and prompts
properties are not shown. For details about the interaction model JSON, see Interaction Model Schema.
{
"interactionModel": {
"dialog": {
"delegationStrategy": "SKILL_RESPONSE",
"intents": [
{
"name": "IntentWithAutoDelegation",
"delegationStrategy": "ALWAYS",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "planet",
"type": "Planet",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.227876833021.1360336347514"
},
"validations": [
{
"type": "isNotInSet",
"prompt": "Slot.Validation.227876833021.1360336347514.650882724620",
"values": [
"sun",
"the sun",
"our sun"
]
},
{
"type": "hasEntityResolutionMatch",
"prompt": "Slot.Validation.227876833021.1360336347514.445874299877"
}
]
}
]
},
{
"name": "IntentWithoutAutoDelegation",
"delegationStrategy": "SKILL_RESPONSE",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "color",
"type": "AMAZON.Color",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.199336742512.1106707015044"
}
}
]
},
{
"name": "IntentFallbackToSkillSetting",
"confirmationRequired": false,
"prompts": {},
"slots": [
{
"name": "name",
"type": "AMAZON.FirstName",
"confirmationRequired": false,
"elicitationRequired": true,
"prompts": {
"elicitation": "Elicit.Slot.789417862303.645497121610"
}
}
]
}
]
}
}
}
Related Topics
- Define the Dialog to Collect and Confirm Required Information
- Dialog Interface Reference
- Validate Slot Values
- Handle Requests Sent by Alexa
Last updated: Nov 28, 2023