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

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 an IntentRequest for each turn of the conversation.
    • The request indicates the current state of the dialog with the dialogState set to STARTED, IN_PROGRESS, or COMPLETED.
    • 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 with dialogState set to COMPLETED.

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 the GetPlanetWeather 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.

Copied to clipboard.

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();
  }
};

Copied to clipboard.

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, and travelDate) 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 – handles PlanMyTripIntent requests where dialogState is STARTED.
    • Check for a value in the fromCity slot. If the slot is empty, get the user's normal default starting city and updates the fromCity slot value on the intent.
    • Return Dialog.Delegate and pass along the updated intent in the directive's updatedIntent property.
    • See Update Slot Values and Confirmation Status During the Dialog for more about changing slot values when returning Dialog.Delegate.
  • InProgressPlanMyTripHandler – handles requests where dialogState is IN_PROGRESS. Just return Dialog.Delegate for all requests.
  • CompletedPlanMyTripHandler – handle PlanMyTripIntent requests where dialogState is COMPLETED. 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.

Copied to clipboard.

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...
  },
};

Copied to clipboard.

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 the drink is “coffee”
  • teaType if the drink 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 the OrderIntent intent as a required slot and provide prompts to ask the user for this value. The drink-specific slots (coffeeRoast and teaType) 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 the Dialog.ElicitSlot directive:
    • Elicit a value for coffeeRoast when drink is "coffee".
    • Elicit a value for teaType when drink is "tea".

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 – handles OrderIntent requests where drink is "coffee", but coffeeRoast has no value. Returns Dialog.ElicitSlot to ask for the coffee roast.
  • TeaGivenOrderIntentHandler – handles OrderIntent requests where drink is "tea", but teaType has no value. Returns Dialog.ElicitSlot to ask for the tea type.
  • StartedInProgressOrderIntentHandler – handles OrderIntent requests where dialogState is not completed. Returns Dialog.Delegate. This ensures that the drink 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 – handles OrderIntent requests where dialogState is COMPLETED. At this point, the intent includes values for the drink slot and either coffeeRoast or teaType.

Copied to clipboard.

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();
  }
};

Copied to clipboard.

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.

  1. In the developer console, navigate to Build > Custom > Interfaces.
  2. 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.

  1. Click an intent from the left-hand navigation to open the detail page for the intent.
  2. 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"
              }
            }
          ]
        }
      ]
    }
  }
}

Was this page helpful?

Last updated: Nov 28, 2023