Uh oh! We couldn’t find any match.

Please try other search keywords.

Bixby Developer Center

Guides

Effects

Suppose your capsule performs a search action on behalf of the user, such as finding a restaurant with specific criteria, and the action returns no results. While you can have Bixby report the lack of results to the user, you might want to relax the search constraints and try again. You might increase the search radius for restaurants, or drop the requirement for a price range. Relaxing includes modifying or dropping an input, or even prompting the user for more or different information. You might also want to perform similar operations in the case of an error or during input validation. These operations, which modify the plan and change its execution, are effects.

Handling Empty Output

When an action's output is empty, such as a search action that returns no results, you can use an on-empty block to apply effects that can change the plan's execution.

For example, a FindRestaurants action that searches by name might widen its search region when no results are found. This on-empty block checks to see if the search region's radius is under 100 units (kilometers or miles, depending on the user's settings) and, if so, replaces the search region input with a new, larger one:

action (FindRestaurants) {
type (Search)
description (An action that finds restaurants matching some search criteria)
collect {
input (searchRegion) {
type (viv.geo.SearchRegion)
min (Required) max (One)
}
input (name) {
type (RestaurantName)
min (Optional) max (One)
}
}
output (Restaurant) {
on-empty {
if (searchRegion.searchType == 'PointRadius' &&
searchRegion.pointRadius.radius.magnitude < 100) {
replace (searchRegion) {
intent {
goal { viv.geo.SearchRegion }
value { $expr (searchRegion.pointRadius.centroid) }
value {
geo.SearchRadius {
unit: $expr (searchRegion.pointRadius.radius.unit)
magnitude { geo.DistanceMagnitude(100.0) }
}
}
}
}
}
}
}
}

You can use the following child keys in an on-empty block:

  • drop: Drop the specified input from an action.
  • halt: Halt execution completely, displaying an error message.
  • prompt: Prompt the user for a new input value.
  • replace: Replace an existing input value with a new one.
  • replan: Restart the planner, using a new intent.
  • unlock: Pause execution if the device is unlocked and inform users they need to unlock it to continue.
  • flag-as-off-topic: Flag the current utterance as off-topic. (See Managing Prompts for details.)

Validating Input

Validation rules for inputs are defined in a validate block. These rules consist of conditionals and an effect to be applied if the condition is met. For example, Bixby might need to prompt for more information, or prompt the user to unlock their device. An airport search might check to make sure that at least one of the possible search fields is available and prompt the user if none of them are:

action (findAirport) {
type (Search)
collect {
// needs at least one of a search region, name, or airport code
input-group (oneOf) {
requires (OneOf)

collect {
input (searchRegion) {
type (geo.SearchRegion)
min (Optional) max (One)
}
input (name) {
type (AirportName)
min (Optional) max (One)
}
input (airportCode) {
type (AirportCode)
min (Optional) max (One)
}
}

validate {
if (!exists(searchRegion) && !exists(name) && exists(airportCode)) {
prompt
}
}
}
}

output (Airport) {
on-empty {
if (exists(airportCode) && exists(searchRegion)) {
drop (searchRegion)
}
}
}
}

Note that this also demonstrates the use of an on-empty block. If no results have been found and the user has provided an airport code, Bixby will drop the searchRegion and try the search again.

A validate block cannot replace or drop inputs, but the halt, prompt, replan, and unlock effects are available.

Catching Errors

Effects can also be used for handling errors. If your JavaScript action implementation throws an error, it can be caught by a throws block in your action model, with the effects to execute in an on-catch block.

output (Receipt) {
...
throws {
error (PaymentUnaccepted) {

property (vendorName) {
type (viv.business.BusinessName)
min (Required) max (One)
}
property (paymentType) {
type (viv.payment.PaymentType)
min (Required) max (One)
}
on-catch {
halt {
dialog {
template ("#{value(vendorName)} does not accept #{value (paymentType)}")
}
display (order)
}
}
}
}
}

All the effects available in an on-empty block are available in on-catch: drop, halt, prompt, replace, replan, unlock, and flag-as-off-topic.

Grouping Multiple Effects

By default, Bixby only executes the first qualifying effect in a block. If you need to run multiple effects, you can wrap them in an ordered-effects block.

output (Recipe) {
on-empty {
if (exists(course) || exists(meal) || exists(cuisine)) {
ordered-effects {
drop (course)
drop (meal)
drop (cuisine)
}
}
}
}

The effects will be executed sequentially, in the order declared. The ordered-effects block itself can only contain other effect keys: drop, halt, prompt, replace, replan, unlock, and flag-as-off-topic. You cannot use conditionals in an ordered-effects block, nor nest ordered-effects.

You can put ordered-effects blocks within on-empty and on-catch blocks, but not validate blocks.