25 Backend Integration

You can integrate skills with backend services, such as Oracle Human Capital Management Cloud and Oracle Financials Cloud, through custom components. For example, you might want to create a skill that lets your employees report their travel expenses to Oracle Financials Cloud.

To integrate a skill with a backend service:

  1. Implement: Using JavaScript and the Oracle Digital Assistant Node.js SDK, implement a custom component that transfers data to and from the skill using the SDK's metadata and conversation objects. See Task 1: Implement Custom Components.

  2. Deploy: If you are hosting the components on Oracle Mobile Hub backend, Oracle Functions, or a Node.js server, deploy the component package. See Task 2: Deploy the Component Package to a Service.

  3. Add to Skill: Make the components available to a skill by adding a component service for it. See Task 3: Add Component Package to a Skill.

Task 1: Implement Custom Components

To implement custom components, you use the Oracle Digital Assistant Node.js SDK to interface with Digital Assistant's custom component service.

Here's how to implement custom components that you can deploy to the Digital Assistant embedded container, Oracle Functions, a Mobile Hub backend, or a Node.js server:

  1. Install the software for building custom components.

  2. Create the custom component package.

  3. Create and build a custom component.

Note:

If you plan to deploy the custom component package to an embedded custom component service, each skill that you add the package to is counted as a separate service. There's a limit to how many embedded custom component services an instance can have. If you don't know the limit, ask your service administrator to get the embedded-custom-component-service-count for you as described in View Service Limits in the Infrastructure Console. Consider packaging several components per package to minimize the number of embedded component services that you use. If you try to add a component service after you meet that limit, the service creation fails.

Step 1: Install the Software for Building Custom Components

To build a custom component package, you need Node.js, Node Package Manager, and the Oracle Digital Assistant Bots Node.js SDK.

Note:

If you plan to deploy to the embedded container, your package should be compatible with the following versions:
  • For Oracle Digital Assistant instances that are provisioned on Oracle Cloud Infrastructure (sometimes referred to as the Generation 2 cloud infrastructure), your package should be compatible with Node.js 8.11.5 and Bots Node SDK 2.2.2.
  • For Oracle Digital Assistant instances that are provisioned on Oracle Cloud Platform (as all version 19.4.1 instances are), your package should be compatible with 8.11.4 and Bots Node SDK 2.2.0.
  1. If you haven’t already, download Node.js from https://nodejs.org and install it for global access. Node Package Manager (npm) is distributed with Node.js.

    To test if Node.js and npm are installed, open a terminal window and type these commands:

    node –v 
    npm –v
  2. To install the Oracle Digital Assistant Bots Node.js SDK for global access, enter this command in a terminal window:
    npm install -g @oracle/bots-node-sdk

    On a Mac, you use the sudo command:

    sudo npm install -g @oracle/bots-node-sdk

    When you use the -g (global) option, you have direct access to the bots-node-sdk command line interface. Otherwise, use npx @oracle/bots-node-sdk.

  3. To verify your Oracle Digital Assistant Bots Node.js SDK installation, type the following command:
    bots-node-sdk -v
    The command should print the Oracle Digital Assistant Bots Node.js SDK version.

Step 2: Create the Custom Component Package

To start a project, you use the bots-node-sdk init command from the SDK’s command line interface (CLI) to create the necessary files and directory structure for your component structure.

The init command has a few options, such as whether to use JavaScript (the default) or TypeScript, and what to name the initial component's JavaScript file. These options are described in CLI Developer Tools. Here's the basic command for starting a JavaScript project:

bots-node-sdk init <top-level folder path> --name <component service name>

This command completes the following actions for a JavaScript package:

  • Creates the top-level folder.

  • Creates a components folder and adds a sample component JavaScript file named hello.world.js. This is where you'll put your component JavaScript files.

  • Adds a package.json file, which specifies main.js as the main entry point and lists @oracle/bots-node-sdk as a devDependency. The package file also points to some bots-node-sdk scripts.

    {
      "name": "myCustomComponentService",
      "version": "1.0.0",
      "description": "Oracle Bots Custom Component Package",
      "main": "main.js",
      "scripts": {
        "bots-node-sdk": "bots-node-sdk",
        "help": "npm run bots-node-sdk -- --help",
        "prepack": "npm run bots-node-sdk -- pack --dry-run",
        "start": "npm run bots-node-sdk -- service ."
      },
      "repository": {},
      "dependencies": {},
      "devDependencies": {
        "@oracle/bots-node-sdk": "^2.2.2",
        "express": "^4.16.3"
      }
    }
  • Adds a main.js file, which exports the package settings and points to the components folder for the location of the components, to the top-level folder.

  • Adds an .npmignore file to the top-level folder. This file is used when you export the component package. It must exclude .tgz files from the package. For example: *.tgz.

  • For some versions of npm, creates a package-lock.json file.

  • Installs all package dependencies into the node_modules subfolder.

Note:

If you don't use the bots-node-sdk init command to create the package folder, then ensure that the top-level folder contains an .npmignore file that contains a *.tgz entry. For example:
*.tgz
spec
service-*

Otherwise, every time you pack the files into a TGZ file, you include the TGZ file that already exists in the top-level folder, and your TGZ file will continue to double in size.

If you plan to deploy to the embedded container, your package should be compatible with the following versions:

  • For Oracle Digital Assistant instances that are provisioned on Oracle Cloud Infrastructure (sometimes referred to as the Generation 2 cloud infrastructure), your package should be compatible with Node.js 8.11.5 and Bots Node SDK 2.2.2.
  • For Oracle Digital Assistant instances that are provisioned on Oracle Cloud Platform (as all version 19.4.1 instances are), your package should be compatible with 8.11.4 and Bots Node SDK 2.2.0.

Step 3: Create and Build a Custom Component

Here are the steps for building each custom component in your package:

  1. Create the component JavaScript file.

  2. Add code to the metadata and invoke functions.

  3. Access the backend.

  4. Use the SDK to access request and response payloads.

  5. Ensure that the component works in digital assistants.

Create the Component File

Use the SDK's CLI init component command to create a JavaScript or TypeScript file with the framework for working with the Oracle Digital Assistant Node.js SDK to write a custom component. The language that you specified when you ran the init command to create the component package determines whether a JavaScript or a TypeScript file is created.

For example, to create a file for the custom component, from a terminal window, CD to the package’s top-level folder and type the following command, replacing <component name> with your component's name:

bots-node-sdk init component <component name> c components

For JavaScript, this command adds the <component name>.js to the components folder. For TypeScript, the file is added to the src/components folder. The c argument indicates that the file is for a custom component.

Note that the component name can't exceed 100 characters. You can only use alphanumeric characters and underscores in the name. You can't use hyphens. Nor can the name have a System. prefix. Oracle Digital Assistant won't allow you to add a custom component service that has invalid component names.

For further details, see https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.md.

Add Code to the metadata and invoke Functions

Your custom component must export two objects:

  • metada: This provides the following component information to the skill.

    • Component name

    • Supported properties

    • Supported transition actions

    By default, the custom component supports the following properties. You don't need to add them to the metadata.

    • autoNumberPostbackActions: Boolean. Not required. When true, buttons and list options are numbered automatically. The default is false. See Auto-Numbering for Text-Only Channels.

    • insightsEndConversation: Boolean. Not required. When true, the session stops recording the conversation for insights reporting. The default is false. See Model the Dialog Flow.

    • insightsInclude: Boolean. Not required. When true, the state is included in insights reporting. The default is true. See Model the Dialog Flow.

    • translate: Boolean. Not required. When true, autotranslation is enabled for this component. The default is the value of the autotranslation context variable. See Translation Services in Skills.

  • invoke: This contains the logic to execute. In this method, you can read and write skill context variables, create conversation messages, set state transitions, make REST calls, and more. The invoke function takes two arguments:

    • context, which names the reference to the CustomComponentContext object in the Digital Assistant Node.js SDK. This class is described in the SDK documentation at https://oracle.github.io/bots-node-sdk/. Note that in earlier versions of the SDK, the name was conversation. You can use either name.
    • done, which is a callback that the component invokes when it has finished processing

Here’s an example:

'use strict';

module.exports = {

  metadata: {
    name: 'helloWorld',
    properties: {
      human: { required: true, type: 'string' }
    },
    supportedActions: ['weekday', 'weekend']
  },

  invoke: (context, done) => {
    // Retrieve the value of the 'human' component property.
    const { human } = context.properties();
    // determine date
    const now = new Date();
    const dayOfWeek = now.toLocaleDateString('en-US', { weekday: 'long' });
    const isWeekend = [0, 6].indexOf(now.getDay()) > -1;
    // Send two messages, and transition based on the day of the week
    context.reply(`Greetings ${human}`)
      .reply(`Today is ${now.toLocaleDateString()}, a ${dayOfWeek}`)
      .transition(isWeekend ? 'weekend' : 'weekday'); 
    done();  
  }
}

Bots Node SDK version 2.5.1 introduced an alternative syntax for the invoke function, which uses an async keyword instead of the done argument, as shown here.

  invoke: async (context) => {
    ...
    context.reply('hello world');
  }

To learn more as well as explore code examples, see Writing Custom Components in the Bots Node SDK documentation.

Control the Flow with keepTurn and transition

You use different combinations of the Bots Node SDK keepTurn and transition functions, as well as the call to done(), to define how the custom component interacts with a user and how the conversation continues after the component returns flow control to the skill.

  • keepTurn(boolean) specifies whether the conversation should transition to another state without first prompting for user input.

    Note that if you want to set keepTurn to true, you should call keepTurn after you call reply because reply implicitly sets keepTurn to false.

  • transition(action) causes the dialog to transition to the next state after all replies, if any, are sent. The optional action argument names that action (outcome) that the component returns.

    If you don't call transition(), then, when you invoke done(), the response is sent but the dialog stays in the state and subsequent user input comes back to this component. That is, invoke() is called again.

  • done() signals that the custom component request has been processed and that the server response should be sent. You must always call it once per invoke().

invoke: (context, done) ==> {
   ...
   context.reply(payload);
   context.keepTurn(true);
   context.transition ("success"); 
   done();
}

Here are some common use cases where you would use keepTurn and transition to control the dialog flow:

Use Case Values Set for keepTurn and transition

A custom component that transitions to another state without first prompting the user for input.

  1. If applicable, use context.reply(<reply>) to send a reply.

  2. Set context.keepTurn(true).

  3. Set context.transition with either a supportedActions string (e.g., context.transition("success")) or with no argument (e.g., context.transition()).

  4. Call done() to signal that the custom component request has been processed and the server response should be sent.

For example, this custom component updates a context variable with a list of values to be immediately displayed by a System.List component, which the skill has defined for the next state in the dialog flow definition.
invoke: (context, done) => {
    const listVariableName = context.properties().variableName;
    ...
    // Write list of options to a context variable
    context.variable(listVariableName, list);
   // Navigate to next state without 
   // first prompting for user interaction.
   context.keepTurn(true);
   context.transition();
   done();
 }

A custom component that enables the skill to wait for input after control returns to the skill and before the skill transitions to another state.

  1. If applicable, use context.reply(<reply>) to send a reply.

  2. Set context.keepTurn(false) .

  3. Set context.transition with either a supportedActions string(context.transition("success")) or with no arguments (context.transition()).

  4. Call done() to signal that the custom component request has been processed and the server response should be sent.

For example:
context.keepTurn(false);
context.transition("success");
done();
A custom component that gets user input without returning flow control back to the skill. For example:
  • A component passes the user input to query a backend search engine. If the skill can only accommodate a single result, but the query instead returns multiple hits, the component prompts the user for more input to filter the results. In this case, the custom component continues to handle the user input; it holds the conversation until the search engine returns a single hit. When it gets a single result, the component calls context.transition() to move on to another state as defined in the dialog flow definition.

  • A component processes a questionnaire and only transitions to another next state when all questions are answered.

  1. Do not call transition.

  2. Set keepTurn(false).

  3. Call done() to repeat the invocation.

For example, this custom component outputs a quote and then displays Yes and No buttons to request another quote. It transitions back to the skill when the user clicks No.
  invoke: (context, done) => {
    // Perform conversation tasks.
    const tracking_token = "a2VlcHR1cm4gZXhhbXBsZQ==";    
    var quotes = require("./src/Quotes.json");
    var quote = quotes[Math.floor(Math.random() * quotes.length)];
    
    // Check if postback action is issued. If postback action is issued, 
    // check if postback is from this component rendering. This ensures
    // that the component only responds to its own postback actions.     
    if (context.postback() && context.postback().token == tracking_token && context.postback().isNo) {
      context.keepTurn(true);
      context.transition();
      done();
    } else {
      // Show the quote of the day.
      context.reply("'" + quote.quote + "'");
      context.reply(" Quote by: " + quote.origin);
      // Create a single message with two buttons to 
      // request another quote or not.
      let actions = [];
      actions.push(context.MessageModel().postbackActionObject("Yes", null, { isNo: false, token: tracking_token }));
      actions.push(context.MessageModel().postbackActionObject("No", null, { isNo: true, token: tracking_token }));
      let buttonMessage = context.MessageModel().textConversationMessage("Do you want another quote?", actions, null);
      context.reply(buttonMessage);
      // Although reply() automatically sets keepTurn to false, 
      // it's good practice to explicitly set it so that it's
      // easier to see how you intend the component to behave.
      context.keepTurn(false);
      done();
    };
  }

If a component doesn’t transition to another state before it calls done(), then it needs to keep track of its own state, as shown in the above example.

For more complex state handling, such as giving the user the option to cancel if a data retrieval is taking too long, you can create and use a context variable. For example: context.variable("InternalComponentWaitTime", time). If you use a context variable, don't forget to reset it or set it to null before calling context.transition.

Note that as long as you don't transition, all values that are passed in as component properties are available, even after you call done().

The component invocation repeats without user input. For example:

  • A component pings a remote service for the status of an order until the status is returned as accepted or the component times out. If the accepted status is not returned after the fifth ping, then the component transitions with the failedOrder status.

  • The custom component hands the user over to a live agent. In this case, the user input and responses get dispatched to the agent. The component transitions to another state when either the user or the agent terminates their session.

  • Do not call transition.

  • Set context.keepTurn(true).

  • Call done() to repeat the invocation.

Here's a somewhat contrived example that shows how to repeat the invocation without waiting for user input, and then how to transition when done:
  invoke: (context, done) => {
    // Perform conversation tasks.   
    var quotes = require("./src/Quotes.json");
    var quote = quotes[Math.floor(Math.random() * quotes.length)];
    // Show 5 quotes of the day
    context.variable("InternalQuoteCount", 
        context.variable("InternalQuoteCount") + 1 || 1);
    if (context.variable("InternalQuoteCount") < 6) {
      // Show the quote of the day.
      context.reply("'" + quote.quote + "'");
      context.reply(" Quote by: " + quote.origin);
      // Don't prompt for user input
      context.keepTurn(true);
      // Don't transition. Start over to show another quote.
      done();
    } else {
      // Reset quote count
      context.variable("InternalQuoteCount", 0);
      // Transition to another state without prompting for user input
      context.keepTurn(true);
      context.transition();
      done();
    };
  }
Access the Backend

You'll find that there are several Node.js libraries that have been built to make HTTP requests easy, and the list changes frequently. You should review the pros and cons of the currently available libraries and decide which one works best for you. We recommend that you use a library that supports promises so that you can leverage the async version of the invoke method, which was introduced in version 2.5.1, and use the await keyword to write your REST calls in a synchronous way.

One option is the node fetch API that's pre-installed with the Bots Node SDK. Access the Backend Using HTTP REST Calls in the Bots Node SDK documentation contains some code examples.

Use the SDK to Access Request and Response Payloads

You use CustomComponentContext instance methods to get the context for the invocation, access and change variables, and send results back to the dialog engine.

You can find several code examples for using these methods in Writing Custom Components and Conversation Messaging in the Bots Node SDK documentation

The SDK reference documentation is at https://github.com/oracle/bots-node-sdk.

Ensure the Component Works in Digital Assistants

In a digital assistant conversation, a user can break a conversation flow by changing the subject. For example, if a user starts a flow to make a purchase, they might interrupt that flow to ask how much credit they have on a gift card. We call this a non sequitur. To enable the digital assistant to identify and handle non sequiturs, call the context.invalidInput(payload) method when a user utterance response is not understood in the context of the component.

In a digital conversation, the runtime determines if an invalid input is a non sequitur by searching for response matches in all skills. If it finds matches, it reroutes the flow. If not, it displays the message, if provided, prompts the user for input, and then executes the component again. The new input is passed to the component in the text property.

In a standalone skill conversation, the runtime displays the message, if provided, prompts the user for input, and then executes the component again. The new input is passed to the component in the text property.

This example code calls context.invalidInput(payload) whenever the input doesn’t convert to a number.

"use strict"
 
module.exports = {
 
    metadata: () => ({
        "name": "AgeChecker",
        "properties": {
            "minAge": { "type": "integer", "required": true }
        },
        "supportedActions": [
            "allow",
            "block",
            "unsupportedPayload"
        ]
    }),
 
    invoke: (context, done) => {
        // Parse a number out of the incoming message
        const text = context.text();
        var age = 0;
        if (text){
          const matches = text.match(/\d+/);
          if (matches) {
              age = matches[0];
          } else {
              context.invalidUserInput("Age input not understood. Please try again");
              done();
              return;
          }
        } else {
          context.transition('unsupportedPayload");
          done();
          return;
        }
 
        context.logger().info('AgeChecker: using age=' + age);
 
        // Set action based on age check
        let minAge = context.properties().minAge || 18;
        context.transition( age >= minAge ? 'allow' : 'block' );
 
        done();
    }
};

Here’s an example of how a digital assistant handles invalid input at runtime. For the first age response (twentyfive), there are no matches in any skills registered with the digital assistant so the conversation displays the specified context.invalidUserInput message. In the second age response (send money), the digital assistant finds a match so it asks if it should reroute to that flow.


Description of components-nonsequitur-conversation.png follows
Description of the illustration components-nonsequitur-conversation.png

You should call either context.invalidInput() or context.transition(). If you call both operations, ensure that the system.invalidUserInput variable is still set if any additional message is sent. Also note that user input components such as System.CommonResponse, System.Text, System.List, and System.ResolveEntities reset system.invalidUserInput.

Say, for example, that we modify the AgeChecker component as shown below, and call context.transition() after context.invalidInput().

if (matches) {  age = matches[0]; } else { 
      context.invalidUserInput("Age input not understood. Please try again"); 
      context.transition("invalid"); 
      context.keepTurn(true);
      done();
      return;
}

In this case, the data flow needs to transition back to askage so that the user gets two output messages – "Age input not understood. Please try again" followed by "How old are you?".

  askage:
    component: "System.Output"
    properties:
      text: "How old are you?"
    transitions: {}
  checkage:
    component: "AgeChecker"
    properties:
      minAge: 18
    transitions:
      actions:
        allow: "crust"
        block: "underage"
        invalid: "askage"

Run the Component Service in a Development Environment

During the development phase, you can start a local service to expose the custom component package.

  1. From the top-level folder, open a terminal window and run these commands to start the service:
    npm install
    npm start
  2. To verify that the service is running, enter the following URL in a browser:
    localhost:3000/components

    The browser displays the component metadata.

  3. If you have direct Internet access, you can access the development environment from a skill:
    1. Install a tunnel, such as ngrok or Localtunnel.
    2. If you are behind a proxy, go to http://www.whatismyproxy.com/ to get the external IP address of your proxy, and then, in the terminal window that you will use to start the tunnel, enter these commands:
      export https_proxy=http://<external ip>:80
      export http_proxy=http://<external ip>:80
    3. Start the tunnel and configure it to expose port 3000.
    4. In Oracle Digital Assistant, go to the skill's Components Components icon tab and add an External component service with the metadata URL set to https://<tunnel-url>/components.
      You can use any value for the user name and password.
You can now add states for the service's components to the dialog flow and test them from the skill's Preview page.

Task 2: Deploy the Component Package to a Service

You can host the custom component package from a Digital Assistant embedded container, Oracle Functions, Mobile Hub, or an external Node.js server. For embedded component services, you deploy the package when you create the service. For Oracle Functions, external Node.js server, and Mobile Hub services, you must first deploy the package to the service, as described here, before you add it to a skill as a component service.

Deploy to a Node.js Server

To host a custom component package on an external Node.js server, use the bots-node-sdk pack --service express CLI to copy your component package folders and make a few changes that are specific to Express, then install the component package and start it on your server.

  1. From the custom component package's top-level folder (the one that contains the main.js file), type this command in a terminal window:

    bots-node-sdk pack --service express

    The command does the following:

    • Copies the files and subfolders to service-express-<package version>.
    • Adds an index.js service wrapper.
    • Creates an api.js file, which is an Express wrapper for main.js.
    • Modifies the package.json file to set the main file to index.js and add the dependencies.

    This step shows the basic CLI command. For more information, see https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.md.

  2. Run these commands:

    npm install
    
    npm start

Deploy to Oracle Functions

You can deploy your custom component package to Oracle Functions.

Note:

This feature is not available for Digital Assistant instances that are paired with a subscription to a Fusion-based Oracle Cloud Applications service, such as HCM Cloud or Sales Cloud.

Here are the high-level steps:

  1. Get Artifact Names and Permissions for Oracle Functions Deployment

  2. Set Up Your User Account for Oracle Functions

  3. Set Up Your Local Machine for Oracle Functions

  4. Modify the Custom Component Package for Oracle Functions

  5. Deploy the Custom Components to Oracle Functions

Get Artifact Names and Permissions for Oracle Functions Deployment

Before you can deploy custom components to Oracle Functions, you need to obtain the names of the artifacts that are used for deployment, and you need to verify that you have permission to use them.

To set up your instance for Oracle Functions deployment, your tenancy administrator completed the steps in Setup and Policies for Oracle Functions. As part of the process, they created the following artifacts. Ask your administrator for their names, which you'll need when you complete the steps in Set Up Your User Account for Oracle Functions:

  • The names of the region and compartment to use for your functions.

  • The name of the compartment for the function application's virtual network (VCN). Typically, this is the same compartment as the one used for functions.

  • The name of the VCN to use for the function application.

Also, ask your administrator to verify that you belong to a group that has the necessary permissions for function developers, which includes access to these artifacts.

Set Up Your User Account for Oracle Functions

Before you can deploy custom component packages to Oracle Functions, you must complete these steps in the Oracle Cloud Infrastructure Console:

Note:

You'll need to know the name of the compartments and virtual network (VCN) to use and you'll need to belong to a group that allows function development as described in Get Artifact Names and Permissions for Oracle Functions Deployment.
  1. Sign into the Console and, in the top bar, select the region that the function-development compartment is in.

  2. Click Navigation menu icon on the top left to open the navigation menu, click Developer Services, and then, in the List Scope section, select the compartment that's been set up for function development.

  3. You'll deploy to Oracle Functions through the Oracle Cloud Infrastructure Registry. If you don't already have a registry repository that you can use, click Container Registry in the Developer Services section, and then click Create Repository.

    Give the repository a name, and then click Create Repository.

  4. If you don't have a functions application for your custom component packages, you'll need to create one. From the Developer Services section, click Functions, and then click Create Application. Provide a name, select a VCN, select at least one subnet, and click Create.

    If you don't see any VCNs to choose from, you might not be in the correct region.

    There are limits to the number of applications and functions. For the default limits, see Functions Limits in Oracle Cloud Infrastructure Documentation .

  5. Click the application that you use for function deployment, click Getting Started in the Resources section, and then click Local Setup.

    As shown in the following screenshot, the page displays several commands that you'll need to use to set up your local computer and to deploy your custom component package. Copy and save the commands for steps 3 through 7.

    You'll use these later after you've installed the required software on your local machine and are ready to deploy your custom components. Alternatively, bookmark this page so that you can return to it when you need to use the commands.

    Don't run these commands now. Just copy them.


    Description of fn-local-setup-commands.png follows
    Description of the illustration fn-local-setup-commands.png

  6. In your copied command that looks similar to the following, change [OCIR-REPO] to the name of your registry repository.

    fn update context registry phx.ocir.io/devdigital/[OCIR-REPO]
  7. Click the Profile icon in the top-right corner, and then click User Settings to go to the User Details page.

  8. In the next step you'll create a PEM file that you need to store in a .oci folder on your local machine. If your home folder on your local machine doesn't have this directory, create one from a terminal window.

    • Linux and Mac:

      cd ~
      mkdir .oci
    • Windows:

      cd C:\Users\<your-user-name>
      mkdir .oci
  9. You need a public and private PEM file for secure access. If you haven't set one up for your user account yet, then, from User Details in the Console, click API Keys from the Resources section, and then click Add API Key.

    Save the private key file (the PEM file) to the .oci directory in your home folder.

  10. Make a note of the Fingerprint that's associated with the API key. When you have multiple API keys, you must know which fingerprint to use for each private PEM file.
  11. If you haven't already set up a config file for the fingerprint on your local machine, then, from the API Keys section, do these steps:

    1. Click More in the row for your API key's fingerprint and then click View Configuration file.

    2. Copy the Configuration File Preview content.

    3. In the .oci folder on your local machine (the same folder that you saved your private key file in), create a file named config and paste the copied contents into the file.

  12. In the config file, change the key_file property to point to the location of your private PEM file. For example: key_file=/home/joe/.oci/my-private.pem

  13. If you don't have an auth token, click Auth Tokens in the Resources menu, and then click Generate Token. Copy the auth token immediately to a secure location from where you can retrieve it later because you won't see the auth token again in the console. You use the auth token as a password when you sign in to push your custom component package to the Oracle Infrastructure registry for deployment.

Set Up Your Local Machine for Oracle Functions

You'll need to install cURL, the OCI command line interface (CLI), Fn, and Docker on your local machine to enable deployment to Oracle Functions. If your machine runs on Windows, then you'll need to either install Oracle VM VirtualBox and host the Linux operating system, or use Cloud Shell.

If you plan to deploy our custom components from Cloud Shell, then you don't need to do the steps in this section. To learn how to deploy from Cloud Shell, see Cloud Shell in Oracle Cloud Infrastructure Documentation. You can use a repository such as GitHub or Object Store to make your custom component package available in the shell.

  1. (Windows only) If your machine runs on Windows, then you must use a Linux guest on Oracle VM VirtualBox to deploy your custom component package to Oracle Functions.

    Here are the steps to install Linux on VirtualBox:

    1. Install VirtualBox from https://www.virtualbox.org/.

    2. Download a Linux ISO. For example, to get the ISO for Ubuntu-Mate, go to https://ubuntu-mate.org/download/ and click 64-bit PCs/Macs.

    3. In VirtualBox, create a virtual machine from the ISO. You can find instructions for creating a Ubunto-Mate virtual machine at https://itsfoss.com/install-linux-in-virtualbox/. This will be your Linux guest.

    4. Start the Linux guest.

    5. From a terminal window, run this command:

      sudo apt-get update

      This updates the package lists for new packages and packages that need upgrading.

      Tip:

      To open a terminal window in Ubuntu, press Ctrl-Alt-T.
    6. To be able to do things like copy and paste in a terminal window, you'll need the guest additions. Download http://download.virtualbox.org/virtualbox/<release>/VBoxGuestAdditions_<release>.iso and install and configure the additions using the instructions at https://itsfoss.com/virtualbox-guest-additions-ubuntu/

      Be sure to configure configured Devices > Drag and Drop to bidirectional.

    7. Enter this command in a terminal window to install node.js and npm on the guest.

      sudo apt install npm
    8. Drag the .oci folder in your home directory on your local machine into the home folder on the Linux guest.

      Because it's a hidden file, you must press Ctrl-H or select View > Show Hidden Files in the home folder to see it.

    9. From the .oci folder on the Linux guest, open the config file and change key_file to point to the location of the file in your Linux guest. For example: key_file=/home/joe/.oci/my-private.pem

    10. Complete the remaining steps in this topic from the Linux guest.

  2. (Mac only) If you haven't already, install Homebrew to enable you to install cURL, OCI CLI, and Fn. See https://docs.brew.sh/Installation. Alternatively, you can use the equivalent MacPorts commands.
  3. If your Internet access is through a VPN, then you might need to set up proxies. For example:

    export http-proxy = http://<external_ip>:80
    export https-proxy = http://<external_ip>:80
    export no_proxy = localhost,127.0.0.1,<list>
    export noproxy = localhost,127.0.0.1,<list>
    export no_proxy = localhost,127.0.0.1,<list>
    # Example for apt
    nano /etc/apt/apt.conf
    Acquire::http::Proxy "http://<external_ip>:80";
    Acquire::https::Proxy "http://<external_ip>:80";
  4. Run the appropriate command to bring the packages up to date.

    • Linux:

      sudo apt update && sudo apt upgrade
    • Mac:

      brew update && brew upgrade
  5. (Linux only) You'll use cURL to install OCI and Fn. Enter this commeand in a terminal window. The last statement is to verify that it installed successfully.

    sudo apt install curl
    curl --version
  6. Fn uses the OCI CLI to deploy the custom components to Oracle Functions. Run the appropriate command to install the CLI, and accept all defaults.

    • Linux:

      bash -c "$(curl -L https://raw.githubusercontent.com/oracle/oci-cli/master/scripts/install/install.sh)"
    • Mac:

      brew update && brew install oci-cli
  7. In Set Up Your User Account for Oracle Functions, you created a config file. You now need to configure the CLI to use that file. Open a new terminal window, run this command, provide the location of your config file, and then enter n for the remaining questions (your config file already has the necessary settings).

    oci setup config

    For example:

    $ oci setup config
        This command provides a walkthrough of creating a valid CLI config file.
        ...
    
    Enter a location for your config [/home/joe/.oci/config]:
    Config file: /home/joe/.oci/config already exists. Do you want add a profile here? (If no, you will be prompted to overwrite the file) [Y/n]: n
    File: /home/joe/.oci/config already exists. Do you want to overwrite (Removes existing profiles!!!)? [y/N]: n
  8. You need Docker 17.10.0-ce or later to push the custom component package to the registry.

    See https://docs.docker.com/engine/install/linux-postinstall/ if you don’t want to preface the docker command with sudo.

  9. If you are using VPN, then follow the instructions at https://docs.docker.com/network/proxy/

  10. Ensure that Docker is running. You can't start Fn, which you install next, if Docker isn't running.

  11. You'll use Fn, which is a lightweight Docker-based serverless-functions platform, to configure the context and deploy the package. Follow the instructions for installing Fn, starting the Fn server, and testing the installation at https://fnproject.io/tutorials/install/

    You don't need to configure the context or set the registry at this time. You'll do this when you complete the steps in Deploy the Custom Components to Oracle Functions.

Modify the Custom Component Package for Oracle Functions

Before you can deploy a custom component package to Oracle Functions, you'll need to add func.js and func.yaml files, add a developer dependency for the fnproject FDK, and install the FDK.

Note:

(Windows only) Complete these steps on your local machine and then use drag-and-drop to copy the component package to your Linux guest. Alternatively, install node.js and the Bots Node SDK, as described in Step 1: Install the Software for Building Custom Components, on your Linux guest before you do the steps.
  1. In the top folder for your custom component package (the folder that contains main.js), create a file named func.js, and then add the following code. This is the file that Oracle Functions will invoke.

    /***
     
      This function handles an invocation that sets the "Oracle-Bots-Fn-Path" header to determine which component to invoke or if metadata should be returned.
     
    ***/
     
    const fdk = require('@fnproject/fdk');
    const OracleBotLib = require('@oracle/bots-node-sdk/lib');
    const path = require("path");
     
    const BOTS_FN_PATH_HEADER = "Oracle-Bots-Fn-Path";
    const METADATA_PATH = "metadata";
    const COMPONENT_PREFIX = "components/";
     
    let shell;
    let componentsRegistry;
     
    const getComponentsRegistry = function (packagePath) {
        let registry = require(packagePath);
        if (registry.components) {
            return OracleBotLib.ComponentRegistry.create(registry.components, path.join(process.cwd(), packagePath));
        }
        return null;
    }
     
    componentsRegistry = getComponentsRegistry('.');
    if (componentsRegistry && componentsRegistry.getComponents().size > 0) {
        shell = OracleBotLib.ComponentShell({logger: console}, componentsRegistry);
        if (!shell) {
            throw new Error("Failed to initialize Bots Node SDK");
        }
    } else {
        throw new Error("Unable to process component registry because no components were found in package: " + packagePath);
    }
     
    const _handle = function (input, ctx) {
        let botsFnPath = ctx.getHeader(BOTS_FN_PATH_HEADER);
        if (!botsFnPath) {
            throw new Error("Missing required header " +  BOTS_FN_PATH_HEADER);
        } else if (botsFnPath === METADATA_PATH) {
            return shell.getAllComponentMetadata();
        } else if (botsFnPath.startsWith(COMPONENT_PREFIX)) {
            let componentName = botsFnPath.substring(COMPONENT_PREFIX.length);
            if (!componentName) {
                throw new Error("The component name is missing from the header " + BOTS_FN_PATH_HEADER + ": " + botsFnPath);
            }
            return new Promise((resolve) => {
                let callback = (err, data) => {
                    if (!err) {
                        resolve(data);
                    } else {
                        console.log("Component invocation failed", err.stack);
                        throw err;
                    }
                };
                shell.invokeComponentByName(componentName, input, {logger: () => console}, callback);
                });
        }
    };
     
    fdk.handle(function (input, ctx) {
        try {
            return _handle(input, ctx);
        } catch (err) {
            console.log("Function failed", err.stack);
            throw err;
        }
    });
  2. In the same folder, create a file named func.yaml and then add the following content:

    schema_version: 20180708
    name: <custom component package name>
    version: 0.0.1
    runtime: node
    entrypoint: node func.js
  3. In the name property, change <custom component package name> to the name of your custom component package, and then save your changes. The name is typically the same as the name that you specify in the package.json file.

    The name should be no more than 255 characters and contain only letters, numbers, _, and -.

  4. In a terminal window, change to the package's top folder and enter this command to install the FDK and to add it as a package dependency in the package.json file:

    npm install --save-dev @fnproject/fdk
  5. (Optional – Linux and Mac only) Run this command to install package dependencies:

    npm install

    Note that if the node_modules folder doesn't exist, then the fn deploy command that you do later will invoke npm install for you.

  6. (Windows only) Complete these steps to copy your custom component code to your Linux guest for deployment:

    1. Drag-and-drop the top level folder to the Linux guest.

    2. In a terminal window, change to the top-level folder (the one that contains main.js) and type this command to add execute permissions for the folder.

      chmod 755 components
    3. Delete the node_modules folder to ensure that you don't have any platform-dependent node modules.

    4. (Optional) Run this command to reinstall the node module dependencies.

      npm install

      Note that if the node_modules folder doesn't exist, then the fn deploy command that you run later will invoke npm install for you.

You are now ready to complete the steps in Deploy the Custom Components to Oracle Functions.

Deploy the Custom Components to Oracle Functions

After you create the func.js file, add fnproject to the development dependencies, and install the dependencies as described in Modify the Custom Component Package for Oracle Functions, you are ready to deploy a Docker image of the component package to Oracle Functions.

When you completed the steps in Set Up Your User Account for Oracle Functions, you copied commands from the Local Setup on the Getting Started page for steps 3 through 7. You'll use these copied commands to deploy your custom components.

If you're using Cloud Shell, then use the similar commands shown in Cloud Shell Setup instead.

To deploy the custom components:

  1. Ensure that Docker and the Fn server are running.

  2. In a terminal window, change to the top directory for your custom component package and enter your equivalent copied commands to configure the context.

    fn create context <context> --provider oracle
    fn use context <context>
    fn update context oracle.compartment-id <compartment-ocid>
    fn update context api-url https://functions.<region-identifier>.oraclecloud.com

    You don't have to run these commands again until you need to change the context configurations.

  3. To point the registry repository that you created in Set Up Your User Account for Oracle Functions, enter your copied command that's equivalent to the following. If you haven't already, change [OCIR-REPO] to the name of your repository.

    fn update context registry <region-key>.ocir.io/<tenancy-namespace>/[OCIR-REPO]

    You don't have to run this command again until you need to change the repository configuration.

  4. If you haven't signed into Docker in your current session, run the copied command that's equivalent to the one shown here.

    When it prompts you for a password, enter your auth token, which is the token that you obtained while completing the steps in Set Up Your User Account for Oracle Functions.

    docker login -u '<tenancy-namespace>/<user-name>' <region-key>.ocir.io
  5. To deploy the custom components, run this command:

    fn deploy --app <application>

    If you see the following message, open the .oci/config file and verify that fingerprint shows the correct fingerprint for the specified key_file. If not, go to your user settings in the Console, click API Keys, view the configuration file for the correct fingerprint, and then replace the content of your config file with the displayed content.

    Fn: Service error:NotAuthenticated. The required information to complete
    authentication was not provided or was incorrect.. 
    http status code: 401.

Your custom components are ready to use in a skill as described in Add Oracle Function Service.

Deploy to Mobile Hub

To host a custom component package in Mobile Hub, use the bots-node-sdk pack --service mobile-api CLI to copy your component package folders and make a few changes that are specific to Mobile Hub, including the RAML file. Then create the custom API from the RAML file, and upload a ZIP of the component package into the custom API.

  1. From the custom component package's top-level folder (the one that contains the main.js file), type this command in a terminal window:

    bots-node-sdk pack --service mobile-api

    The command does the following:

    • Copies the files and subfolders to service-mobile-api-<package version>.
    • Adds a component.service.raml file, which contains the necessary endpoints and operations.
    • Creates an api.js file, which is a Mobile Hub wrapper for main.js.
    • Modifies the package.json file to set the main file to api.js, set the dependencies, and add the Mobile Hub node configuration.

    This step shows the basic CLI command. For more information, see https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.md.

  2. Review the package.json file and verify that the package name conforms to the following Mobile Hub constraints. Modify the name as necessary to conform.
    • The name must consist only of letters (A-Za-z), numbers (0-9), and underscores (_).
    • The name must begin with a letter.
    • The name must be 100 characters or less.
  3. From the Mobile Hub APIs page, click New API > API, and then create the custom API by uploading the component.service.raml file.

  4. From the Security tab, switch off Login Required and then click Save.

  5. Zip up the service-mobile-api-<package version> folder, and then upload the ZIP file from the custom API’s Implementation tab.

  6. From the Test page, invoke the GET request. The response should show the component metadata.

    Tip:

    If you get a status 500, and the error is that it can’t find a matching route definition, check your files for bad JavaScript syntax, as that is the typical cause.

Task 3: Add Component Package to a Skill

You add a component package to a skill by creating a component service. For component packages that you host on an external server, Oracle Functions, or on Oracle Mobile Hub, a component service is an active connection from the skill to host server. Alternatively, you can upload the component package and host it from your Oracle Digital Assistant instance. This is referred to as an embedded component service.

A component service has two functions:

  • It queries the component to get the package metadata, including the names of the components, their properties, and allowed actions for each one. After a service is added to the skill, you can see this information in the Components tab, which you access by clicking Components This is an image of the Components icon. in the left navbar. You can reference this page to get the component names, properties, and actions, which you will need to use the components in your dialog flow.

  • It allows the skill to invoke the components.

    The JSON payload of the call made by the Dialog Engine to the components includes input parameters, variable values, user-level context, and the user’s message text. The component returns the results by changing the values of existing variables or adding new ones (or both). The Dialog Engine parses the returned payload and proceeds.

To add a custom component package to a skill, go to the skill's Components This is an image of the Components icon. tab and click Add Service, which opens a dialog for configuring the service.

How you configure the service depends on where you are hosting the component package. These topics provide instructions for each type:

After you create the service, you can invoke the custom components from your dialog flow as described in Custom Components.

When you upload a package to the embedded container, Digital Assistant verifies that the package is valid, and can reject the package for these reasons:

  • There are JavaScript errors.

  • The package doesn't contain all the node module dependencies.

  • A component name has more than 100 characters, begins with System., or contains other than alphanumeric characters and underscores, then the service creation fails.

  • Your instance already has the maximum number of embedded component services.

  • The TGZ file is too large. This typically happens when the .npmignore file doesn't contain a *.tgz entry and therefore, every time you pack the files, a nested copy of the existing TGZ is added.

See Add Embedded Component Service for more information about these verification checks.

Add Embedded Component Service

If you want to host the custom component package from your Oracle Digital Assistant instance, complete these steps:

  1. Prepare the Package for an Embedded Container Service.

  2. Upload Package to Create an Embedded Component Service.

Prepare the Package for an Embedded Container Service

If you want to host the custom component package from Oracle Digital Assistant as an embedded component service, you must first pack the custom components into a TGZ file. Then, when you create the embedded component service, you upload this file.

This TGZ file, which you package using bots-node-sdk pack, must contain the assets and structure described in Task 1: Implement Custom Components. It also must contain all the node modules that it depends on (the bots-node-sdk pack does that for you).

Note:

There's a limit to how many embedded custom component services an instance can have. If you don't know the limit, ask your service administrator to get the embedded-custom-component-service-count for you as described in View Service Limits in the Infrastructure Console. If you try to add a component service after you meet that limit, then the service creation fails.

To prepare a package for uploading to the embedded container service:

  1. Ensure that you have the latest version of the Bots Node.js command line tools.

    The embedded container requires that the TGZ file includes all dependencies. Earlier versions did not bundle the dependencies into the file. Now, the command that you'll use to create the TGZ file ensures that your package.json file contains a bundledDependencies node that lists all the dependent modules that need to be included in the TGZ file.

  2. In the directory that contains the main.js file, run the following command for each of the modules that your package depends on. You don't need to do this for devDependencies, such as the Bots Node SDK.

    This command adds the module to the node_modules folder and adds it as a dependency in package.json.

    npm install <module>

    If your package.json already names all the dependencies, then you can run npm install instead.

  3. Ensure that the top-level folder contains an .npmignore file that has a *.tgz entry. For example:

    *.tgz
    spec
    service-*

    Otherwise, when you pack the files into a TGZ file, you include the TGZ file that already exists in the top-level folder, and your TGZ file will double in size. After you pack the files a few times, the TGZ file will be to large to upload into the container.

  4. Run this command:

    bots-node-sdk pack

    This command validates the component package, updates it to include devDependencies if necessary, and then creates a TGZ file, which you'll upload when you create an embedded component service from the skill’s Components tab. Note that the files you've listed as dependencies are included as bundledDependencies, with the exception of the Bots Node SDK and Express, which are devDependencies.

Your package should be compatible with the following versions:

  • For Oracle Digital Assistant instances that are provisioned on Oracle Cloud Infrastructure (sometimes referred to as the Generation 2 cloud infrastructure), your package should be compatible with Node.js 8.11.5 and Bots Node SDK 2.2.2.
  • For Oracle Digital Assistant instances that are provisioned on Oracle Cloud Platform (as all version 19.4.1 instances are), your package should be compatible with 8.11.4 and Bots Node SDK 2.2.0.

For more information about the pack command, see https://github.com/oracle/bots-node-sdk/blob/master/bin/CLI.md.

Upload Package to Create an Embedded Component Service

After you pack a custom component package into a TGZ file, you can upload it to create an embedded component service from the skill's Components tab.

To learn how to create the TGZ file, see Prepare the Package for an Embedded Container Service.

Note:

When you upload the package to the embedded component service, it's deployed to Oracle Functions Service. If your instance is provisioned on the Oracle Cloud Platform (as all version 19.4.1 instances are), then the service is instead deployed within the Digital Assistant instance.

To create the embedded component service:

  1. From the skill, click Components Components icon.

  2. Click + Add Service button..

  3. Select Embedded Container.

  4. Click Upload a component package file and point to the TGZ file to upload, or drag the file to the Package File box.

  5. (Optional) If you want to send custom component context.logger() statements to the service's log, then switch Enable Component Logging to On. This switch is available only in instances of Oracle Digital Assistant that were provisioned on Oracle Cloud Infrastructure (sometimes referred to as the Generation 2 cloud infrastructure).

    You can see the log from the Components tab by clicking Diagnostics > View Logs.

  6. Click Create.

    Digital Assistant uploads the TGZ file and creates the embedded component service. During the upload, Digital Assistant verifies that the package is valid, and can reject the package for the reasons that are described later in this section.

    After you upload the TGZ file, the custom component service is built and its components are deployed. If the Components page displays an awaiting deployment message after you upload the TGZ file, it means that the service has been created, but is not yet available. When the service becomes available, the deployment metadata displays in place of the awaiting deployment message.

  7. Ensure that Service Enabled is switched to On.

During the upload, Digital Assistant might reject the package. Here are reasons for rejection and ways to resolve the issues.

  • JavaScript contains syntax errors: If a component's JavaScript has syntax errors, then that component is not added to the container, which results in this error message:

    Error Message: failed to start service built: Invalid component
          path:

    View the component files in an editor that detects syntax errors. Also, try hosting the package on a local server that sends error messages to a console log.

    Another reason for this message might be that the package doesn't contain all the node module dependencies. See the next item in this list.

  • Missing node modules: If the package doesn't contain all the node module dependencies, then you'll get the same error message as above:

    Error Message: failed to start service built: Invalid component
          path:

    To learn how to include node module dependencies, see Prepare the Package for an Embedded Container Service.

  • Component name is too long: If a component name has more than 100 characters, begins with System., or contains other than alphanumeric characters and underscores, then the service creation fails.

    Change the name in the component's JavaScript, repackage, and upload again.

  • Exceeded component service limit: If your instance already has the maximum number of embedded custom component services, then the service creation fails. Ask your service administrator for the embedded-custom-component-service-count limit as described in View Service Limits in the Infrastructure Console.

    If you need to raise the limit, you can request an increase. See Requesting a Service Limit Increase.

  • TGZ file is too large: This typically happens when the .npmignore file doesn't contain a *.tgz entry and therefore, every time you pack the files, a nested copy of the existing TGZ is added.

    When the top-level folder contains an .npmignore file with *.tgz, the previous version of the TGZ file isn't included when you update the package.

If you want to send custom component context.logger() statements to the service's log, then switch Enable Component Logging to On. This switch is available only in instances of Oracle Digital Assistant that were provisioned on Oracle Cloud Infrastructure (sometimes referred to as the Generation 2 cloud infrastructure).

When Enable Component Logging is switched to On, you can click the Diagnostics button for the service to access view logs and crash reports to diagnose the problem.

  • Select View Logs to view messages that the custom component sends to context.logger(). This feature is available only in instances of Oracle Digital Assistant that were provisioned on Oracle Cloud Infrastructure (sometimes referred to as the Generation 2 cloud infrastructure). The Enable Component Logging switch must be On for the log to contain these messages.
  • Select View Crash Report to view details about what may have caused the container to crash.

After you create the service, you can invoke the custom components from your dialog flow as described in Custom Components.

Add Oracle Function Service

You can deploy your custom components to Oracle Functions and add them to a skill as an Oracle Function service.

To add an Oracle Function service:

  1. You'll need to know the function's URL. A user with function development privileges can get the URL from the Integration Console for you.

    1. Sign in to the Integration Console.
    2. Click Navigation menu icon on the top left to open the navigation menu, click Developer Services > Functions, and then select the compartment that's been set up for function development.

    3. Click the application.

    4. In the Functions section, click the More icon for your function and click Copy Invoke Endpoint. Skill developers need this value to add the custom component package as a component service in a skill.

  2. A skill developer adds the component service to a skill in Oracle Digital Assistant. Sign into Oracle Digital Assistant, open the skill and click Components Components icon.

  3. Click + Service button..

  4. Provide a name and description for the service.

  5. Select Oracle Function.

  6. In the URL text box, enter the invoke endpoint URL that you copied from the Developer Services > Functions page in the Infrastructure Console while completing the steps in Set Up Your User Account for Oracle Functions.

  7. Click Create.

    If you get a "Can't Create the Service" error, go to Developer Services > Functions in the Infrastructure Console, select the compartment, click the application, and click Logs in the Resources menu. Then enable the log for the function, retry the deployment, and check the logs (click the log name to see the log). To learn more about logs, see Storing and Viewing Function Logs in Oracle Cloud Infrastructure Documentation.

    If you see an error like this, it's because the folder doesn't have the right permissions. On your local machine, use chmod 775 to change the folder's permissions, then redeploy:

    "Error: EACCES: permission denied, stat
    '/function/components/hello.world.js.js'"

    If you see an error like this then, on your local machine, delete node_modules, run npm install and redeploy.

    "Error: Cannot find module '@fnproject/fdk'"
  8. Ensure that Service Enabled is switched to On.

After you create the service, you can invoke the custom components from your dialog flow as described in Custom Components.

Add External Component Service

You can host your custom components on your own Node.js server and add them to a skill as an external component service.

Tip:

You can use the external service option during development, as described in Run the Component Service in a Development Environment.

To add an external component service:

  1. From the skill, click Components Components icon.

  2. Click + Service button..

  3. Select External.

  4. In the Metadata URL text box, enter the The URL that points to the GET endpoint that returns the list of components.

  5. Enter the service's user name and password.

  6. Click Create.

  7. Ensure that Service Enabled is switched to On.

After you create the service, you can invoke the custom components from your dialog flow as described in Custom Components.

Add Mobile Hub Component Service

You can host your custom components from Oracle Mobile Hub, and add them to a skill as an Oracle Mobile Cloud component service. Custom components that are hosted on Mobile Hub can integrate with remote services using connectors that are controlled by a Mobile Hub backend and they have access to the Mobile Hub platform APIs.

Because the backend that hosts the custom code handles the authentication for the custom components, you need to refer to the backend’s Settings page to get the information that you need to complete the configuration.

To add a component service for the Mobile Hub backend:

  1. From the skill, click Components Components icon.

  2. Click + Service button..

  3. Select Oracle Mobile Cloud.

  4. Enter the unique identifier assigned to the Mobile Hub backend in the Backend ID field. This ID is passed in the REST header of every call from the skill.

  5. In the MetadataURL field, enter the /components endpoint from the custom code API. For example, http://<server>:<port>/mobile/custom/ccPackage/components.

  6. Choose Use Anonymous Access if the service allows anonymous login. If you choose this option, enter the anonymous key, which is a unique string that allows your app to access anonymous APIs without sending an encoded user name and password. The anonymous key is passed in their place. You can find the anonymous key on the backend's Settings page in Mobile Hub. (You may need to click Show.)

    If the component service requires a login (meaning no anonymous access), then enter the user name and password.

  7. If the service requires specific parameters, click Add HTTP Header and then define the key-value pairs for the headers.

  8. Click Create.

  9. Ensure that Service Enabled is switched to On.

After you create the service, you can invoke the custom components from your dialog flow as described in Custom Components.