Write your first flow
Write complex business logic with basic flow code.
Remove unused files
Let's do a bit of clean up first.
- Open your app in the Meya Console.
- Select the Flows page.
- Delete the following flow files:
welcome.yaml
hi.yaml
catchall.yaml
- Select the Components page.
- Delete:
welcome.py
Update the welcome message
Your initial message to the user should give them an indication of what they can do with your app. Let's encourage the user to create an order by giving them a quick reply button.
- Select the Flows page.
- Open the
open_page.yaml
file in the code editor and paste the following BFML code, click Save (you can ignore the error message for now, this will be fixed when adding the other flows):
triggers:
- type: page_open
- keyword: start
steps:
- say: Hi, I'm Pizza Bot! I can help you order a pizza.
quick_replies:
- text: Order
action:
flow: flow.order
transfer: true
composer:
visibility: hide
Whitespace
Flow code is written in Bot Flow Markup Language, which is based on YAML. This means that whitespace, including indentation, is very important. You'll get errors if your flow code is not indented properly. Make sure your flow code looks like the above code example.
Lines 8-10: When the user clicks the quick reply, it will launch the yet-to-be-created order.yaml
file. transfer: true
means that we don't want to return to the open_page.yaml
flow when the order.yaml
flow completes (check the Flows guide for a detailed explanation of the flow
component).
Lines 11-12: Since our bot is going to be menu-driven, we don't want to expose the composer, which let's the user enter any text they want. As an extension of this project you could try adding the Dialogflow integration so your app can understand your user's free text, but for now, let's continue with a menu-only bot.
Create the order flow
- Select the Flows page.
- Click the Create flow button.
- Rename the flow from
new_flow.yaml
toorder.yaml
. - Paste the following code into the code editor, and click Save (ignore the error message for now):
steps:
- ask: What size of pizza would you like?
quick_replies:
- text: Small
data:
size: small
price: 6
- text: Medium
data:
size: medium
price: 10
- text: Large
data:
size: large
price: 14
- text: Cancel order
action:
jump: cancel
composer:
visibility: hide
- flow_set:
ingredients: []
message: What ingredients you like to add
- (add ingredients)
- ask: (@ flow.message )
quick_replies:
- text: Pepperoni
result: pepperoni
- text: Olives
result: olives
- text: Chicken
result: chicken
- text: Hot peppers
result: hot peppers
- text: Feta cheese
result: feta
- text: Green pepper
result: green pepper
- text: Onion
result: onion
- text: Done
action:
jump: get user info
- text: Cancel order
action:
jump: cancel
composer:
visibility: hide
- flow_set:
ingredients: (@ flow.ingredients + [flow.result] )
- flow_set:
message: |
**Added: (@ flow.ingredients | join(", ") )**
What else?
- jump: add ingredients
- (get user info)
- flow: flow.get_user_info
- tiles:
- title: Your order
rows:
- - cell: Size
value: (@ flow.size )
- - cell: Ingredients
value: (@ flow.ingredients | join(", ") )
- - cell: For delivery?
value: (@ flow.is_delivery )
- - cell: Address
value: (@ user.home_address )
- - cell: Payment method
value: (@ flow.payment_method )
- - cell: Total
value: $(@ flow.price ) + tax
ask: Here's a summary of your order.
quick_replies:
- text: Submit order
action: next
- text: Cancel
action:
jump: cancel
- type: component.submit
api_token: (@ vault.api_token )
size: (@ flow.size )
ingredients: (@ flow.ingredients )
address: (@ user.home_address )
payment_method: (@ flow.payment_method )
is_delivery: (@ flow.is_delivery )
- if: (@ flow.result )
then:
say: >
Your order is submitted and will be
(%- if flow.is_delivery %)
delivered
(%- else %)
ready for pickup
(%- endif %)
in 20 minutes.
else:
say: I wasn't able to place your order. To place your order, please give us
a call at 1-800-123-4567.
- flow: flow.open_page
transfer: true
- (cancel)
- say: Okay, I've cancelled your order.
- flow: flow.open_page
transfer: true
Let's take a minute to understand what's going on here.
Lines 3-18: When the user clicks on one of these quick reply buttons, the size and price of the pizza will be stored on flow scope at flow.size
and flow.price
, respectively.
Lines 22-24: Next, we initialize a list of ingredients and a message we'll use to prompt the user for their selection.
Lines 51-57: After the user selects an ingredient, we add it to the list and update our message to include the list of selected ingredients. Note that we need to use two flow_set
components so that the message
variable has the latest version of the ingredients list.
Line 58: We use the jump
component to jump back to the add ingredients
label so the user can keep selecting ingredients.
Once the user clicks the Done quick reply, they'll jump to the get user info
label.
Lines 62-83: We use a tile
component to summarize the order details.
Lines 85-91: In a future step, we'll build a custom component to actually place the order. you can see from this BFML, though, that we'll provide it with an API key and the order details.
Lines 92-104: Depending on whether the custom component returns true
or false
, we'll display a final message to the user.
Vizualize the flow
- Open the
order.yaml
flow in the code editor. - Click on the Visual button.
Create the user info flow
Although we could include this code in the order.yaml
flow, it makes sense to split this out into another flow so that each flow has a specific purpose: The previous flow is for customizing the pizza; this flow is for providing user info, such as payment method and delivery address.
- Select the Flows page.
- Click the Create flow button.
- Rename the flow from
new_flow.yaml
toget_user_info.yaml
. - Paste the following code into the code editor, and click Save (ignore the error message for now):
steps:
- ask: How will you be paying?
quick_replies:
- Cash
- Credit/debit
composer:
visibility: hide
- flow_set: payment_method
- ask: Is this for take-out, or delivery?
quick_replies:
- text: Take-out
result: false
- text: Delivery
result: true
- text: Cancel order
action:
jump: cancel
composer:
visibility: hide
- flow_set: is_delivery
- if: (@ flow.is_delivery )
then: next
else:
jump: end
- if: (@ user.home_address | default(false) )
then:
jump: end
else: next
- ask: What is your address?
- user_set: home_address
- (end)
- end:
payment_method: (@ flow.payment_method )
is_delivery: (@ flow.is_delivery )
- (cancel)
- say: Okay, I've cancelled your order.
- flow: flow.open_page
transfer: true
Having already written the order.yaml
flow, this flow will probably make sense pretty quickly:
- We ask a series of questions about the user,
- offer them quick reply buttons to make the process as easy as possible, and
- save the results to either
flow
oruser
scope.
user
scopeLine 33: We're using
user
scope here because this piece of data (the user's home address) is unlikely to change often. By saving it touser
scope, we ensure that the user won't need to type it again when they order pizza from us in the future.
Lines 36-38: The end
component ends the flow and returns the user to the parent flow, which in this case is order.yaml
. Since payment_method
and is_delivery
are stored on flow
scope, they'll disappear as soon as we leave the get_user_info.yaml
flow. The end
component lets us specify a YAML dictionary of data we want to pass back to the order.yaml
flow's flow
scope so we can keep working with it. (Check the Flows guide for more detailed info on the end
component).
Vizualize the flow
- Open the
get_user_info.yaml
flow in the code editor. - Click on the Visual button.
(Optional) Local IDE
Remove files
Remove the following files:
flow/welcome.yaml
flow/hi.yaml
flow/catchall.yaml
component/welcome.py
Update bot config
Open bot/default.yaml
and update name
to Pizza Bot
.
Let's also change the default bot avatar to this pizza slice icon: icon
Here's what your file should look like:
type: meya.bot.element
name: Pizza Bot
avatar:
image: https://images.vexels.com/media/users/3/157209/isolated/preview/725aa2473489db2e550656210c557f18-cheesy-pizza-icon-by-vexels.png
markdown: true
Create new files
Create the following files in your IDE:
flow/order.yaml
: paste the content of theorder.yaml
file above.flow/get_user_info.yaml
: paste the content of theget_user_info.yaml
file above.
Update the following files in your IDE:
flow/open_page.yaml
: paste the content of theopen_page.yaml
file above.
Updated about 2 years ago
Next, we'll add the component.order.submit component referenced in the order.yaml flow.