Attached scripts

Attached scripts are Groovy scripts that are attached to a whole condition or a part of a condition. There are two types of attached scripts in Teneo: Propragation scripts and Predicate scripts. The former may be used to access and extract information from the user input, while the latter are used to impose further restrictions on the matching.

Propagation scripts

With an attached script you can determine exactly what information should be extracted. For example, you can access the 'used words' of a matching condition part or entity variables from matched entities. Moreover, attached scripts allow you to reliably recognize multiple entities of the same type within the same input. This makes your condition very flexible.


Attached scripts contain snippets of Groovy code. They have to be put into curly brackets and their content has to conform with Groovy syntax. Below we show how to attach the propagation script {orderedCoffeeType = lob.coffeeType} using the operator '^' to the entity COFFEES_SERVED.ENTITY. This makes that the flow variable orderedCoffeeType is assigned the value of the enitty variable coffeeType which has been defined in the entity COFFEES_SERVED.ENTITY. This value is propagated to the flow variable, hence the name 'propagation script'.

Attached script for coffee type

Propagation scripts can also be attached directly to any part of a condition. It must not always be attached to an entity or language condition. However, you need to bracket the part of the condition to which the script is attached to, as shown below. Note that in this case, the flow variable orderedCoffeeSize is directly assigned the value 'small'.

Attached script for size


Sometimes the user utterance may contain useful information that is not mandatory but still good for your bot to catch. One way to catch such information is by using the optionality operator (:o) together with an attached script.

In the example below ( with >> milk ) and %DECAFF.ADJ.LEX are optional. If the user says with milk, the variable orderedMilk is set to 'yes' and if the user says 'decaf', the variable orderedCaffeine is set to 'no'. Otherwise, the variables are not changed with no harm done.

%COFFEE.NN.LEX &^ ((with >> milk)^{orderedMilk = 'yes'}):o &^ (%DECAF.ADJ.LEX^{orderedCaffeine = 'no'}):o

Optionality can also be used to capture multiple occurrences of the same type in an input. The example below matches user inputs containing the phrase 'I_WANT.PHR' and up to three coffee types and their sizes. The optionality operator (:o) indicates that the 2nd and 3rd bracketed expressions are optional and can thus remain unmatched. However, if they are matched, the placing of the propagation scripts ensures that each size is stored together with the respective coffee type that the user ordered.

(%SIZES.ENTITY^{orderedCoffeeSize1 = lob.size} >> %COFFEES_SERVED.ENTITY^{orderedCoffeeType1 = lob.coffeeType}) &^
(%SIZES.ENTITY^{orderedCoffeeSize2 = lob.size} >> %COFFEES_SERVED.ENTITY^{orderedCoffeeType2 = lob.coffeeType}):o &^
(%SIZES.ENTITY^{orderedCoffeeSize3 = lob.size} >> %COFFEES_SERVED.ENTITY^{orderedCoffeeType3 = lob.coffeeType}):o 

Predicate Scripts

With predicate scripts you can add additional constraints to the evaluation of a language object, input annotation, entity or bracketed condition. These value-dependent constraints are based on information available during the matching process as follows:

  1. NLU variables: any variables set by the language object or entity
  2. Input annotation variables: any annotation information set by the object
  3. Used words: of the language object, entity or bracketed condition

There is no access to flow or session variables. Predicate scripts are attached to condition objects in a similar way as propagation scripts. If the predicate script is evaluated as false, the match is disregarded. In a sense predicate scripts allow you to "re-engineer" a language object to only react to a sub-category of its content. This allows you to quickly make the most of existing language resources, without having to create specialized versions of the objects. In the example below we use the language object containing a list of all countries and make it applicable for European countries only:

Predicate script for European countries

It is also possible to combine predicate scripts with propagation scripts. In this case the predicate script should be attached first, followed by the popagation script. The example below shows how we can use the number annotation to find a value under 1000, then save the found value using an attached propagation script.

Predicate script combined with propagation script

The table below shows additional ways that you can use predicate scripts along with an explanation of when each case might be useful.

Condition Description
%$BOOK_FLIGHT.TOP_INTENT:{lob.confidence > 0.8} This example shows how to apply a customized confidence threshold to a class intent by creating a 'hybrid trigger'. E.g. if the solution's confidence threshold is set to .45 for all class triggers, but that is too low for this intent, you could:
1) disable the class trigger for book flight
2) create a hybrid trigger using the top intent annotation with an improved confidence threshold.
%$BOOK_FLIGHT.INTENT:{lob.confidence > 0.3} In this example, if we have detected a book flight input with 30% confidence or better, we decide to prefer this intent, even if a different top intent was selected.
%AIRPORT.LIST:{AirportHelpers.IsKnownDestination(lob.airportCode)}^{destinations<< lob.airportCode} This example shows calling a service to see if a detected airport is one of the destinations covered by the travel system. If the predicate script is true, the propagation script will additionally append the airport code to a list of destinations. Note: though flow and session variables are not available in predicate scripts, you are able to call functions.
%$NUMBER:{(lob.numericValue.remainder(java.math.BigDecimal.ONE)) == 0} Use the number annotation to match to whole numbers only.
(%$PERSON.NER/%NAMES.LIST):{!(_USED_WORDS.toLowerCase() in ["frank" , "frankie", "franklin"])} Match to all names except variations of "Frank", e.g. in case Frank is the bot's name. Note: this condition could also be rewritten as ((%$PERSON.NER/%NAMES.LIST)!&=(frank/frankie/franklin))
%CONTACT_REQUEST.PHR:{lob.chatAvailable=="true"} The language object for contact requests could call a service to check if a live agent is available, and if so, signal it via an NLU variable. The flow using this trigger condition would start the live chat immediately.
%CONTACT.NNVB.SYN+%COMPANY_CITIES.ENTITY:{lob.telephone!=""}^{telephone=lob.telephone} Here we have an entity COMPANY_CITIES.ENTITY that recognizes all company locations, but only some of them have a contact number. If a location does not have a number, the NLU variable would be blank. The predicate script prevents our contact flow from triggering for cities that cannot yet be contacted.
%COUNTRIES_EUROPE_EU.LIST:{lob.TLR_sCountryCode!="GB"} All countries in the EU, excluding Britain.

Was this page helpful?