Identifying intents which are candidates for selection

So let us take a closer look at how to identify intents which are candidates for selection.

Update Nov 2020: I have created a free tool which helps you identify candidate intents. You can check it out here. 

An example

Suppose your team decides you are spending way too much time clicking into DialogFlow intents to find what contexts are declared inside of them. So you decide to do the following: you add an intent number at the beginning. Then you also add the context names inside brackets (parentheses) immediately after, and then you write the intent name. You will use empty brackets to indicate that there is no input context. This allows you to see the full picture at a glance. Please don’t actually use this convention. 🙂 It is meant to be a funny illustration.

For example, a very simple example would look like this:

In the agent above, we have two contexts – c1 and c2 and 4 intents.

How contexts affect the intent

In case you were not 100% clear, an intent can fire only if all its input contexts are active. (By fire, I mean it will be selected as the intent to handle a given user input).

For example, unless both c1 and c2 are active, intent 4 will not fire.

What is an active context?

Another important consideration is what exactly we mean when we say a ‘context is active’. Here is my working definition: a context is active if it was set as the output of a previous intent (let us ignore REST API based activations), and the lifespan has not become zero by the time the user types their message.

For example, if an intent which just fired set the context c1 with a lifespan of 1. Now user types a message, and the intent 2 gets fired. Now the lifespan of c1 has become 0 (because one turn of request-response was completed) if intent 2 does not set an output context. At this point, context c1 is not active.

Once again, if this wasn’t super clear, watch the video I mentioned before the beginning of this section.

Selection candidates

Based on what we have seen till now, you can make the following statements:

The context powerset determines the candidate selection list

Are you familiar with the notion of the powerset from mathematics? If you have a set S, the power-set of S is the set of all subsets, including the set S as well as the empty set.

To give an example, suppose context c1 and c2 are both active. Now the context powerset is:

[(), (c1), (c2), (c1, c2)]

In other words, an intent which has any of these in the prefix of its name is a candidate for selection.

As you can see, if both contexts c1 and c2 are active, this means all the intents are now candidates for selection. If three contexts are active, say c1, c2 and c3, then the number of subsets is “2 to the power of 3” = 8. In that case, these are the context combinations that will trigger an intent: [(), (c1), (c2), (c3), (c1,c2), (c2,c3), (c1,c3), (c1,c2,c3)]. Generally speaking, if N contexts are active, you will have 2^N such combinations.

An intent with empty context is always a selection candidate

Another thing to notice is that since the empty set is always a subset of every other set, including itself, an intent with empty context is always a selection candidate.

It is quite obvious that intent 1 is a selection candidate if no contexts are active. But what people sometimes miss is that even if the context c1 is active, intent 1 is still a selection candidate.

The intent blackhole

If you have been following along, you might see the problem with an intent which is defined like this:

So what we have here is an intent (number 5) with no input context, and exactly one userSays phrase which has nothing except the wildcard entity. Creating such an intent is not a good idea.

What you have created is basically a perennial selection candidate. Because remember, even if a context has been set, since intent 5 has no input context, it is always a candidate for selection. And since it has nothing more than a wildcard entity, it will accept any and all input.

DialogFlow is able to give you answers for slight variants of a user’s expected input because it gives the user some “margin” to go wrong. Margin is not a standard or official term, but I have quoted it because it is an important concept. Usually, the margin is based on the threshold you set in the agent’s settings. If you set the ML threshold very high (say 0.99), almost nothing will match except exact phrases matching what is already in the userSays. Usually, though, we want lower ML thresholds because we want to encourage a higher margin of error from the user. After all, that is what makes the chatbot look very smart – being able to “pick up” on what the user said even if they don’t exactly match what is already defined in the intent.

When you create this wildcard based intent – every time the user’s message misses its “margin of error” with respect to the other intents, it will invoke this intent. Because DialogFlow thinks, “Heck, why not?” It is like an intent blackhole which consumes everything which comes its way 🙂


Here is a quick summary of which active contexts will enable which intent as a selection candidate. (I am ignoring intent 5 for this).

Read as:

Set of active input contexts (enables) -> Set of Intents (the Selection candidates)

() -> (1)

(c1) -> (1, 2)

(c2) -> (1, 3)

(c1,c2) -> (1, 2, 3, 4)