This is the first version of the Dialogue Manager Script (DMS) documentation, which will demonstrate the current state and capabilities of DMS through a tutorial , outline the syntax and semantics , and discuss how to write effective DMS . DMS is a high-level language that compiles down to [ DMPL ] compliant JSON.

If you wish to make comments regarding this document, please send them to public-conv@w3.org ( subscribe , archives ).

This specification was published by the Conversational Interfaces Working Group . It is not a W3C Standard nor is it on the W3C Standards Track. Please note that under the W3C Community Final Specification Agreement (FSA) other conditions apply. Learn more about W3C Community and Business Groups .

The code snippets presented in this page can be evaluated by hitting the "Run" button, which compiles DM Script into [ DMPL ] JSON, and then processes that JSON on a JavaScript runtime. The compiler can be found on GitHub [ dms-compiler ].

The input -> statement awaits for user input, and feeds it to a variable of our choosing. In this case, the variable guess is populated with the user's input.

This guessing game chat-bot will help us better understand DMS. Let's build a simple prompt that asks the user for some input . We start by printing out messages using act , and then awaiting the user's input.

3. Syntax and Semantics

The DMS syntax is loosely based off Rust. Curly-brackets { } establish a block of code, statements do not need a trailing semi-colon ; , and labels before the curly-brackets annotate the behavior of the block. Similar to ECMAScript, DMS is not a strongly typed language.

Scripts written in DM Script are also called components . The runtime shall evaluate the component in an infinite loop, similar to game-loops inherent in most game engines. Components may call other components through run or use statements.

3.2 Variables In programming, a variable is nothing more than a placeholder for some value. The strings “Chai” , and “Moo” are simply values that a placeholder dog_name could take on, as can be seen in the following example. Example 4 dog_name = "Chai" dog_name = "Moo" Run Note that in DMS, there is always an implicit infinite loop wrapping our code. During execution it will keep creating and assigning a variable named dog_name the values "Chai” and "Moo” .

3.3 Control Flow In order to remove these redundant variable creation and assignments we can wrap code in a block beginning with the keyword once . The once keyword tells the compiler that the variable creation and assignments should only be executed one time over the lifetime of the component. Example 5 once { dog_name = "Chai" } dog_name = "Moo" Run Deciding whether or not to run some code depending on if a condition is true is a basic building block in most programming languages. The most common construct thats allows programmers to control the flow of execution of DMS code are if statements. Recall that in DMS there is always an implicit infinite loop wrapping our code, meaning that loops are inherently built in, and any code outside of a once block will be repeatedly executed over the lifetime of our program. 3.3.1 If Statements An if statement allows us to branch our code depending on conditions. These statements start with the keyword if , and follow up with a condition that evaluates to a Boolean value. Example 6 once { number = 1 } if number > 2 { act "Number is greater than or equal to 2." } else { act "Number is less than 2." } number = number + 1 Run We can link multiple conditions by combining if and else in an else if block. For example: Example 7 once { number = 7 } if number % 3 == 0 { act "Number is divisible by 3." } else if number % 2 == 0 { act "Number is divisible by 2." } else { act "Number is not divisible by 2 or 3." } Run

3.4 Fork Statements Forks are generalized if statements. They're the heart and soul of DM Script. As a refresher, let's consider the trivial example below of branching logic. Example 8 if true { act "Let's talk about animals." } else { act "Let's talk about colors." } Run A fork statement allows a more general way of representing branching behavior. First, let's recreate the example above using fork . Think of it as a fork in the road, where we can only go down one candidate path. Each candidate has an entry-condition. In the example below, notice that the underscore _ is a shortcut for the Boolean value true . Example 9 fork { _ { act "Let's talk about animals." } _ { act "Let's talk about colors." } } Run By default, a fork picks the first path whose entry-condition is met, from top to bottom. This method for resolving a fork is also called the "greedy" strategy, because it picks the first possible candidate instead of considering all candidates. Forks allow powerful customization of the branching behavior. In the example below, the fork picks a child-block at random. We can optionaly change the fork-strategy by providing a dictionary in a decorator #{} directly before the statement. In the example below, a strategy of {depth: 0} is associated with the fork . Example 10 #{depth: 0} fork { _ { act "Let's talk about animals." } _ { act "Let's talk about colors." } } Run The content of the dictionary specifying the fork-strategy depends on what the underlying runtime supports. In this case, {depth: 0} means use bounded depth-first search (BDFS), with a depth of 0 to resolve the fork. A depth of 0 in BDFS is effectively picking a candidate at random. Different run-times may support different search algorithms, such as Monte Carlo Tree Search. The heuristic function for the search algorithm is specified by declaring a model . The model of a fork-strategy is a list of lists, representing preferences. For example, the pair [{x: 0}, {x:10}] , declares that the value of x is preferred to be 0 as opposed to 10 . Internally, the runtime infers a utility-function, which is a real-valued function over the variables in DM Script, that provides a total-ordering of preferences. Example 11 once { x = 5 } #{depth: 1, model: [[{x: 0}, {x: 10}]]} fork { _ { x = x + 1 } _ { x = x - 1 } } Run Changing the preference model changes the program behavior. For example, by swapping the pair [{x: 10}, {x: 0}] , the program now counts up instead of counting down. Example 12 once { x = 5 } #{depth: 1, model: [[{x: 10}, {x: 0}]]} fork { _ { x = x + 1 } _ { x = x - 1 } } Run If we want to say that the value of x should be 5 , we can write the model as a list of preference-pairs, as follows. Example 13 once { x = 3 } #{depth: 1, model: [[{x: 5}, {x: 0}], [{x: 5}, {x: 10}]]} fork { _ { x = x + 1 } _ { x = x - 1 } } Run Consider the following scenario, where a autonomous agent has 3 possible actions, (1) eat food, (2) do nothing, or (3) work for food. In DM Script, we can use fork to define the pre-conditions and outcomes of each action. We specify that {health: 10} is desirable over {health: -10} , and use BDFS to resolve the fork, with a depth of 1 . Example 14 once { health = 2 food = 1 } #{depth: 1, model: [[{health: 10}, {health: -10}]]} fork { food > 0 { act "eat" food = food - 1 health = health + 3 } _ { act "do nothing" health = health - 1 } _ { act "work" food = food + 1 health = health - 2 } } Run Unfortunately, the program chooses the suboptimal sequence of actions: it chooses to do nothing after eating up all the available food. Let's increase its intelligence by changing the fork-strategy to {depth: 3} . Notice that now, the program will alternate between eating food and working, which is the optimal strategy. Example 15 once { health = 2 food = 1 } #{depth: 3, model: [[{health: 10}, {health: -10}]]} fork { food > 0 { act "eat" food = food - 1 health = health + 3 } _ { act "do nothing" health = health - 1 } _ { act "work" food = food + 1 health = health - 2 } } Run We'll cover more interesting use-cases of fork in the effective DMS section.

3.5 Primitive Types The example in the variables section only allowed the variable dog_name to take on string values. However, DMS is a dynamically typed language meaning that variables can take on any basic data type such as string , float , and Boolean . Consider the following example where we have a variable named current_thought which denotes what a programmer might be thinking about throughout the day. Example 16 once { current_thought = "coffee" current_thought = false current_thought = 5.20 } Run

3.6 Structures The primitive types defined in the previous section are all atomic literals. DMS also allows programmers to build more complex structures such as lists, or dictionaries. 3.6.1 List A list is an ordered arrangement of other structures. All elements are enclosed within square-brackets [ ] , and separated by commas as follows. Example 17 once { student_grades = [ 87 , 90 , 88 , 92 , 93 ] student_names = [ "Nawar" , "Tom" , "Chris" ] a_bunch_of_stuff = [ false , 1 , "two" , [ 3 , 4 , 5 ]] } Run 3.6.2 Dictionary A dictionary is a structure that maps data in key-value pairs. The value of a corresponding key can be any structure. Example 18 once { student_grades = { Nishant: 0, Carol: 93, Daniel: 90 } } Run Take note of the syntax that was used to create the dictionary in the above code snippet. The keys of the dictionary are symbols which are a finite sequence of characters without the double quotation-marks, and the values in this example are simply integer values. Note that when accessing the values of a dictionary , the keys must be enclosed within double quotation marks. Example 19 once { student_grades = { Nishant : 0 , Carol : 93 , Daniel : 90 } act student_grades[ "Nishant" ] } Run

3.8 Input Handling Up to now all program behavior has been predefined. Variables have been assigned persistent values, and all output can be predetermined ahead of time. However part of what makes any program engaging and meaningful, is when a user or programmer is able to directly interact with the application. In this section we showcase how DMS captures and processes user input. In DMS, user input is handled by a special structure which assigns intents to a temporary user-defined variable, as follows. Example 45 once { act "Hi there! I'm Parrot-Bot. I repeat anything you say!" } input -> result { result == "Hello" { act "Ahoj to you!" } _ { act "You said: " + result } } Run Send In order to begin capturing input, we use the syntax input -> . The expression can be thought of as follows, “Anything that is typed in or captured, redirect and store in the variable immediately following the arrow -> “. In the example above, all captured input is stored in the variable result. Once DMS is done capturing input, the body of the input block begins its execution. Simply put, the conditions contained within the body of the input block can be thought of as if-else expression. This means that the first expression, using the input, that evaluates to true will be executed. In the above example, whenever user input happens to be "Hello" the program will output "Ahoj to you!", (Note: Ahoj is Czech for Hello) and in all other cases will default to the expression beginning with the underscore _ . Note that within an input block whenever an underscore _ is used as the condition of an expression, it will always evaluate to true; essentially acting as the default else of a branching statement.