Use Actions in the Alexa Conversations Description Language

In the Alexa Conversations Description Language (ACDL), an action represents some aspect of the skill's behavior, such as asking the user a question ("Which city?"), fulfilling a task by invoking a back-end API ("In Seattle, it's a high of 65 degrees and a low of 50 degrees."), and so on. Alexa Conversations trains a model that, during runtime, predicts one or more actions depending on the events it observes. For details about the role of events and actions in describing the conversational flow, see How ACDL works with Alexa Conversations.

While you declare action signatures in ACDL, you implement your actions outside of ACDL, such as in AWS Lambda. You use your declared actions in dialog samples to represent the invocation of the corresponding skill behavior.

To use actions in ACDL, you do the following two things:

The Alexa Conversations Core Library (ACCL) provides built-in actions. For details, see Actions in the ACCL.

Declare an action

You declare actions by using one of the following forms.

action ReturnType <action_name>()
action ReturnType <action_name>(Type arg)
action ReturnType <action_name>(Type arg1, Type arg2, ...)
action ReturnType <action_name>(Type arg = <default_expression>, ...)

You can only declare an action in namespace scope. The action declaration must contain a ReturnType. If the action doesn't return anything, set the return type to Nothing.

Optional arguments

An ACDL action declaration can provide a default expression for one or more of its arguments, making the argument optional. Later, if the action invocation in a dialog sample omits the argument, the ACDL compiler uses the default expression. Currently, ACDL only supports Nothing as a default expression.

You can't follow optional arguments by required arguments in an action declaration.

In the following example, the getWeather() action signature has two optional arguments, date and includeRainInfo. The cityName argument is required because it doesn't have a default expression.

action WeatherResult getWeather(US_CITY cityName, DATE date = nothing, Boolean includeRainInfo = nothing)

Variable arguments

You can declare an action to take a variable number of arguments of the same type.

The ensure() action declared in the com.amazon.alexa.ask.conversations namespace is an example of an action that can take a variable number of arguments.

Currently, ACDL only supports variable arguments for built-in actions, which are declared in the Alexa Conversations Core Library (ACCL). You can't use variable arguments with custom actions that you declare.

Examples of action declarations

The following example shows an action declaration that declares the response() action, which accepts a Response argument, two ResponseAct arguments, and a Thing argument. The action produces nothing as a result. The nextAct and payload arguments have default expressions of Nothing and are optional, because they include a default expression.

namespace com.amazon.alexa.ask.conversations

import com.amazon.alexa.schema.Thing
import com.amazon.alexa.schema.Nothing

action Nothing response(Response response, ResponseAct act, ResponseAct nextAct = nothing, Thing payload = nothing)

The following is an example of an action declaration that declares the getWeather() action, which accepts a US_CITY and a DATE as arguments, and produces a WeatherResult result.

namespace org.weatherbot.dialogs

import com.amazon.ask.types.builtins.AMAZON.US_CITY
import com.amazon.ask.types.builtins.AMAZON.DATE
import org.weatherbot.types.WeatherResult

action WeatherResult getWeather(US_CITY cityName, DATE date)

Use the action in a dialog sample

You use actions in dialog samples by using function-call notation. You can provide arguments by position and by name. When you provide arguments by name, you can change the order of the arguments. When you provide both named and unnamed arguments, you must put the unnamed arguments before the named arguments.

sample {
  name = action(arg1 = <expression>, arg2 = <expression>, ...)
}

If you don't provide argument names, the ACDL compiler attempts to add them by using the argument matching rules. For example, consider the following use of the getWeather() expression.

sample {
  ...
  forecast = getWeather(utterance.city, utterance.date)
  ...
}

The ACDL compiler converts the previous declaration to the following.

sample {
  ...
  forecast = getWeather(cityName = utterance.city, date = utterance.date)
  ...
}

If you leave out an optional argument, you must name the subsequent arguments. In the following example, the optional argument time is left out of the action invocation, so any subsequent arguments (in this case, state) must be named. You can provide the arguments before time (that is, city and date) by position as usual.

action WeatherResult getWeather(US_CITY cityName, DATE date, TIME time = nothing, US_STATE state = nothing)

sample {
  ...
  forecast = getWeather(utterance.city, utterance.date, state = utterance.state)
  ...
}

Argument matching

When you use an action, the ACDL compiler matches the arguments of the action against the arguments in the action declaration. The ACDL compiler matches unnamed arguments strictly by position and matches named arguments by their names. The compiler also checks the type compatibility of the matched arguments.

Consider the following action declaration.

Nothing myAction(Type1 param1, Type2 param2)

Consider the following use of the action declared previously.

sample {
  myAction(arg1, param2 = arg2)
}

arg1 is unnamed, so the compiler matches it against param1 due to its position. Because there are no more unnamed arguments, the compiler matches arg2 by the name param2.

Examples

The following example declares the getWeather() action in the same ACDL file as the dialog. The ACCL provides the response() action.

namespace org.weatherbot.dialogs

import com.amazon.ask.types.builtins.AMAZON.US_CITY
import com.amazon.ask.types.builtins.AMAZON.DATE
import org.weatherbot.types.WeatherResult
import prompts.weather_prompt

// Declaration of the getWeather action.
action WeatherResult getWeather(US_CITY cityName, DATE date = nothing, Boolean includeRainInfo = nothing)

// Example dialog sample that uses the getWeather action.
dialog Nothing MyDialog {
  sample {
    ...
    weatherResult = getWeather(city, date)
    response(weather_prompt, Notify {actionName = getWeather, success = true}, payload = {weatherResult = weatherResult})
    ...
  }
}

The following list contains additional examples of how to use the getWeather() action in a sample. Assume that city and tomorrow are named expressions of the appropriate types.

  • getWeather(city). The date and includeRainInfo arguments now refer to their default expressions. The cityName argument now refers to the same expression as city.

  • getWeather(city, tomorrow). The cityName argument refers to the same expression as city. The date argument refers to the same expression as tomorrow. The includeRainInfo now refers to its default expression from the action's declaration.

  • getWeather(city, includeRainInfo=false). The cityName argument refers to the same expression as city. The includeRainInfo refers to the false literal expression. The date argument refers to its default expression from the action's declaration.

  • getWeather(date = tomorrow, cityName = city). The cityName argument refers to the sample expression as city. The date argument refers to the same expression as tomorrow and then includeRainInfo refers to the default expression provided in the action's declaration.

The following example shows an invalid use of the getWeather() action:

  • getWeather(date = tomorrow, city). It isn't valid to provide an unnamed argument after a named argument.

Built-in actions

The ACCL declares actions that the simulator natively supports. These actions are declared in the com.amazon.alexa.ask.conversations namespace. For a list of built-in actions, see Actions in the ACCL.

ACDL representation of actions

ACDL provides syntax to declare Actions, but there's a type representation of actions as well. You can access the arguments of an action by using the arguments field of the action. These are internal types; you can't create these types explicitly. The corresponding type declarations from the ACCL are as follows.

// Type representation of an action
type Action<T : Arguments, R> {
  T arguments
}

type Arguments {
}

// Type representation of an action Argument.
type Argument<T> {
  optional T defaultExpression
}

For example, consider the following declaration for the searchFlights() action.

action SearchFlightResult searchFlights(City fromCity, City toCity, DATE startDate, DATE returnDate)

ACDL internally represents the previous declaration as a name of type Action as follows.

// The compiler creates a type of "someInternalName"
type someInternalName : Arguments {
  Argument<City> fromCity
  Argument<City> toCity
  Argument<DATE> startDate
  Argument<DATE> returnDate
}

searchFlights = Action<someInternalName> {
  arguments = someInternalName {
    fromCity = Argument<City> {},
    toCity = Argument<City> {},
    startDate = Argument<DATE> {},
    returnDate = Argument<DATE> {}
  }
}