External Events

You can define application event types (based on events produced by external applications) and enable users of your digital assistants to be notified when events of those types are passed to the digital assistant.

These event types must follow the Cloud Events specification, which defines common formats for event data to make it interoperable across services, platforms, and systems. You can read about that specification at https://cloudevents.io/.

Workflow for Implementing an Application Event

  • Identify the source of the event.
  • In Digital Assistant, register the event type.
  • Configure a skill to consume events of that event type and add that skill to a digital assistant.
  • Create an Events channel and map it to the digital assistant.
  • From the created Events channel, get the inbound URL and secret key and make them available to the external app that generates the events.
Note

The skill that consumes the event can be part of multiple digital assistants.

Define an Event Type

For a skill to be able to receive a Cloud event, an event type must be defined in Oracle Digital Assistant. To define an event type:

  1. Click icon to open the side menu to open the side menu, select Development > Events, click New Event, and enter a name for the event type.

    Tip:

    You should use a naming convention for the event types to give them meaningful context to help other developers understand what they do. One simple example is pizza.order for an event type for pizza orders.
  2. On the page for the just-created new event, fill in a description.
  3. In the JSON Schema field enter the schema for the event.

    The field is pre-populated with an example schema that contains required elements.

    • The schema attribute can have one of the following values:
      • "http://json-schema.org/draft-04/schema#"
      • "http://json-schema.org/draft-06/schema#"
      • "http://json-schema.org/draft-07/schema#"
      • "http://json-schema.org/draft/2019-09/schema#"
    • In the properties object, you define properties as key-value pairs, where the value is a schema that the property is validated against.

      For example:

      "properties": {
          "firstName": {
            "type": "string",
            "description": "The person's first name."
          },
          "lastName": {
            "type": "string",
            "description": "The person's last name."
          },
          "age": {
            "description": "Age in years which must be equal to or greater than zero.",
            "type": "integer",
            "minimum": 0
          }
        }

      See https://json-schema.org/understanding-json-schema/reference/object.html for more on defining these properties.

  4. When you have finished work on the schema and want to freeze its contents, click Mark as Finalized.

    At this point, you can use this event type in a skill.

    If you later determine that you need change the schema, you can create a new version of it.

Example: Cloud Event Type Schema

{
   "$schema":"http://json-schema.org/draft-07/schema#",
   "description":"Pizza Order Schema",
   "title":"Pizza Order Schema",
   "type":"object",
   "properties":{
      "size":{
         "description":"The pizza size",
         "type":"string"
      },
      "orderid":{
         "description":"The pizza orderid",
         "type":"string"
      },
      "type":{
         "description":"The pizza type",
         "type":"string"
      },
      "topping":{
         "description":"The pizza topping",
         "type":"string"
      }
   }
}

Configure a Skill to Consume an Event

These are the general steps you need to follow for a skill to consume an event:

  1. In a skill, create a flow with the Notify User component to consume the event. (This component is only available for dialog flows developed in Visual mode.)

    At runtime, when the event is generated, the event is passed to the skill. You can use expressions to access the event's data and context.

  2. If you are designing the event type to target specific authenticated users (with IDCS user IDs), make sure that the skill has an Authorize using OAuth 2.0 component and that you have enabled channel account linking.
  3. In the Main Flow of the dialog flow, create an Application Event mapping between the event and the flow containing the User Notification state for the event.
  4. Add the skill to a digital assistant.

Create a User Notification for the Event

For the skill to respond to the event, you add a flow for that event and use a Notify User state to display a message when the event occurs:

  1. In the skill that you want to use the event, click Flows icon and then click + Add Flow.
  2. Enter a flow name and click Create.
  3. Click the menu The Add State menu icon. in the flow start, then click Add Start State to open the Add State dialog.
    The Add Start State option.

  4. Select Service Integration > Notify User, fill in a name for the state, and click Insert.
  5. In the property inspector for the inserted Notify User state, select the Component tab and fill in the Notification Message field with a message that you want the user to see when the event occurs.

    In the message, you can make use of expressions in the following format to access data from the event:

    ${skill.system.event.value.application.data.<propertyName>}
    Note

    You can also access context information from the event using the following type of expression:
    ${skill.system.event.value.application.context.<attributeName>}
    See Event Context Attributes for information on the available context attributes.
  6. Optionally, fill in the User ID property with an ID for a specific user that you are able to dynamically determine from within the flow (such as through a custom component). This property is mainly useful if the user ID is not sent in the event payload and the user is a unified user that has been authenticated through an Authorize using OAuth 2.0 component where the Associate With Unified User property has been set to true. See Configuring Unified User Identity for more on unified users.

Determine the Event Receipient from the Flow

If the event needs to be targeted to a specific user but that user isn't specified in the event itself, it may be possible to determine the user in the flow that handles the event. Here are the general steps to make that work:

  1. At the beginning of the flow that handles the event, add a custom component that determines the user ID (based on the event payload and/or some custom logic) and assigns that ID to a variable.
  2. After the state for the custom component, insert a Notify User component, and set that component's User ID property to the variable returned by the custom component.

Create a Handler for the External Event

For a skill to receive an event, you create an event handler for that event in the Main Flow. In the event handler, you map the event to the flow containing the Notify User state that you created to receive the event:

  1. In the list of flows, select Main Flow.
  2. On the Events tab of that flow, next to the Application Events section, click Add Application Event icon.
  3. In the Create Application Event Handler dialog, select the event type, the version of the event type, and the flow that you want to map the event to, and then click Close.
    Note

    Only finalized event types are offered in the Unresolved Event Type field.

Add the Skill to a Digital Assistant

For a skill to consume an external event, it must be part of a digital assistant. To add a skill that is configured to consume an event to a digital assistant:

  1. Click icon to open the side menu to open the side menu, select Development > Digital Assistants, and double-click the digital assistant that you want to use.
  2. Click Add Skill.

  3. In the tile for the skill that is configured to consume the event, select checkbox for adding skill .

    If you don't find the skill you are looking for, it might have a language mode that is not compatible with the language mode of your digital assistant. See Conditions for Adding a Skill to a Digital Assistant.

  4. Click the Done button to close the Skills Catalog and display the page for the skill in the digital assistant.
  5. Scroll down to the Interaction Model section of the page and make sure that the Invocation value is the name that you want users to use to invoke the skill.

    This name should adhere to these Invocation Name Guidelines.

  6. Provide some example utterances that would be typical of how a user would invoke the skill.

    These utterances will be used as selectable options in the digital assistant's default welcome and help states.

Tip:

Click Validate and review the validation messages for utterances that are shared by skills registered to your digital assistant.

Create a Channel for the External App

You need to create an application channel to allow the external app to send events to Digital Assistant. After you create the channel, Digital Assistant assigns a secret key and an inbound URL. You need to use these values in the app that generates the event.

  1. In Digital Assistant, click Channels in the left menu and then select Events.
  2. Click Add Channel.
  3. In the Channel Name field, enter a unique name for the channel.
  4. (Optional) In the Outbound Application URL field, enter a web service URL to which you want to any channel-related error messages to be sent via a POST request.

    If an error occurs, such as a problem with initiating a conversation through the user channel, then Digital Assistant sends an error message as a Cloud event and the event data contains code and message attributes that describe the error. For example:

    {
      "code": "InvalidParameter",
      "message": "The event contains invalid or missing attributes: firstName"
    }
  5. Click Create.
  6. Switch Application Enabled to On.
  7. From the Route To dropdown, select the digital assistant that contains the skill that has the flow for consuming the event.
  8. Make a note of the secret key and inbound URL.

    These will be needed by the external app that generates the events. The external app sends messages by sending POST request to the inbound URL and uses the secret key to authenticate its POST requests.

Generate an Event from an External App

To send events to a digital assistant from an external application, the application must create a POST request to the inbound URL for the event channel where:
  • There is an X-Hub-Signature header containing an SHA-256 hash of the request body using the application channel's secret key. For example:
    X-Hub-Signature: sha256=<HMAC SHA-256 signature of body using the secret key for the channel>
  • The content type is application/cloudevents+json.

The event payload can be either in a structured form (where all attributes are part of the JSON in the HTTP body) or in binary form (where event context attributes are present in the header with the ce- prefix). To learn more about these forms, see https://github.com/cloudevents/spec/blob/v1.0/http-protocol-binding.md#3-http-message-mapping.

Structured Form for Sending Events

The following example shows the use of structured form for sending events:

curl --location --request POST 'https://<server>/events/v2/listeners/appevent/channels/<id>' \
--header 'Content-Type: application/cloudevents+json' \
--header 'X-Hub-Signature: sha256=<SHA256 encoded request body using the channel's secret key>' \
--data-raw \

'{
    "specversion": "1.0",           //Version # of Digital Assistant's Events support
    "type": "<event_name>",         //The event type that the skill is listening for
    "source": "< event source>",    //URI-reference - identifies the context in which an event happened
    "id": "<event id>",             //Unique id for the event
    "version":"<event version>",    //An extension attribute(not part of CloudEvent spec) for the version # of the event type
    "data": {                       //The business data that matches with the schema defined for the event  
           
          }
}'

Form for Sending Events in Node.js

async pushEvent(eventName, eventVersion, userId, channelName, eventData){
  try {

    // Build event data
    const event = {
      specversion: "1.0",           //Version # of Digital Assistant's Events support
      type: eventName, // Name of Event you created in ODA
	  source: "< event source>",    //URI-reference - identifies the context in which an event happened
      id: "<event id>",             //Unique id for the event
      time: "2022-09-07T21:19:24Z", // Any Date value will do now
      channelname: <channelName>,   // Can be set to System_Global_Test if you want to test in tester
      version: <eventVersion>, // version of the event that you defined in Digital Assistant
      userid: <userId>,
      datacontenttype: "application/json",
      data: <eventData> // JSON object represting your payload which should confirm to the event's JSON schema
    };

    // Build Required headers
    const headers = {
      "X-Hub-Signature" : this._buildSignatureHeader(event, <EVENTS_CHANNEL_SECRET_KEY> , "utf8"),
      "Content-Type" : "application/cloudevents+json"
    };

    // POST to EVENT_LISTENER_CHANNEL_URL
    ....
    
  } catch (error) {
    logger.error(error.message);
    const errorMessage = `Error pushing event [ ${eventData} ] to Digital Assistant`;
    logger.debug(errorMessage);

    throw new Error(error.message);	
  }
}



_buildSignatureHeader(body, secret, encoding) {
  const buf = Buffer.from(JSON.stringify(body), "utf8");
  return "sha256=" + this._buildSignature(buf, secret, encoding);
}

_buildSignature(buf, secret, encoding) {
  const hmac = crypto.createHmac("sha256", Buffer.from(secret || "", encoding || "utf8"));
  if (buf) {
    hmac.update(buf);
  }
  return hmac.digest("hex");
}

Event Payload Attributes

The following are common attributes that you might use in an event payload:

  • specversion: (Required) Version number of Digital Assistant's Events support. Currently, the only valid value is 1.0.
  • type: (Required) The event type that the skill is listening for. This needs to correspond with the name of the event type that you specified in the Define an Event Type task.
  • source: (Required) Identifies the context in which an event happened. This can be a free-form string.
  • id: (Required) The unique ID that is generated for the event by the application.
  • version: (Required) The name of the version of the type of event being sent. You must include a value for this attribute in the event payload and it must match the value you provided for the event type version that you provided in the Create a Handler for the External Event task.
    Note

    This attribute is one of the extension attribute, meaning that it is not part of CloudEvent spec.
  • data: (Required) The business data that matches with the schema defined for the event.

Event Context Attributes

For each event that is generated, Digital Assistant adds extension attributes that describe the context in which the event is generated. Tools and application codes can then use this information to identify things like the source of the generated events and their relationship to other events. You can also specify values for these attributes in the event payload.

Here's a list of the extension attributes (all of which are of type String):

  • version: The name of the version of the type of event being sent. You must include a value for this attribute in the event payload and it must match the value you provided for the event type version that you provided in the Create a Handler for the External Event task.
  • userid: The ID of the user that message is being targeted to. It can take one of the following two forms:
    • An Oracle Identity Cloud Service (IDCS) user ID. In this case, you also need to include the usertenancy attribute in the payload.
    • A user ID provided by the channel. In this case, you also need to include the channelname attribute in the payload.
      Note

      For Twilio, this value would be the user's mobile phone number.
  • usertenancy: The name of the IDCS tenancy of the user's identity provider.
  • channelname: The name of the channel through which the digital assistant is exposed.
  • tenancy: The name of the Oracle Cloud Infrasture tenancy for the Digital Assistant instance. (Typically, you wouldn't need to explicitly include this attribute since information about the tenancy is passed in the request headers.)

Example: Event Payload

{
    "specversion": "1.0",
    "type": "com.pizzastore.pizza.ordercreated",
    "source": "pizzastore/orders",
    "id": "12345678-90ab-cdef-1234-567890abcdef",
    "time": "2022-08-10T12:31:00Z",
    "contenttype": "application/json",
    "tenancy": "mydigitalassistantinstance",
    "version": "1.0",
    "data": {"size": "Large",
            "type": "Veg"
          }
}

Example: Payload with IDCS User ID

If you need to pass the IDCS user ID for the user in the payload, you'd also specify the userid and usertenancy attributes:

{
    "specversion": "1.0",           //Version # of Digital Assistant's Events support
    "type": "<event_name>",         //The event type that the skill is listening for
    "source": "< event source>",    //URI-reference - identifies the context in which an event happened
    "id": "<event id>",             //Unique id for the event
    "version":"<event version>",    //An extension attribute(not part of CloudEvent spec) for the version # of the event type
    "userid":"<idcs user id>",      //An extension attribute(not part of CloudEvent spec) for the user ID  
    "usertenancy":<idcs tenancy>",  //Extension attribute, IDCS
    "data": {                       //The business data that matches with the schema defined for the event  
           
          }
}
Note

If the event is designed to pass the IDCS user ID in its payload, make sure that the skill has an Authorize using OAuth 2.0 component and that its Associate With Unified User property is set to True.

Example: Payload with User ID and Channel Name

For digital assistants exposed through the Twilio and Web channels, the external app can also notify users by specifying the channel name and the user ID that is provided by the channel.

{
    "specversion": "1.0",            //Version # of Digital Assistant's Events support
    "type": "<name_of_event_type>",  //The event type that the skill is listening for
    "source": "< event source>",     //URI-reference - identifies the context in which an event happened
    "id": "<event id>",              //Unique id for the event
    "version":"<event version>",     //An extension attribute(not part of CloudEvent spec) for the version # of the event type
    "userid":"<channel user id>",    //An extension attribute(not part of CloudEvent spec) for the user ID
    "channelname":"<channel name>",  //Name of the channel through which the digital assistant is exposed
    "data": {                        //The business data that matches with the schema defined for the event  
           
          }
}

Publish an Event from a Skill

In addition to consuming external events in a skill, you can use the skill to publish events of types that you have registered in Oracle Digital Assistant to an external application. You can do so with the Publish Event component (in the Service Integration category). When an event is generated this way, it is published to the URL that you have specified in the Outbound Application URL that you have specified in the channel for the external app.