Hi I’m the Context object, and today we are going to learn some tips and tricks about me.
Don’t forget me!
For all you people starting with Watson Assistant (WA), you might not know me. In fact nearly everyone forgets about me for the first application they create.
WA is a stateless system. That means without me it cannot understand where the user left off in the conversation. So it’s very important to send the updated version of me back to WA on your next call.
If your conversation is repeating the same thing over and over, then this is probably why.
I belong to one workspace
It’s possible to create multi-workspace applications. But a common mistake is thinking that I can be used by multiple workspaces. When I move to a new workspace, I will generate a new conversation ID, and my system map will be meaningless to the new workspace (even if a copy).
Anatomy.
It’s important to understand each of my internal pieces and what they do. I’ll talk a little bit about the input and output parts later.
Context.conversation_id
This is a unique identifier assigned to mark all messages belonging to the same conversation. If you don’t supply this, or you supply an invalid one then a new one is generated for you. It has no other use except for logging.
Context.system
This is what WA uses to understand where it is in the current conversation. I won’t go into details, because it’s undocumented. One tip though! If any variable starts with an underscore (example: “_node_output_map”), this means it’s internal structure is fixed. So any hacks you do against this variable will likely fail on any updates.
Context.branch_exited & Context.branch_exited_reason
This will tell you if WA had to leave the branch in order to find a response for the user. It will also explain why it had to exit.
Context.private
This is a special context variable. Anything you store in this object you can hide from the conversation logging.
Very handy for storing passwords. Just be aware that if you use any of the values elsewhere they can be seen in the logs.
Everything else.
All other objects are created by you! I use a SPeL engine which analyses the variable and change it as I need it. So be careful on what you do. For example:
-
10 + "10" = 2
You can embed code blocks into the variable values, but regardless of what it returns, it must be wrapped in a string.
-
Will work: "id_number": "<? 10 + 10 ?>"
-
Won't work: "id_number": <? 10 + 10 ?>
Code blocks will only work in WA. They are treated as text if you send them from the application.
Proper feeding.
It’s important to not overfeed me. While I can hold a lot of information, it is not good to make me the session storage for your application. There are a few reasons for this.
- Causes more network traffic.
- Increases logging sizes.
- Doesn’t scale very well
To ensure you keep me nice and fit you can do the following.
One time context variable outputs.
If I need to pass a context variable to the application but I don’t want to see it again, then you should put it into the Output object of the response.
Object grouping
If you need to send related variables, group them within an object. For example:
Without Object grouping | With Object grouping |
"context": { "name": "Bob", "id": 12345, "order_id": 67890 } |
"context": { "user": { "name": "Bob", "id": 12345 }, "order_id": 67890 } |
This allows you to drop a large number of context variables with ease when they are no longer needed.
Variable requests
If you have a huge number of potential context variables, then you can use the request model to pull in just the variables you need from the application.
Request (from WA) | Response (to WA) |
"context": { "request": "name,id,order_id" } |
"context": { "name": "Bob", "id": 12345 "order_id": 67890 } |
Call out to cloud functions.
Abstracting your data calls away from your application layer allows you to slot in and out updates without changing your orchestration layer. You are under a time limit to get the data, but if you can stay within 5 seconds, then this can be a better way to retrieve data and act on it.
Remembering the good times.
As a general rule, if you need to jump around the dialog tree, you should use “Jump to”, “Skip” and “Digressions”. There are approaches to get me to do it for you though.
Use these patterns with caution though, as you are moving conversation logic to the application layer. This can cause tight cohesion and more prone for bugs appearing later on.
Snapshots
This is easy enough. You just take a backup of the system object. Then overwrite the existing system object when you want to revert.
Forced jumps
This is a little tricker. You need to first traverse the tree to each jump location, then store the system objects. You can these use these system objects to jump to those areas. I would say use digressions instead if at all possible. This requires having to remap every time there is a change to the workspace.
… and there you have it. Look after me, I’ll make sure everything runs fine!