# Watson Assistant – Conversation Developer Guide

## Watson Context

The integration layer uses some parts of the Watson context for integration
purpose. Here is a brief survey:

### Variables Passed from Watson to Integration

Context Variable | Meaning
-------- | -------
| `$genbot-config-external_error_filter1`, `genbot-config-external_error_filter2`, ... | External error will be sent to Watson (with the intent `#error`) only in case it matches at least one of the filters specified. The filters use reduced glob mathing (`*` for any sequence of characters, `?` for any character) |
| `$genbot-request-microapp` | Micro application to call, more info [here](#micro-applications) |
| `$genbot-request-anynomization-PARAM_NAME` | Instruction for the anonymization, more info [here](#anonymization) |
| `$genbot-request-params-PARAM_NAME` | Parameters passed to a microapp, more info [here](#micro-applications) |

### Variables Passed from Integration to Watson

Context Variable | Meaning
-------- | -------
| `$genbot-response-PARAM_NAME` | Parameters from the start action or a return from a microapp (action=`genericInputAdapter`), more info [here](#micro-applications) |
| `$genbot-request-PARAM_NAME` | Parameters passed from a routing request, more info [here](#routing) |
| `$genbot-request-plugin-PARAM_NAME` | Parameters returned by a plugin, more info [here](#plugin-call) |

### Variables Passed in Both Directions between Watson And Integration

Context Variable | Meaning
-------- | -------
| `$shared-watson-PARAM_NAME` | Context variables shared among various assistants in a multiskill deployment, more info [here](#routing) |
| `$shared-router-PARAM_NAME` | Context variables shared between assistants and the integration, more info [here](#router-context) |

## HTML Support

Watson assistant supports HTML markup. However only a subset of HTML is
supported by the genbot solution. Apart from HTML some special non HTML XML
tags are supported. Here is a survey of the supported markup:

### HTML Markup

Element | Explanation
-------- | -------
| `<a href="URL">` | A link. **IMPORTANT**: As far as a valid XML is required it is not allowed to use `&` in href literally! We must use `&amp;` instead of `&` (similarly `&lt;` instead of `<` etc.). |
| `<br>` | Line break. |
| `<em>` | Emphasized text (usually displayed in italics). |
| `<img src="..." title="...">` | Image. |
| `<video src="..." title="..." type="youtube">` | Youtube video. |
| `<video src="..." poster="..." subtitles="..." subtitlelabel="..." subtitlelang="..." type="mp4">` | Html5 video mp4. |
| `<video src="..." poster="..." subtitles="..." subtitlelabel="..." subtitlelang="..." type="webm">` | Html5 video webm. |
| `<video src="..." poster="..." subtitles="..." subtitlelabel="..." subtitlelang="..." type="ogg">` | Html5 video ogg. |
| `<strong>` | Bold text. |
| `<ul><li>...</li></ul>` | Unordered list. In the wingbot output adapter the unordered list is translated to a carussel. `<li>` may contain text, `<a>` and `<img>` |

### Non-HTML Markukp

Element | Explanation
-------- | -------
| `<pause wait="NUMBER_OF_SECONDS">` | Wait for the specified period of time |
| `<buttons>OTPION1`&#124;`OPTIONS2`&#124;`...</buttons>` | Option buttons (quick links) |

## Anonymization

Genbot supports two types of anonymization:

1. **Pattern anonymization** - Whenever some input to the Watson dialog adapter
(user utterance, plugin return params, microapp return params) contains
a substring that matches a pattern which indicates possibly sensitive value
that substring is replaced with a placeholder.

2. **On-demand anonymization** - The conversation developer marks the next
user utterance as sensitive. In that case the whole input is replaced by
a placeholder.

The anonymized value that comes to Watson Assistant looks like `[[EMAIL.1]]`.
The first part is the name of the recognized pattern. The number behind the dot
is an index of the value of this type in scope of the conversation session.

The supported patterns are:

* `EMAIL`
* `PHONE`
* `BIRTH_CODE`
* `ACCOUNT_NUMBER`
* `DATE`
* `NUMBER`

Moreover there is special type `ALL` for on-demand anonymization (so here
the placeholder looks like `[[ALL.1]]`).

All outputs from Watson are automatically deanonymized, i. e. output to the
chat and input parameters of plugin calls and microapps.

### On-Demand Anonymization and Anonymization Hints

As the patterns for the anonymization are quite loose and the pattern
anonymization is not contextual at all two unwanted situations may occur:

1. Some substring that is in fact not sensitive is wrongly anonymized and
replaced by a placeholder. This may somohew limit Watson NLP abilities but
generally this effect should be insignificant.

2. Some substring is correctly considered sensitive but its type is not
assigned correctly as this substring matches more anonymization patterns
(so Watson Assistant receives e. g. `[[ACCOUNT_NUMBER.1]]` instead of
`[[BIRTH_CODE.1]]`).

In order to prevent 2. we may use the type hinting which means that we
specify the expected anonymization type. During the anonymization the specified
type will be tried to match before the rest of the supported types. Type
hinting has the same syntax as the on-demand anonymization - we set the context
variable `$genbot-request-anynomization-hint`. So for example to hint
the anonymization to expect a phone number we set

```
$genbot-request-anonymization-hint := "PHONE"
```

For on-demand anonymization we use

```
$genbot-request-anonymization-hint := "ALL"
```

## Watson Dynamic Placeholders

In order to achieve deterministic responses from watson,
instead of dynamic data following functions should be used,
`[[time()]]`: returns current time (e.g. 09:18)
`[[date()]]`: returns current date (e.g. 03. 10. 2023)
`[[day(["neděle", "pondělí", "úterý", "středa", "čtvrtek", "pátek", "sobota"])]]`: returns given day
`[[partOfDay(["Dobré ráno", "Dobré dopoledne", "Dobré odpoledne", "Dobrý večer"])]]`: returns given part of day
`[[random()]]`: picks random response from given multi responses

## Statistics

Currently there is just one statistics related feature supported by the
extension JSON - an indication that the dialog node handles a situation
where the Watson Assistant does not understand the user input. Such JSON looks
like:

```
{
  "output": {
    ...
    "user_defined": {
      "not_understood": true
    }
  }
}
```

## Micro Applications

A micro application is an external application called from the conversation.
Generally there are three scenarios:

1. Watson calls the micro application which covers the chat window by itself
   (to disable chat events while the micro application is active). When the
   micro application finishes it calls the conversation back.  From user
   perspective there is usually no difference in the chat application and micro
   application look and feel so s/he usually doesn't even notice that the chat
   is temporarily controlled by a different application. This scenario is most
   common.

1. Watson calls the micro application which does not call Watson back. Such
   micro application does not affect the chat UI.

1. A micro application calls Watson without being previously called from the
   conversation.

A micro application may be started from the Watson Assistant either by using
a JSON or using context variables. The JSON has the following format:

```
{
    "output": {
        ...
        "user_defined": {
            "microapp": {
                "id": "ID_OF_THE_APPLICATION",
                "params": {
                    "PARAM1": "VALUE1",
                    "PARAM2": "VALUE2",
                    ...
                }
            }
        }
    }
}
```

The context variables based version of the above JSON is:

```
$genbot-request-microapp := "ID_OF_THE_APPLICATION"
$genbot-request-params-PARAM1 := "VALUE1"
$genbot-request-params-PARAM2 := "VALUE2"

```

The response from the micro application comes with an intent
`#microapp.return` and return parameters are mapped to the context variables

```
$genbot-response-PARAM1
$genbot-response-PARAM2
...
```

We should avoid using both JSON and context variables. If both are specified
then JSON has precedence.

## Action Definition

The **Watson Assistent Dialog Adapter** enables to define custom actions as
a JSON extension of the Watson Assistant dialog node. These actions are then
interpreted by the **Output Adapter** and may be translated to various actions
on the output - e. g.  a plugin call.

The dialog node JSON with an action definition has the following format
(the `generic` part is usually pre-generated by Watson Assistant):

```
{
    "output": {
        "generic": [
            {
                "response_type": "text",
                "selection_policy": "sequential",
                "values": []
            }
        ],
        "user_defined": {
            "actions": [ ... ]
        }
    }
}
```

`actions` is an array - there may be more actions executed within one user
interaction.

### Action Common Properties

Every action has the following properties:

1. **name** – Action name.
2. **on** – The event that triggers the action. Values `pre-display` and
`post-display` are supported. `pre-display` means that the action is triggered
before displaying the output of the Dialog Adapter. Based on the action
result it may happen that the output of the Dialog Adapter will not be
displayed at all. `post-display` means that the action is triggered after
displaying the output of the Dialog Adapter before waiting for the next user
input.

Here is a short example of the action JSON:

```
{
    "name": "handover",
    "on": "pre-display",
    "plugin": { ... }
}
```

### Plugin Call

Plugin call is a common action. It is specified by adding

```
    "plugin": { ... }
```
to the action definition. The plugin configuration object has properies:

1. **name** – Name of the plugin to be called.
2. **actions** (optional) – Definition of a reaction to the plugin response
   (see [**Return from a Plugin**](#return-from-a-plugin))
3. **params** (optional) - Parameters that will be passed to the
   plugin. Each parameter is specifed in the format `"PARAM_NAME": VALUE` where
   `VALUE` may have any JSON-supported data type (in most cases `"SOME_STRING"`).
   A value `"$NAME"` is interpreted as a context variable and it is translated
   to the relevant value.

#### Plugin Return Values

Plugin response is mapped to the context variables
`$genbot-request-plugin-OUTPUT_PARAM_NAME`.


#### Return from a Plugin

If a parameter `actions` is **not specified** then conversation usually defines
a reaction based on context variables where the plugin response is mapped.
Using `actions` we may translate plugin actions to intents. Here is an example:

```
actions: {
    "PLUGIN_ACTION_1": "continue",
    "PLUGIN_ACTION_2": {
        "intent": "#INTENT_NAME"
    }
}
```

The `continue` means that instead of asking Watson for the response the flow
will continue by the next action or generally response part prepared by the
dialog adapter. The part with `ìntent` means that the Watson will be called
with the specified intent (if there is some more response prepared by the
dialog adapter it will be ignored).

**NOTE**: It is recommended to use intent names prefixed with some string (e. g.
`plugin.INTENT_NAME`) to make it clear at first sight that such intent
is not based directly on the user input as usual.

**IMPORTANT**: If we specify `actions` and the plugin returns with an action
not listed in `actions` then a runtime error is triggered.

Because of the compatibility with the return from the newer handover
(which routes to **cc_app_genesys** instead of doing a postback to
the action `handover`) the mechanism of evaluating the response from the plugin
has been extended in the following way: the definition
is considered as the one that applies for the return from the plugin if one of
the following is true:

1. genbot is called with the action `ACTION_NAME` (the original approach).
2. genbot is called with the intent `INTENT_NAME`.
3. `INTENT_NAME` has the form `plugin.INTENT_WITHOUT_PREFIX` and genbot is
   called with the intent `INTENT_WITHOUT_PREFIX`. In this case Watson is
   called with a forced intent `INTENT_NAME`, **not** `INTENT_WITHOUT_PREFIX`.

Here is a complete example of a plugin call:

```
{
    "output": {
        "generic": [
            {
                "response_type": "text",
                "selection_policy": "sequential",
                "values": []
            }
        ],
        "user_defined": {
            "actions": [
                {
                    "name": "handover",
                    "on": "pre-display",
                    "plugin": {
                        "name": "handover",
                        "actions": {
                            "back-from-agent-callback": {
                                "intent": "#plugin.call_completed"
                            },
                            "back-from-agent-on-timeout-or-error-callback": {
                                "intent": "#plugin.timeout_or_error"
                            }
                        }
                    }
                }
            ]
        }
    }
}
```

The JSON specifies that

- The response of the dialog adapter should not be displayed at all (there is no
`continue` action) – instead the **handover** plugin is called.
- The handover plugin is expected to return with action **back-from-agent**
  or **back-from-agent-on-timeout-or-error**. These actions are translated
  to intents **#plugin.call\_completed** and **#plugin.timeout\_or\_error**
  respectively.

### UI Action
User actions defined in the conversation can be used to send actions to UI.
UI currently supports these actions:
- hide-composer - this action completely hides composer (input) in the GUI
- disable-composer - this action disables composer, meaning composer remains visible but it is not possible to write inside it
- show-composer - this action display composer and enables it if it is disabled

Here is an example of hiding composer action:

```
{
    "output": {
        "user_defined": {
            "actions": [
                {
                    "ui-action": "hide-composer"
                }
            ]
        }
    }
}
```

## Wingbot Plugins

This section describes Wingbot plugins from the perspective of the Watson
Conversation developer. Most facts presented here may be found in the Wingbot
UI.

## Routing

Routing enables to pass the dialog flow from one chatbot to another. One chatbot
is considered a master and the others are child chatbots. Generally the
difference is that the master may route to any chatbot while for a child chatbot
it is preferred to route only to the master which decides what to do next
(however technically a child chatbot is allowed to route to any bot in the same
tree). The routing is specified using usual `actions` JSON. Moreover the text
response (which is never displayed to the user in the routing use cases) must
have a specific format to give basic information about the routing without the
necessity to open the routing JSON.

Now we will show the JSONs for specific routing actions:

### Routing from a master chatbot to a child chatbot

```
{
  "user_defined": {
      "actions": [
          {
              "route": {
                  "target": "TARGET_CHATBOT_ALIAS"
              }
          }
      ]
  }
}
```

The alias names are a part of the application configuration.
The text response associated with the routing JSON must be
```
-> TARGET_CHATBOT_ALIAS
```
which is being validated by the integration. This text response is never
returned to the chat user - it just ensures some coding standards and
transparency of the conversation implementation.

The target attribute may also contain a special value (not in PoC):

```
[PARENT]
```

(in this case the text response will be `-> [PARENT]`). We typically want to add
a node with such routing in case some of the child assitants route to the master
with the atribute `return_back` set to `true` (see [**Routing from a child
chatbot to a master
chatbot**](#routing-from-a-child-chatbot-to-a-master-chatbot) for more
details). Generally it will route to `$genbot-request-assistant_stack[0]`. If
the stack is empty it will do nothing.

There are some optional attributes that may be added to `route`:

Attribute | Meaning
--------- | -------
| `intent` | A name of a forced intent (it must start with #). |
| `action` | Target action. This parameter is intended for routing to non-Watson chatbots, it has no meaning for Watson targets. |
| `utterance` | A forced utterance. In case we don't specify this attribute the target assistant will receive the last user utterance from the calling assistant. If this is not convenient for some reason we may override the user utterance. The value is either a string or a context variable (the dot notation for accessing complex object properties is supported). |
| `params` | An object of extra parameters that will be passed to the target bot context as `$genbot-request-PARAM1`, `$genbot-request-PARAM2`, .... This parameter should be used if we need to pass some parameter but we don't need to store the value in the context (the content of `$genbot-request` is refreshed with every utterance). If we need to store the value we use the parameter `shared_watson` instead. |
| `shared_watson` | An object of extra parameters that will be merged to the shared context. The shared context is accessible in Watson Assistant as `$shared-watson-PARAM_NAME`. Once some bot stores some value here using `shared_params` the value is visible to all other bots where the communication is routed. |
| `shared_router` | An object of parameters that will be written to the router context. The router context is accessible in Watson Assistant as `$shared-router-PARAM_NAME`. While the parameters stored in `shared-watson-PARAM_NAME` are intended for Watson Assistant only and have no meaning for the router the parameters in `$shared-router-PARAM_NAME` may be populated by the router and may affect router bahaviour. See [**Router Context**](#router-context) for more details) |
| `only_if_knows` | If we set this parameter to `true` the routing will be realized only in case the target assistant does not give a response coming from a node which specifies `not_understood: true`. Otherwise the conversation will stay in current assistant with a forced intent **#genbot-not_routed**. The default value is `false`. |

**Important**: Parameter `action` is exclusive with the parameters `intent` and `utterance`.

Instead of adding `params`, `shared_watson` or `shared_router` to the routing JSON it is possible to set the context variables `$genbot-request-PARAM_NAME`, `$shared-watson-PARAM_NAME` or `$shared-router-PARAM_NAME` directly. If some variable is set directly and it is also specified in the routing JSON then the JSON has precedence. Updating of `$shared-watson-*` and `$shared-router` works also in case of a non-routing response. An example:

1. Utterance 1.
2. Watson updates `$shared-watson-PARAM_NAME` and responds with a text.
3. Utterance 2.
4. Watson does a routing without updating `$shared-watson-PARAM_NAME` and without
specifying `shared_watson`.

In this scenario the routing target will see the `$shared-watson-PARAM_NAME` value set in step 2. On the other hand updating `$genbot-request-*` within a non-routing response has no effect.

Before routing to a child watson assistant the master assistant should always
check whether it is not handling a request that is coming just from that
child assistant. Otherwise the routing could lead to an infinite loop.
The integration tries to prevent such loops and implements the following check:
if a child assistant tries to route to an assistant from which the request is
coming and also the parameters are the same (utterance, intent), the routing
is halted and an error is displayed. In order to implement this check
in the master assistant the integration provides a context variable
```
$genbot-request-caller_assistant
```
which is an alias of the assistant from which the request is coming (i. e.
it was routed from this assistant).

### Routing from a child chatbot to a master chatbot

The controling JSON is very similar to the routing from the master:

```
{
  "user_defined": {
      "actions": [
          {
              "route": {
              }
          }
      ]
  }
}
```
We don't specify the target as the child chatbot always route to the master.
The text associated with this node must be `-> [MASTER]`. By master is meant
the primary application in a given channel.
As well as for the master there are optional `route` attributes `intent`,
`utterance` and `only_if_knows`. There is also another optional attribute
**return_back**.  By default it is false which means that the bot does not know
how to handle the utterance and wants to pass the control to another bot
completely. However in some cases the bot may assume that the user would wish
to return back to the same place once his/her last utterance is resolved by
another bot. In this case we use `return_back=true` (not in PoC). However it is
only a wish. It is the master assistant who decides whether this wish will be
fulfilled or not.  In order to route to the bot which used `return_back=true`
the master must have the instruction:

```
{
  "user_defined": {
      "actions": [
          {
              "route": {
                  "target": "[PARENT]"
              }
          }
      ]
  }
}
```
However such instruction may by in a node that is entered conditionally
or some determinictic routing may take precendence in the dialog flow. The
routing to parent is based on `$genbot-request-assistant_stack`
which is a stack of assistants (represented by its aliases)
that are willing to receive the control back (the master assistant is not
enumerated here). Let us explain on an example how this context variable
is populated by the integration.
Assume we have three bots with aliases **master**, **A** and
**B**. The **master** routes to **A**. At some point **A** wants to route to
another bot and return back once the utterance is solved by the other bot. So
**A** routes to master. At this point on master
`$genbot-request-assistant_stack` contains `['A']`. The master decides to route
to **B**. At some point **B** does not know how to solve the utterance and routes
to master without specifying `return_back`. At this point
`$genbot-request-assistant_stack` contains `['A']` (while
`$genbot-request-caller_assistant` contains `B`). Now it is up to the
master assistant implementation whether it will obey **A** and will route to it
using the above JSON or it will decide to solve the utterance in a different
way.  If **B** in the previous routing would specify `return_back=true`, the
master would receive `[B, A]` in the parameter `$genbot-request-assistant_stack`.

### Router Context

The Watson context parameters prefixed with `$shared-router-` are shared with
the router. It may be populated by the router and updating the value in
Watson may affect the router behaviour. The following parameters are agreed
for the router context:

Parameter | Access | Description
--------- | ------- | ----------
| `webUserAgent` | Read-only | User agent sent by the browser. |
| `webPage` | Read-only | A complex object containing information about the web page from which the chat is called. |
| `agentReason` | Write | Reason of routing to human agent. The following values are supported: `wantHuman`, `misunderstanding`, `unsuccess`, `outOfScope`, `upsell`. The default one is `wantHuman`. |
| `agentRouting` | Write | Name of the rule used to select the group of genesys agents. |

Watson is not allowed to set a context parameter `$shared-router-PARAM_NAME`
for a `PARAM_NAME` that is not listed in this table with access **Write**.
