Blocks are one of the main Convoworks components. They represent different steps in conversation. Each block defines a user interaction. It usually outputs something to the user, processes user response, and gives a reaction to that response.
Block structure
Basic block structure has two main parts. One is a Read Phase whose purpose is displaying or telling initial information to the user. Basically, all block types have the Read Phase. After that, the system waits for a user request. When a user makes a request, the service will try to execute the second, Process Phase of the current block. All blocks have some form of a Process Phase. Some block types have a non-editable, outwardly hidden – main processing phase with their own built-in processors. However, they always include the user-editable Additional Processors phase.
If a block processor matches the user requests, its sub-element flow will be executed. However, if none of the block processors matched, the Fallback stream will be executed instead.
Different block types
The most basic block type is also the most commonly used one – Conversation block. Its structure is pretty straightforward. It contains a Read Phase, Process Phase, and a Fallback flow.
The second available block, the Loop block iterates through an array you have to provide under the Items property and evaluates user answer. Its structure is a little bit more complicated. It has two process phases – Main Processors and Process Phase. The Main Processors, when triggered, advance the Loop block‘s iteration. Unlike the Process Phase, whose processors function as additional processors and don’t affect the iteration. It has a Read Phase and Done phase which executes when the iteration’s done.
You can access the current iteration item under the Data collection item name. You can also access index, natural, first (boolean), and last (boolean) values.
Example: ${dataCollectionItemName.index}
You can skip iterations of as many items as you wish, starting from the beginning of the array, by entering an offset number in the Offset field and entering a limit number in the Limit field limits the loop to the specified number of iterations. You can set the Skip reset field to true if you don’t want the Loop block to reset the status variables after all the rounds are done or the round is interrupted.
Conversation and Loop blocks are part of the core package.
The last block, the Trivia Round block is part of the convo-trivia package and is a specialized block for creating a trivia game. It iterates through the provided trivia questions array, evaluates player answer, and executes either the Correct answer given or the Incorrect answer given flow. The Done container executes after the iteration is done. As in all block types, there’s also the Fallback flow.
The block has its own built-in intents, so the main process phase isn’t available, but you can add additional intents and processors in the Other processors container. The block provides the current questions array item and the current users array item under the Status variable name you define. You can also access the question_index, user_index, and boolean last_question.
Example: {status.user_index}
You can provide the Users array expression if there are multiple players and lastly the Skip reset boolean expression which is optional as well. You set the Skip reset field to true if you don’t want the Trivia round block to reset the status variables after all the rounds are done or the round is interrupted.
There are two types of components that you can place within blocks: Elements and Processors.
Block component types
Elements (in the green sections) are the most common and most versatile component type in Convoworks. They are executed in sequential order and can be nested one in another. You can use them to output some response to users, load data, manipulate variables, and as control structures (if, then, loop, include, goto …).
Processors (in the violet sections) are components that are activated only if the right condition is met. They consist of two parts: one determines if the processor should be activated at all (intent matching) and the other is the element flow to be executed if that processor is activated.
The processors actually delegate the matching responsibility to a third type of component, the request filters. They are a bridge to the underlying NLP platforms we rely on. They can handle both text and intent-based platforms. This means that you can use the same logic for handling Alexa (which is a strictly intent-based system) with FB Messenger and Viber which provide just raw text inputs. You can read more about filters in the Request Filters guide.
Now let’s get back to blocks.
Block Examples
So, in the block, you define what user responses you want to handle and what you will do if the user requests something else (fallback flow).
Here’s a simple conversation block’s structure:
It uses the Yes/No Processor which accepts ”yes” or ”no” answers to move further in the service flow.
Here’s the real-life counterpart:
Text response elements are used for output, while the GOTO element is there to redirect the flow to another block if the user answers in the affirmative. Text response re-prompt option is used in the no flow to wait for the next user answer. If the user answers in the negative again, it redirects back to the no flow.
Now, take a look at this example from the Robo Numbers game:
It seems a lot harder to figure out than the previous one, no? This particular block is used in setting up clash mode and it tries to set the competing device name. Clash mode is having two devices playing one against another.
Let’s break it all down step by step.
- Read phase: The user is asked for the device name. There’s also the re-prompt text if the user doesn’t answer right away.
- Process phase: We have two processors for handling user response. The first will activate if the user gives us the device’s name. As you can see, we are catching two intents – SetDeviceNameIntent and SetDeviceNameSoloIntent. That’s because the targeted platforms have various restrictions on how the intents are defined, and this kind of scenario is not uncommon. In this case, we defined SetDeviceNameIntent which uses AMAZON.SearchQuery entity that can be used only in combination with some predefined text. E.g “It is {device_name}” is a valid definition, but “{device_name}” is not.That’s why we created the second intent, SetDeviceNameSoloIntent which catches AMAZON.FirstName entity. In this case, we do not need additional text, but we have to use a different slot name, so the utterance definition is: “{device_name_solo}”. Note how we configured intent readers to end up with the same slot name for both intents, making our control logic more clear. The second processor is catching the HelpIntent. It explains this particular step in conversation to the user – setting the competing device name. It’s a built-in system intent, and it’s triggered by the user responding with ”help”.
- Fallback flow: we notify the user that we didn’t understand their response and then we re-run the block starting with the read flow – informing the user what is expected from them.
Hopefully, this guide has helped you grasp the basics of blocks.
In our next one, we’ll be learning about special blocks types and how to use them.