Skip to content

Skills and Apps

One of the benefits writing your bots in Bubblescript is the fact that you can reuse code in different dialogs. With Skills, you can reuse parts of one bot, within another bot. Skills can therefore be thought of as a tool that you can buy. Programmers can think of Skills as libraries or packages. A skill can depend on other skills, just as a drill can depend on a drill-bit to perform its function. Skills are developed in a bot, and then a version of it can published as a package. This published skill can then later be installed in a different bot.

Apps can be seen as a template bot that is preconfigured for a specific purpose. In an app-bot, the Bubblescript code of the bot cannot be changed anymore, it is read-only, because the app has a specific purpose and should not be used for something else. However, the bot configuration, CMS and Flows of an app-bot can of course still be changed by the end user, to be able to customize the bot up to a certain point. Just like skills, apps are versioned, can be published, and are developed inside a bot.

Managing Skills

Installing an external Skill

Skills provided by DialoX can be installed through the Packages main-menu item. There, on the Store subpage, you can find an overview of skills that are available for installation and the skills that are already installed in your bot. A skill is installed using the "Install" button in the pop-up.

All the dependencies for a skill will be installed automatically.

Configuring a Skill

Once a skill is installed, it can, depending on the skill, be configured to perform its task in a way you desire. Configuration of the Skill is done in the "Installed" section by clicking on the cogwheel of a Skill, or via the entry in the Settings main menu.

Uninstalling a Skill

Skills can be uninstalled in the "Installed Skills" by clicking on a Skill and then on the "Uninstall Skill" button. If the Skill you are trying to uninstall has another installed Skill that depends on it, an error will be shown with the name(s) of the Skill(s) that depend on it. Uninstall those skills first.

Disabling a skill

Skills can be temporarily disabled. This functionality can be used to first install the skill and then configure it, without exposing the skill yet to the world.

Skill development

A skill exists in its own folder in the bot, where all the files that are necessary for the Skill to function properly are stored. A skill name is always formatted as namespace/skill_name, where namespace is a common prefix to group related skills together (e.g a company name). The folder name where a skill resides in MUST be equal to the same namespace/skill_name.

Skills that are being developed ("native skills") live always in a subfolder in its 'host bot'. For instance, when developing a skill named acme/example, the skill metadata file must be called acme/example/skill and all files live in that same folder (sharing the acme/example/ prefix) are considered skill files and are treated as a single package of files.

Through the 'packages' menu item, it is possible to publish native skills into the app store. For this to work, as a developer you must have access to the skill's namespace (acme in the previous example). When publishing a skill, you give a change log text and then the skills files are packaged and stored in a separate package repository, independent of the host bot.

Published skills are available for installation in other bots, if the environment of those bots is configured to show the published skill(s) in its skill store, or when a skill is listed as an optional dependency of a bot app (see Bot Apps).

Skill Metadata

The information about the Skill is stored in the skill YAML file that resides in the directory of the Skill. This file has the following fields:

  • name string, mandatory, unique identifier of the Skill,
  • title string, mandatory, a display title for the Skill,
  • icon string, mandatory, the icon that is displayed in the Skills section (blueprintjs icon),
  • subtitle string, mandatory, a small description of what the Skill does.
  • author string,
  • dependencies list of string, a list of names of other Skills that this Skill depends on,
  • optional_dependencies list of string, a list of names of other Skills that need to be ordered below this skill,
  • settings settings schema, a CMS definition of the settings for this Skill,
  • tags list of strings, a list of tags that apply to this Skill,
  • version string, a semantic version of the Skill at the time of publishing.

A minimal skill YAML file:

name: "company/skill"
title: "My Skill"
subtitle: "Provides basic behaviour"
icon: "badge"
version: "1.0.0"
dependencies:
  - "bsqd/base"

Skills optionally have a settings key which can expose a configuration / settings screen for the skill:

name: "company/skill"
title: "My Skill"
subtitle: "Provides basic behaviour"
icon: "badge"
version: "1.0.0"

settings:
  type: form
  storage:
    type: script
    script_title: config/company_skill
  title: Users
  icon: people
  form:
    schema:
      type: object
      properties:
        name:
          title: "A configurable string field"
          type: string

Dependencies

Skill dependencies give a list of other skills that must be installed if this skill is to be used. They can be in the form of a simple array of strings:

dependencies:
  - bsqd/base

or in the form of a skill name + requirement string, to better specify the version constraint the dependent skill must meet:

dependencies:
  - bsqd/base == 1.0.0

This specifies that only bsqd/base version 1.0.0 should be used as the dependency. See the Elixir docs on version requirements for more information on how to specify these requirements.

Testing

Often you develop multiple skills inside a single bot. In that case, you might want to write test cases that only cover a single skill. In such cases, it is best to disable the other skills in the bot that are not the focus of the current test.

It is possible to automatically disable certain skills for certain test files, by setting the @disabled_skills constant in the test file, like this:

@disabled_skills ["b"]

test "Only testing skill a"
  expect "Hello from a"
end

Migrations

Sometimes it can be necessary to run code when a skill upgrades its version, or when it is installed. For this purpose, skill migrations exist. Migrations are tasks, which live within the folder of the skill, which are annotated with a migrate_to: attribute.

Skill upgrade migrations

When a skill is upgraded, the following happens:

  • The source version of the skill is retrieved; this is the currently published version number of the skill;
  • The target version of the skill is retrieved from the skill in the store;
  • From the skill's scripts, all tasks are gathered which have a migrate_to attribute with a version number which lies between the source and the target version
  • These tasks, ordered by their version number, are then performed in the bot.

All log statements in the tasks are collected and presented to the developer afterwards. When a migration task fails, the upgrade of the skill is cancelled.

An error can be raised from within a task by using the fatal statement.

Typically, the write_script(title, contents) function is used inside the migration task to modify some of the content on the bot while the skill is upgrading.

Example:

task migrate_to: "5.1.4" do
  log "Starting content migration"
  data = []
  repeat i in keys(@answers) do
    data[i] = @answers[i]
    # add a new attribute
    data[i].enabled = true
  end
  write_script("answers", data)
  log "All done"
end

The write_script function can only be called from inside the studio, and called by a developer with enough permissions to change the bot's script.

Migration tasks can be tested in the studio by giving the task a name, and from the debug console calling perform on the task.

Skill installation migration

To run a migration when a skill is newly installed into a bot, specify :install as the version:

task migrate_to: :install do
  log "Installing the skill..."
  # do your things here
  log "All done"
end

App development

A bot containing an app can be in three states:

Installed - in this case, the bot has an app YAML file at the top level with all the bot metadata. The rest of the bot, with the exception of its content / flow files, are locked for editing. To change the bot's code, an update of the app must be published and then the target bot must be updated to that new version.

Native - in this case, the bot is used to develop the app. To be able to edit the bot in this case, there must be an app YAML file but it is called app.dev. A minimal app.dev file looks like the following:

name: company/first_app
version: 1.0.0
title: My first app
subtitle: This will say hello and then hang up

For native apps, the Packages main menu has a Development section from which the app can be published to the store. If the app requires any skills, these must be installed inside the native app bot.

A third app state exists, unlocked. In this case the "unlock" operation in the bot advanced settings renames the app file to app.unlocked, causing the bot to behave like a normal bot. This also disables any app updates et cetera. Unlock should only be used in emergency cases. To lock a bot again, rename the file back to app.

Editable scripts

Once an app is installed, all its scripts are in principle fixed and users are not able to edit the scripts of the bot. This is fine for most scripts because they are part of the "app" and should not be touched. However, exceptions need to be specified for "content" files.

In the app.dev file you can add an editable_scripts section that specifies a list of script patterns which will be editable once the app is installed:

editable_scripts:
  - translations
  - flows/*
  - content/*
  - settings/*

App publishing

Once an app is being published, the following checks are done:

  • The bot does not contain any native skills. Only skills inside deps/ are allowed in apps.

  • All skills that are installed in the bot must be part of the dependencies[] or optional_dependencies[] arrays in the app metadata (installing a skill from the store adds it to dependencies automatically when an app.dev file is present)

  • The apps' namespace must exist and developer is allowed to publish to it.

  • All the apps' dependencies have an equivalent published skill release.

  • The app name is not already published as a skill.

  • If app is already published earlier, it must not be archived

  • The app name + version is not already published and the version bigger than the latest published version.

If all checks are OK, the app.dev YAML file is transformed into the app file:

  • The apps' dependencies and optional dependencies are both "frozen" at their installed versions. This means that the version requirement for the dependent skills are strictly set to their version numbers. This ensures that a certain version of an app always installs a well-known combination of skills plus their versions.

  • The bot's profile picture is set as the icon in the app metadata

  • A list of supported_locales is added to the app metadata: only the locales that are configured in the bot settings will be allowed to set in a bot that installs this app. This is to ensure that a target bot explicitly supports certain languages and no untranslated strings occur.

  • The list of supported_frontends is taken from the allowed_frontends list in the studio.yml file, to ensure that only those explicitly listed channels can be used in this app.

  • All bot scripts are collected, with the exception of the deps/ folder, and uploaded in a tarball, similar to how skill publishing is done.

App upgrade process

  • All installed skills which are not part of the new app's dependencies (and optional dependencies) are removed.
  • All new versions of the app skills are installed
  • All new versions of the app optional skills are installed
  • Skill migrations are run

Content files are not overwritten by an app update, except if they were not changed by the user between app updates.

Disolvable apps

To support legacy bot development flows, where the user installs a template bot (instead of an app), and then starts editing its code, without ever wanting to update the template to a newer version, a special app metadata attribute is introduced: dissolve: true.

When an app is installed that has dissolve: true specified, the installation process will remove the app file from the bot: therefore the bot behaves again like an oldschool, non-updateable, editable "template bot".