Configure Composite Bag Entities

Composite bag entities allow you to write much shorter, more compact dialog flow definitions because they can be resolved using just one component (either Resolve Entities or a Common Response).

We recommend that you use this approach, because you don't need components like Switch or Set Variable to capture all of the user input that's required to perform some business transaction. Instead, a single component can prompt users to provide values for each item in the bag. The prompts themselves are condition-specific because they're based on the individual configuration for each bag item. Using the composite bag entity, an entity event handler or Apache FreeMarker, and either Common Response or Resolve Entities components, your skill can:
  • Capture all free text, allow file uploads, and collect the user's current location with the STRING, ATTACHMENT, and LOCATION items.

  • Execute individual behavior for each member entity in the bag–You can add value-specific prompts and error messages for individual entities within the composite bag (which includes custom entities, system entities, and the STRING, ATTACHMENT, and LOCATION items). You can also control which entities should (or shouldn't) match the user input. Because you can create a prompt sequence, the skill can output different prompts for each user attempt.

  • Present multi-select pick lists.

  • Validate value matches based on validation rules.

  • Support for the unhappy flow–Users can correct prior entries.

  • Execute temporary, match-based transitions–The dialog flow can temporarily exit from the component when an entity has been matched, so that another state can perform a supporting function like a REST call. After the function completes, the dialog flow transitions back to the component so that the value matching can continue. For example:
    • After a user uploads a receipt, the receipt itself needs to be scanned so that values like expense date, amount, and expense type can be extracted from it for the other entities in the bag. This allows the component to fill the rest of values from the receipt, not from any user input.

    • The skill outputs a message like, “Almost there, just a few more questions” in between matching sets of entities in the bag.

    • The user input must be validated through a backend REST call. The validation might be required immediately, because it determines which of the bag items must prompt for further user input. Alternatively, the call might return information that needs to be shared with the user, like an out-of-policy warning.

  • Disambiguate values–You can isolate a value from the user input through entity-specific prompts and component properties. These include support for corrections to prior input (the “unhappy” flow) and for prompting user input for specific built-in entity properties.

Create a Composite Bag Entity

  1. Click Entities This is an image of the Entities icon. in the side navbar.

  2. Click Add Entities.

  3. Choose Composite Bag as the entity type.

  4. Enter the name and description.
  5. Click + Event Handler if you want to use execute the composite bag's prompting and logic programmatically using entity event handlers.
  6. Click + Bag Item to open the Add Bag Item dialog. If you’re adding a built-in entity or an existing custom entity, you can create a bag-specific name for it and add a description of its role within the context of the composite bag.

  7. You can fill the bag with custom entities, built-in entities, and the following:
    • STRING—Captures free text from the user.

    • LOCATION—Captures the user’s location.

    • ATTACHMENT—Accepts files, audio files, video, or image files uploaded by the user. The composite bag entity stores the URL where the attachment is hosted.

    Note:

    You are prompted for a subtype when you add the DATE_TIME entity.
    The items get resolved in the order that you add them. However, the sequence can be affected depending on how you configure individual members of the composite bag.
  8. Clicking Close returns you to the Entities page, but you can add other bag-specific capabilities to the item first (or update it later by clicking This is an image of the Edit icon. in the Entities page).

  9. Next steps:
    • Add individual error messages, disambiguation prompts, or conditional prompting for the bag items.

      Note:

      These will be overwritten if you add the entity to a composite bag.
    • Add the entity to an intent. See Add Entities to Intents.

    • Configure the dialog flow to use the composite bag entity..

Enhanced Slot Filling

When you enable enhanced slot filling by switching on Use Enhanced Slot Filling in Settings > Configuration:
  • Only the currently resolving item will be updated. When a match applies to more than one bag item, the currently resolving bag item takes precedence over other items. If you switch off enhanced slot filling, then all items are updated with the same value.
  • If the current resolving item is a STRING bag item, then no other bag items are ever updated.
  • If an entity match applies to multiple (non-resolving) bag items, a disambiguation dialog displays, allowing the user to choose which item should be updated instead of updating all bag items.
  • The entity's Prompt for Disambiguation switch is ignored. We recommend that you implement custom disambiguation with an entity event handler.

Note:

The Use Enhanced Slot Filling toggle is switched on by default for skills created using Version 22.08 of the platform. It's switched off for skills that have been upgraded to this version.

Add Prompts

You can add a single prompt, or create a sequence of prompts, each providing increasingly specific information for each time the user enters an invalid value. By default, prompting is enabled. To add these prompts:
  1. If you want to enable prompting, leave the Prompt for Value field blank (its default state). Entering false in the Prompt for Value field prevents prompting. To prompt for a conditional value, add a boolean FreeMarker expression that evaluates to either true (for prompting) or false.

    Tip:

    When you set Prompt for Value to false, the item can still be resolved as part of another item that’s being prompted for when you enable Out of Order Extraction.
  2. Click Add Prompt to build the prompt sequence. You can reorder it by shuffling the fields through drag and drop gestures, or by renumbering them. You can randomize the output of the prompts when you give two or more prompts the same number.

    Note:

    You can only add prompts for built-in entities when you add them to a composite bag.
    You can store prompts in resource bundles (for example, ${rb.askCheese}), or write them as combinations of text and FreeMarker expressions.

Updating Slotted Values with Apache FreeMarker Expressions

In the Updatable field, enter an Apache FreeMarker expression that evaluates to true to allow the value slotted for a composite bag item to be updated.

Enable Out-of-Order Extraction

Out of order extraction enables value slotting and updating for a composite bag item at any point in the conversation regardless of whether the composite bag has prompted the user for the value or not. Using the following rules, you can set how, when, or if, a value can slotted or changed at any point in the conversation for any item or item subtype (such as the DATE_TIME subtypes).
  • Always – The default option. When you choose this option for an item, its value can be slotted with no prompting. For example, the PizzaSize entity might be resolved when a customer enters I want a large pizza. This option also enables the item value to be changed at any point, provided that the expression in the Updatable property does not evaluate to false. For example, when the composite bag prompts for the PizzaType entity, the customer might then reply Veggie please, but make it a medium. The skill can update the PizzaSize entity value with medium without restarting the conversation because Always is enabled for the bag's PizzaSize and PizzaType items.

    Note:

    Although this option is the default behavior, it may not always be appropriate for STRING items. If you chose this option on for a STRING item, for example, the first user message would be stored by STRING item instead of getting matched by intended entity (which might be designated as the first item in the bag to get resolved).
  • Never – When you choose this option, the item is only slotted after it's been prompted for, even when other user messages contain valid values. Choose Never to prevent inadvertent matches.
  • Only when resolving the intent utterance – Restricts the out-of-order value slotting to the first user utterance that has been resolved to the intent that's associated with the composite bag entity.
Here are examples of the out-of-order extraction rules as they're applied to a PizzaToppings composite bag item.
Out of Order Extraction Rule Initial User Utterance Value Slotted Notes
Always Order pizza with tuna Tuna The value slotting for the PizzaToppings item can be matched whenever the user message contains the correct value ("Mushrooms instead!). It can be slotting or updated at any point in the conversation without prompting.
Never Order pizza with tuna None The value for PizzaTopping item cannot slotted out of order or updated ad hoc. It can only be matched when it's prompted for.
Only when resolving the intent utterance Order pizza with tuna Tuna. However, if the user entered "Order large pizza", the composite bag would have to prompt for the PizzaTopping value. The PizzaTopping item can be slotted out of order only when the first user utterance that resolves to an intent has a matching value. Otherwise, this value must be prompted for. The composite bag will not allow ad hoc updating or slotting of this item.

Enable Extract With

Use the Extract With option to enable your skill to resolve one bag item using the input entered for a second item in the bag. This option, which allows your skill to handle related values, provides greater flexibility for user input. Users can enter home instead of a full address, for example. Here's how:
  • The composite bag has two address-related entities: NamedAddress, a list value entity with values like home and office, and DeliveryAddress, an ADDRESS entity.
  • The DeliveryAddress entity's prompt is Where do you want that delivered?
  • The NamedAddress entity does not prompt for input (false is entered in the Prompt for Value field).
  • The NamedAddress entity can be extracted with DeliveryAddress (DeliveryAddress is selected from the Extract With menu).

When the composite bag prompts for the DeliveryAddress entity, it can resolve the entity using either a physical address, or one of the NamedAddress list values ( home or office).

Add Validation Rules

Each item in the bag can have its own validation rules. You can add a validation rule by first clicking +Validation Rule and then adding a FreeMarker expressions and a text prompt. The expression uses the following pattern to reference the item value, where varName is the name of the composite bag entity that’s declared as a context variable in the dialog flow definition:
${varName.value.itemName}
If this expression evaluates to false, then the user input is not valid.
The following example of a validation expression is for a item called Amount. It’s a built-in entity, CURRENCY. To return a number amount for the comparison, the expression adds the CURRENCY entity’s amount property:
${expense.value.Amount.amount > 4}
The corresponding validation message can also reflect the user input through a FreeMarker expression. For example, the following message uses the type of currency extracted from the user's input as part of the validation message:
Amounts below 5 ${expense.value.Amount.currency} cannot be expensed. Enter a higher amount or type 'cancel'.
To find out about other CURRENCY properties (and the other built-in entity properties as well), see Built-In Entities and Their Properties.

Configure a YAML Dialog Flow for Composite Bag Entities

If your skill is being developed in YAML dialog mode, here are the things you need to do to configure the dialog flow for composite bag entities:

  1. In the context node, declare the composite bag entity as a variable:
    ...
    metadata:
      platformVersion: "1.1"
    main: true
    name: "ExpenseBot"
    context:
      variables:
        expense: "Expense"
        iResult: "nlpresult"
  2. You can use System.ResolveEntities or System.CommonResponse. Both of these components let you leverage the composite bag entity and both provide their own benefits. The System.ResolveEntities is the simpler of the two, having a small set of properties. Unlike the System.ResolveEntities component, the System.CommonResponse provides you with more control over the UI that’s used to resolve the entities in the bag. For example, you can add conditional logic to determine prompts and value-related global actions.

    Tip:

    Because the metadata for the System.CommonResponse component can become very complex when you use composite bag entities, we recommend that you use the System.ResolveEntities component instead and use entity event handlers for any UI customizations.
  3. Reference the composite bag entity context variable in the component’s variable property and then define the other properties as needed. System.ResolveEntities and The Component Properties describe them and provide further examples.

    Here’s an example of the System.ResolveEntities component:
    createExpense:
        component: "System.ResolveEntities"
        properties:
          variable: "expense"
          useFullEntityMatches: true
          nlpResultVariable: "iResult"
          cancelPolicy: "immediate"
        transitions:
          actions:
            cancel: "cancelExpense"
          return: "done"          

The system.entityToResolve Variable

The system.entityToResolve variable provides information on the current status of the entity resolution process as performed by Resolve Entities and Common Response components. You will typically reference the properties of this variable value in the Common Response component metadata when you want to customize messages. You can use it to define the logic for an entity's error message, or for various properties that belong to the Resolve Entities and Common Response components. Append the following properties to return the current entity value:
  • userInput
  • prompt
  • promptCount
  • updatedEntities
  • outOfOrderMatches
  • disambiguationValues
  • enumValues
  • needShowMoreButton
  • rangeStartVar
  • nextRangeStart
You can also reference the properties in FreeMarker expressions used bag item properties like prompt, errorMessage and validation rules.
Here's an example of using this variable to return the current user input in an entity's error message:
Sorry,'${system.entityToResolve.value.userInput!'this'}' is not a valid pizza size.
Here's an example of using various system.entityToResolve definitions. Among these is a message defined for the text property, which confirms an update made to a previously set entity value using an Apache FreeMarker list directive and the updatedEntities property.
    metadata:
      responseItems:        
      - type: "text" 
        text: "<#list system.entityToResolve.value.updatedEntities>I have updated <#items as ent>${ent.description}<#sep> and </#items>. </#list><#list system.entityToResolve.value.outOfOrderMatches>I got <#items as ent>${ent.description}<#sep> and </#items>. </#list>"
      - type: "text" 
        text: "${system.entityToResolve.value.prompt}"
        actions:
        - label: "${enumValue}"
          type: "postback"
          iteratorVariable: "system.entityToResolve.value.enumValues"
For global actions, this variable controls the Show More global action with the needShowMoreButton, rangeStartVar, and the nextRangeStart properties:
        globalActions: 
        - label: "Show More"
          type: "postback" 
          visible:
            expression: "${system.entityToResolve.value.needShowMoreButton}"
          payload:
            action: "system.showMore"
            variables: 
              ${system.entityToResolve.value.rangeStartVar}: ${system.entityToResolve.value.nextRangeStart} 
        - label: "Cancel"
          type: "postback" 
          visible:
            onInvalidUserInput: true
          payload:
            action: "cancel"
The Show More label must include a system.showMore (action: "system.showMore"). Otherwise, it won't function.

entityToResolve Expressions

Expression Description
${system.entityToResolve.value.resolvingField} Returns the name of the bag item.
${system.entityToResolve.value.allMatches[0].entityName} Returns the entity name that's referenced by the bag item. The allMatches array contains all of the entities whose values could potentially be updated by the user's message.
${<variable>1.value[system.entityToResolve.value.resolvingField]} Returns the bag item value that users enter or select.
${system.entityToResolve.value.userInput} Returns the text entered by the user. You can use this expression to log the user input or display it in the chat, for example, when a user enters an invalid value.
${system.entityToResolve.value.outOfOrderMatches[n].entityName} Returns the name(s) of the entities that are extracted out-of-order. Along with the values that the Resolve Entities or the Common Response components prompt for, users may provide additional values that trigger out-of-order value extraction and updates to other entities in the composite bag.
${system.entityToResolve.value.outOfOrderMatches[n].name} Returns the name of the composite bag item.
${system.entityToResolve.value.outOfOrderMatches? has_content?then(…,…)} Returns the value of an entity that has been matched out of order. Because it's likely that no entity has been matched out of order, this expression uses the has_content operator.

Entity Event Handlers

You can execute validation, prompting, and disambiguation for the composite bag entity items programmatically using Entity Event Handlers. An Entity Event Handler (EEH) is a JavaScript (or TypeScript) implementation that's created for a composite bag entity and deployed as a custom code service.

Note:

You can manage the service deployed for the EEH from the Components page This is an image of the Components icon in the left navbar..
You can control the resolution behavior for both individual bag items and for the entity itself by defining the event handler functions provided by the bots-node-sdk. For example, the following snippet illustrates defining a validate event on a bag item called ExpenseDate that prevents users from entering a future date when filing an expense report.
ExpenseDate: {

        validate: async (event, context) => {
          if (new Date(event.newValue.date) > new Date()) {
            context.addValidationError("ExpenseDate",context.translate('ExpenseDate.text'));
            return false;
          }          
        }
The bots-node-sdk’s Writing Entity Event Handlers documentation describes the overall structure of the event handler code, the item- and entity-level events, and the EntityResolutionContext methods like addValidationError and translate in the above snippet.

Because Entity Event Handlers are written in JavaScript, you can use advanced logic that isn’t easily achieved – or even feasible – with the FreeMarker expressions that you can use to define the validation, errors, and prompts in the edit bag item page and the dialog flow. They’re also easier to debug. That said, you don't have to choose Entity Event Handlers over FreeMarker expressions. You can combine the two. For example, you can use FreeMarker expressions for simple validations and prompts and reserve an EEH for more complicated functions like calling a REST API when all of the bag items have been resolved.

Create Entity Event Handlers with the Event Handler Code Editor

You can build the EEH using the Event Handler Code editor that's accessed from the composite bag properties page or with the IDE of your choice. While the Event Handler Code editor has some advantages over a third-party tool, you may want to alternate with a third-party IDE depending on the size of the task and the libraries that you need. To weigh the pros and cons, refer to Which IDE Should I Use?

To access the Event Handler Code editor:
  1. Click + Event Handler.
  2. Complete the Create Event Handler dialog by adding a service name and a handler name.

After you've created the handler, you can open the editor by clicking This is an image of the Edit icon..

The editor is populated with starter code. Its handlers object contains entity, items, and custom objects. Within these objects, you define event-level events, which are triggered for the entire composite bag, the item-level events, which control the resolution of the individual bag items, and the custom events that are fired on postback actions. By default, the handler object has an entity object defined. The items and custom objects get populated when you add an item-level or custom template.
Description of eeh_default_template.png follows
Description of the illustration eeh_default_template.png

The events themselves are asynchronous JavaScript functions that take two arguments:
  • event: A JSON object of the event-specific properties.
  • context: A reference to the EntityResolutionContext class, whose methods (such as addValidationError in the following snippet) provide the event handler logic.
items: {
  Amount: { 
    validate: async (event, context) => {
      let amount = event.newValue.amount;
      if (amount < 5) {
        context.addValidationError("Amount",`Amounts below 5 ${event.newValue.currency} cannot be expensed. Enter a higher amount or type 'cancel'.`);
      }
    }
  }
You access the templates by clicking + Add Event.

Note:

Refer to the bots-node-sdk’s Writing Entity Event Handlers documentation for further information on the EEH starter code, item- and entity-level events, EntityResolutionContext, and code samples.
Add Events
Clicking + Add Event enables you to add the templates for event, item, and custom events.

For example, adding a validate event template populates the editor with the following code:
validate: async (event, context) => {
        
      },
You can then update this template with your own code:
validate: async (event, context) => {
     if (event.newValue.value === 'PEPPERONI')
       context.addValdiationError('Type', "Sorry, no pepperoni pizzas today!");     
      },
Clicking Validate checks your code for design time issues, so you should click this option regularly. You can’t add further events if the code is invalid, neither can you save invalid code. Because saving code means also deploying it, you can’t deploy invalid code either.

When your code is valid, clicking Save automatically deploys it and packages it in a TGZ file. You can monitor the status of the deployment and download the TGZ file for reuse in other skills from the Components page.

Tip:

To check for runtime errors, switch on Enable Component Logging and then review the logs (accessed by clicking Diagnostics > View Logs) to find about the parameters that invoked the events.
In the composite bag page, a Ready status This is an image of the Ready status icon. and an Edit icon Edit icon for revising your code becomes available after you’ve deployed the service.

Add Entity-Level Event Handlers
For entity-level, events, you can update the templates for the validate, publishMessage, maxPromptsReached, resolved, attachmentReceived, and locationReceived entity level events.

Event Description
validate A handler for entity-level validations that's called when the value for at least one of the bag items has been changed.
publishMessage A generic fallback handler that's called whenever a bag item lacks a prompt message or disambiguation handling.
maxPromptsReached A generic fallback handler when the item-specific handler for reaching the maximum number prompts has not been specified.
resolved This function gets called when the composite bag entity has been resolved. You would typically add a resolved event to call a backend API that completes a transaction related to the values collected by the composite bag entity. If API call returns errors because some the values collected by the composite bag are not valid, then you can clear these values.
attachmentReceived This handler is called when the user sends an attachment.
locationReceived This handler gets called when the user sends a location.
By default, the template is populated with an entity-level event, publishMessage. Through the updatedItemMessage and outOfOrderItemsMessage functions (which are also defined in the default template), this event enables the skill to output messages that confirm that a previously resolved bag item value has been updated, or that it has accepted valid input for a bag item other than the one that the entity is currently prompting for (out-of-order input).

This event is optional. You can delete it, leave it as is, or add functionality to it. For example, you can add a cancel button when a user’s attempts at entering a valid value have exceeded the maximum number of prompts.
publishMessage: async (event, context) => {
        updatedItemsMessage(context);
        outOfOrderItemsMessage(context);
        //Add Cancel button for invalid values entered by users
        let message = context.getCandidateMessageList()[0];
      }
…
message.addGlobalAction(context.getMessageFactory().createPostbackAction('Cancel', {action:'cancel'}));
        context.addMessage(message);      }
}
Add Item-Level Handlers
For the bag items listed in the dialog, you can add templates for the item level events: shouldPrompt, validate, publishPromptMessage, publishDisambiguateMessage, and MaxPromptsReached .

Event Description
shouldPrompt Prompts for an item based on the values of the other items in the bag. This handler takes precedence over the prompting configured through the Prompt for Value field.
validate This handler is called only when a value has been set for a bag item. If the validity of the value depends on other bag items, then you should implement the entity-level validate event instead.
publishPromptMessage Use this function to replace or extend the message that's generated by the Common Response and Resolve Entities components to prompt for the item.
publishDisambiguateMessage Use this function to replace or extend the disambiguation prompt message generated by the Common Response and Resolve Entities components.
maxPromptsReached This function gets called when the maximum number of prompts for this item, which specified by Maximum User Input Attempts the in the composite bag item screen, has been reached.

Adding an item-level event generates the items object.
Description of eeh_items_block.png follows
Description of the illustration eeh_items_block.png

Add Custom Events
You can create custom events that are called from postback actions (buttons or list items) using the custom event template.

Adding a custom template adds a custom object with the basic event code. Refer to the bots-node-sdk’s Writing Entity Event Handlers documentation for examples of implementing a custom event.
someCustomEvent: async (event, context) => {
  
}

Replace or Remove an Entity Event Handler

If you need to replace or remove an EEH:
  1. Select an empty line from the Event Handler menu to reactivate the + Event Handler button.

  2. Open the Components page This is an image of the Components icon in the left navbar.. Switch off Service Enabled or delete the service.

    Note:

    You can't delete or disable a service if the EEH is still associated with the composite bag entity.
  3. If needed, add a new EEH to the composite bag, or if you're not opting for a new EEH, you can add the resolution logic with FreeMarker expressions.

Tip:

Deleting the composite bag entity will also delete the service deployed for the EEH.

Which IDE Should I Use?

You can create an EEH using the IDE of your choice and then deploy the code using a TGZ file that you packaged manually with bots-node-sdk pack, or you can use the Event Handler Code editor that we provide. When you use our editor, you don’t have to set up your development environment or package and deploy your code. The code is deployed automatically after you save it. You can also revise the code directly without having to redeploy it, something that you can’t do when you package and deploy a handler created with your own IDE. You can't add additional NPM packages using Event Handler Code editor. You'll need another IDE. For example, if you want to use Moment.js to work with dates, then you must download the TGZ, add the library using the IDE of your choice, and then repackage and deploy the TGZ. After that, you can continue using the Event Handler Code editor.

Tip:

The Event Handler Code editor might be a better option for small changes. If you need to make bigger changes, or add additional NPM packages, then you can download the TGZ from the Components page, unzip it, and then use your favorite editor to modify the code before repackaging and deploying it.

Simplify Dialog Flows with Entity Event Handlers

Entity event handlers can simplify your dialog flow definition because they’re used with the dialog-shortening best practice that is composite bag entities. When it comes to backend services, they make your dialog flow definition less complicated because you don’t need to write a separate state for the custom component that calls them.

Event handlers simplify the dialog flow definition in another way: they enable you to modify the messages that are generated by the Resolve Entities component. For example, you can create a carousel of card messages without using the complex structure of the Common Response component metadata property. You can instead add the carousel through simple code, which means you can also add card responses to the Resolve Entities component. For example, this code enables the Resolve Entities component to output a horizontally scrolling carousel of cards for pizza type, with card each having a cancel button:
Type: {

        publishPromptMessage: async (event, context) => {
          let candidateMessage = context.getCandidateMessageList()[0];
          const mf = context.getMessageFactory();
          const message = mf.createCardMessage()
            .setLayout(horizontal)
            .setCards(context.getEnumValues().map(p => {
                      mf.createCard(p.value)
                        .setDescription(pizzaInfo[p.value].description)
                        .setImageUrl(pizzaInfo[p.value].image)
                        .addAction(mf.createPostbackAction('Order',{variables: {pizza: p.value}}));
                      })
            .setGlobalActions(candidateMessage.getGlobalActions());
          context.addMessage(message);
        }

Entity Event Handler Tutorials

Follow this tutorial to get acquainted with entity event handlers by creating one using the editor. Then check out this advanced tutorial for creating an entity event handler with an external IDE and bots-node-sdk.

Disambiguate Nested Bag Items and Subtypes

The composite bag will always prompt for values per the item order that's dictated by the hierarchical structure a nested bag item. It will not blindly slot values for multiple items. It instead attempts to match the value in the user message only to the item that it's currently prompting for. When the user input doesn't match the current item, or could potentially match more than one item, as might be the case for the startTime and endTime for an INTERVAL subtype, it presents users with the value defined for the Label property to clarify the requested input.

Tip:

As with all strings, we recommend that you define the Label value as a resource bundle.

Add the DATE_TIME Entity to a Composite Bag

To enable your skill to handle complex scenarios that require multiple user prompts like scheduling a meeting, or setting a recurring event, you need to create a DATE_TIME composite bag item and then configure the attributes of the Interval, Recurring, and Date and Time subtypes and their respective nested bag items.

Note:

While you can use the Date, Time and Duration as standalone entities, we recommend that you use them within composite bag entities.
  1. Before you create a DATE_TIME bag item, configure the date and time ambiguity resolution rules appropriate for your use case. For example, if you're creating an expense reporting skill, select Past. If the skill is a meeting scheduler, select Future.
  2. Within the composite bag entity, click Add item.
  3. Select Entity from the Type menu.
  4. Select DATE_TIME from the Entity Name menu.
  5. Choose a DATE_TIME subtype from the Subtype menu.

    The configuration options on the Add Bag Item page change depending on the subtype that you select. For example, if you select the Recurring subtype, then you can access configuration options for the nested bag items that are specific to setting a repeating event, such as the Date and Time object for the initial starting date and time and the Duration object for setting the event frequency.

  6. If you selected the Recurring or Interval subtypes:
    • Set the subtype values that the composite bag prompts for from the Prompt for menu.
    • Because meetings typically start and end on the same day, switch on Default end date to start date for the startDate subtype. This sets the end date as equal to the start date when the user message does not mention the end date (or when the end date is not extracted out of order).
      This is an image of the Default start date to end date toggle.

  7. Optionally add a disambiguation label if the user input can match more than one subtype.

    Tip:

    You can also configure the properties that are not DATE_TIME-specific, such as enhanced slot filling, updating slotting values with Apache FreeMarker, custom prompts, and error messages.
  8. You can access subtype-level configuration by clicking a subtype. Use the traversal to return to the item-level configuration.
    This is an image of the Edit Bag Item traversal.

  9. Next steps:
    • Associate the composite bag entity with the intent.
    • Declare a variable for the entity in the dialog flow.
    • In the dialog flow, reference the composite bag entity with the DATE_TIME item using a Resolve Composite Bag state.
    • The DATE_TIME values are represented as ISO 8601. For user-friendly output, use the Apache FreeMarker .xs built-in. In the following snippet, the value for the Time subtype is formatted using .value?time.xs?string['hh:mm a'].
      Your pizza will be delivered at ${pizza.value.deliveryTime.value?time.xs?string['hh:mm a']}.
      
      Instead of referencing the DATE_TIME item as a string, you can follow the best-practice approach of referencing it in a resource bundle, such as DeliveryMessage in the following example.
      ${rb('DeliveryMessage','time',pizza.value.deliveryTime.value?time.xs?string['hh:mm a'])}
      
      For the DeliveryMessage resource bundle message, the value is rendered through the {time} parameter:
      Your pizza will be delivered at {time}.
      

Tutorial: Real-World Entity Extraction with Composite Bag Entities

You can get a hands-on look at creating a composite bag through this tutorial: Enable Real-World Entity Extraction with Composite Bag Entities.