Getting Started with Chatbots and Forms

Persona Forms are used by The Sedro Project as a tool to manage and map content to and conversations. Forms are written in simple XML much like an HTML form. They allow the definition of inputs, labels, content validation, events and a bit more.

Each Persona may have Forms added to it to manage input, output, or integrate with external APIs and databases. Form management can be done via the APIs or via the persona manager that is a thin layer on top of the same APIs, but a bit easier to work with

Since the format is much like HTML forms so it will be a bit familiar, additionally you can embedded in them directly HTML pages (style=’display:none’ perhaps), this allows a web page to provide visual interaction as well as chat or audio.

Hello World Chatbot

A simple Hello World Chatbot example provides the basic structure for the form: name, data-type with inputs and labels.

 <form name='_helloform_' data-type='form'>
       <input name="intro" data-type="content" />
       <label for="intro" state='wake'>Hello from your form!</label>

Form names should follow the convention of _name_ for interaction or action forms (so that your persona does not find it and think it is an object).

Main Form

The main form for a Persona is a form that runs at the time the persona wakes. To make a Form main, just set it as the main form.

Now you can add the Hello World example as main when you submit it. Then Try it by click ‘Chat’ on the persona from the Persona Manager.

Extending hello world form

Now the Form is extended to add another line to the introduction, this is done by adding another line with the same state. Then conversation closing text is added via another input and labels. After that a bye event is used to close the conversation.

They bye event is added as an input with data-type=event and data-event=bye this forces the chatbot to hangup.

 <form name='_helloworld2_' data-type='form'>
       <input name="intro" data-type="content" />
       <label for="intro" state='wake'>Hello World!</label>
       <input name="intro2" data-type="content" />
       <label for="intro2" state='wake'>(from your form)</label>
       <input name="exit" data-type="content" />
       <label for="exit" state='any'>That is all.</label>  
       <input name="exit2" data-type="content" />
       <label for="exit2" state='any'>Good Bye</label>     
       <input name="bye" data-type="event" data-event='bye' />

Remote Forms

Forms may be in the persona or remote. Remote forms are fetched on demand via HTTP GET from the provided URL. This allows for simpler management of the chatbot flow and as well as per user / etc customization.

In the Persona Manager adding a remote form will add a main form that is remote. The URL provided will be pulled to the persona each time it wakes.

The URL to retrive the remote Form will contain some parameters to allow dynamic creation.

  • ctok = the caller_token passed into the wake API call
  • lang = the language of the conversation
  • chtype = the channel type for the conversation (chat=online chat)

Test a remote form, from the Persona Manager add a form and set the URL with our example

Try it by clicking ‘Chat’ on the persona… It also has a few more features.


In this Form an input is added to collect the caller/chatter’s title. Additionally it ask them to verify we have the correct answer and complains if they send junk. Then it uses it in the context of the conversation.

 <form name='_helloform_' data-type='form'>
       <input name="intro" data-type="content" />
       <label for="intro" state='wake'>Hello from the form!</label>
       <input name="title name" data-type="input" data-seq="X:%any%:(lx_role_name):sz[large]"/>
       <label for="title name" state='wake'>What is your Title?</label>
       <label for="title name" state='incomplete'>Your job title or personal title</label>
       <label for="title name" state='verify'>You are really a %title name%?</label>
       <label for="title name" state='nomatch'>%title name% isn't a title!</label>
       <label for="title name" state='complete'>Never met a %title name% before</label>
       <input name="exit" type='hidden' data-type="content" />
       <label for="exit" state='any'>That is all.</label>
       <input name="exit2" type='hidden' data-type="content" />
       <label for="exit2" state='any'>Good Bye</label>
       <input name="bye" data-type="event" data-event='bye' />

The value of the input can be aded in phrases by wrapping the input name with a ‘%’’s example:  %title name%. This makes it easy to use the current values in follow on messages.

In the “title name” labels we have added some additional states that are available for inputs;

  • wake – starting state, use for opening label
  • incomplete – still waiting for a valid response
  • verify – check if the current response is what they want to use
  • nomatch – if content is not a match, question or command
  • complete – done with the input

This input has an additional data-seq= attribute, this is used to correctly identify and extract the information from the response they give us and uses the SEQ language (documented elsewhere)


Menus are the most common interaction for many voice systems (think phone IVR), they are often used in text based chatbots as well. The menu is always a complete form, it can be linked as the main form or as a sub-form from any other (more on that in documentation and later post)

 <form name='_testmenu_' data-type='form'>
 <input name="intro" data-type="content"/>
 <label for="intro" state='wake'>Select an option from this list</label>
 <input name="select" data-type="menu"/>
 <label for="select" state='option' value='1'>option 1</label>
 <label for="select" state='option' value='2'>option 2</label>
 <label for="select" state='option' value='3'>option 3</label>
 <label for="select" state='option' value='4' data-formname='cancel'>Go back</label>
 <label for="select" state='incomplete'>Please select an option or cancel</label>
 <label for="select" state='verify'>You would like option %select% %select_txt%?</label>
 <label for="select" state='done'>You selected option %select% %select_txt%</label>
 <input name="exit" data-type="content" />
 <label for="exit" state='wake'>Thank you</label>

The menu is created as a menu type input. Labels are then added for each option with the state=’option’ set and a value set for the simple option value.

 <label for="select" state='option' value='1'>option 1</label>

Matching the value= or the text for the label will match the option for the caller.

Once a response is selected the done label is displayed. The phrase can include the value and or label for the selected option using the % method and _txt% for the label. If a verify message is added (or multiple via conditional labels) the verification of the selection will take place, just as it does on a standard input.

Conditional labels

Many times the response for an input or other interaction needs to be dependent on the response data. A data-seq=’xxx’ option on a label allows selection from a set of responses based on the input using SEQ language definitions to match content.

 <input name="full name" data-type="input" data-seq="X:%any%:(lx_person_name):sz[large]"/>
 <label for="full name" state='wake'>What is your full name?</label>
 <label for="full name" state='incomplete'>Your full legal name please</label>
 <label for="full name" state='verify'>Is %full name% your full name?</label>
 <label for="full name" state='verify' data-seq='P:%any%:length[1]'>%full name%, you have only 1 name?</label>
 <label for="full name" state='complete'>nice to meet you %full name%.</label> 

The full name is desired in this example and verification is added if a single name is added instead of the expected first and last (and possibly more). A data-seq=”P:%any%:length[1]’ has been added that will display this message if the token length == 1 for the input (Parent in SEQ terms) .

Channel Type specific Labels

The content from a label without a channel type specified is the default, it will be used on all channel types. chat, sms, email, voice, etc. If you would like a specific channel type to have different content, just add another label with attribute data-channel-type=’xxx’ specified.

<label for="full name" state='complete'>nice to meet you %full name%.</label>
<label for="full name" state='complete' data-channel-type='sms'>Hello %full name%.</label>

In some cases you may want no content for a specific channel type, set the content to ‘%’ to accomplish that.

<label for="full name" state='complete' data-channel-type='sms'>%</label>

Message Delays

Waits before or after a message allow better control over the user experience, providing time to separate content as in a natural conversation. Each label may have a wait before the content data-pre-wait=”time” and after the content with data-post-wait=”time”. Time is in tenths of a second so 10 = 1 second.

<label for="full name" state='complete' data-pre-wait='5' data-post-wait='20'>nice to meet you %full name%.</label>

Get started

Now is a good time to get started with The Sedro Project to try Forms and Persona based chatbots.

To Be Continued…

In the next blog on Forms we will focus on Sub-Forms