Conditional Expressions in the Alexa Conversations Description Language
In the Alexa Conversations Description Language (ACDL), you can use conditional expressions to create branches in the conversational flow that your dialog samples describe. Conditional expressions reduce the need to write variations of a conversational flow that differ only based on some conditional logic. With conditional expressions, samples can describe multiple desired flows for conversational experiences.
Syntax
Conditional expressions follow an if
, else if
, and else
chaining syntax. The expression in the condition
must be of type com.amazon.alexa.schema.Boolean
. The if
, else if
, and else
follow the
expression block syntax, type, and name-scoping rules. The types of all the expression blocks in the same conditional expression must match.
conditionalExpr
: IF LPAREN expression RPAREN blockExpression (ELSE (conditionalExpr | blockExpression)) ?
;
The following example shows the minimum possible conditional expression.
if (<condition>)
<expression-block>
A conditional expression can have zero or more else if
conditions as follows.
if (<condition>)
<expression-block>
else if (<condition>)
<expression-block>
else
<expression-block>
You can nest conditional expressions as follows.
if (<condition>)
<expression-block>?
if (<condition>)
<expression-block>
else
<expression-block>
<expression-block>?
else
<expression-block>
Example
An example use case for conditional expressions is to specify the response Alexa gives in
conditions such as failure or success. In the following example, the response in the conversational
flow differs depending on whether the getWeather()
action returns a forecast versus nothing
.
sample {
weatherRequest = expect(Invoke, getWeatherEvent)
ensure(
RequestArguments {arguments = [getWeather.arguments.cityName], response = request_city_prompt},
RequestArguments {arguments = [getWeather.arguments.date], response = request_date_prompt}
)
weatherResult = getWeather(weatherRequest.cityName, weatherRequest.date)
if (weatherResult != nothing) {
response(weather_prompt, Notify {actionName = getWeather, success = true}, payload = WeatherResultPayload {weatherResult = weatherResult})
} else {
response(bye_prompt, Bye {})
}
}
Restrictions on conditional expressions
-
Every block expression in a conditional expression must contain a
response<T>()
action. -
The Boolean expression in the condition must reference at least one result from a previous external action invocation and can only reference names from the previous external action invocations.
The following example shows an invalid conditional expression.// An invalid example sample { bookFlightRequest = expect(Invoke, BookFlightEvent) ensure( RequestArguments {arguments = [searchFlights.arguments.fromCity], response = fromCityPrompt}, RequestArguments {arguments = [searchFlights.arguments.toCity], response = toCityPrompt}, RequestArguments {arguments = [searchFlights.arguments.startDate], response = startDatePrompt} ) searchResult = searchFlights(bookFlightRequest.fromCity, bookFlightRequest.toCity, bookFlightRequest.startDate) // This is invalid because the name used in the condition's boolean expression refers to a name that does not result from a previous API invocation. It refers to a name from an expect() action call. if (bookFlightRequest != nothing) { ... } else { ... } }
-
Either a
response<T>()
action or another conditional expression must come before any external (user-defined) action invocation or event in a conditional block expression.
The following examples contain valid conditional expressions.if (condition) { payload = SearchResultPayload {result = searchResult} act = Notify {actionName = searchFlights} // Alexa response or another conditional expression must come before the next external action invocation or event expression response(informBookingResponse, act, payload) } else { ... }
if (condition) { payload = SearchResultPayload {result = searchResult} act = Notify {actionName = searchFlights} // Another conditional expression can come before the first Alexa response if (anotherCondition) { response(informBookingResponse, act, payload) } else { ... } } else { ... }
if (condition) { // This is allowed because it is a natively supported action, not an external action x = size(list) ... } else { ... }
The following example shows an invalid conditional expression that violates this rule.
// An invalid example if (condition) { // This is invalid because an event expression comes before the response<T>() flightDetail = expect(Inform, InformOrdinalEvent) confirmAction(confirmFlightBooking, bookFlight, SearchResultPayload {searchResult = searchResult}) expect(Affirm, affirmEvent) bookingDetail0 = bookFlight(searchResult, flightDetail.ordinal) response(informBookingResponse, Notify {actionName = bookFlight, success = true}, payload = BookingDetailPayload {itinerary = bookingDetail0}) } else { ... }
-
The first response act in a conditional block expression must be the
Notify
response act. This rule includesresponse<T>()
actions that chainNotify
with additional response acts.// An invalid example sample { bookFlightRequest = expect(Invoke, BookFlightEvent) ensure( RequestArguments {arguments = [searchFlights.arguments.fromCity], response = fromCityPrompt}, RequestArguments {arguments = [searchFlights.arguments.toCity], response = toCityPrompt}, RequestArguments {arguments = [searchFlights.arguments.startDate], response = startDatePrompt} ) searchResult = searchFlights(bookFlightRequest.fromCity, bookFlightRequest.toCity, bookFlightRequest.startDate) if (searchResult.status == "success") { response(informBookingResponse, Notify {actionName = searchFlights}) } else { // This is invalid because this response act is not a Notify response act response(confirmFlightBooking, ConfirmAction {actionName = bookFlight}) } }
-
The type of the conditional expression is the same as the type of the first expression block. Therefore, the final expression in each of the conditional expression's block expressions must have the same type.
// An invalid example // The types of the two block expressions do not match. The first block returns type SearchFlightsResult // and the second block returns type BookingDetail if (condition) { ... searchResult = searchFlights(bookFlightRequest.fromCity, bookFlightRequest.toCity, bookFlightRequest.startDate) } else { ... bookingDetail = bookFlight(searchResult, flightDetail.ordinal) }
Related topics
- Expressions in the Alexa Conversations Description Language
- About Alexa Conversations Description Language
Last updated: Nov 27, 2023