The problem is that programming for the Assistant is an event-driven system (each Intent is an event), and you end the processing of the event on the server with assistant.ask()
or assistant.tell()
. This sends your reply back to the user. ask()
will then wait for another event, while tell()
indicates that the conversation is over.
This means you can't put ask()
inside a loop and you can't store results in a local variable, since each answer will come back to you as a new event (ie - a new call to your webhook each time).
Here is a way to do it. It consists of three parts:
- An intent (name.init in my screen shot) that is used to first call the webhook with an action
name.entry
and trigger the loop.
- An intent (name.loop in my screen shot) that responds when the
name_loop
context is active to get the name and send it to the webhook with the same action name.entry
.
- A code fragment for handling the
name.entry
intent.


Code
var loopAction = function( assistant ){
const CONTEXT = 'name_loop';
const PARAM = 'name';
const VALUE = 'index';
const NUM_NAMES = 4;
// Get the context, which contains the loop counter index, so we know
// which name we're getting and how many times we've been through the loop.
var index;
var context = assistant.getContext( CONTEXT );
if( !context ){
// If no context was set, then we are just starting the loop, so we
// need to initialize it.
index = 0;
} else {
// The context is set, so get the invex value from it
index = context.parameters[VALUE];
// Since we are going through the loop, it means we were prompted for
// the name, so get the name.
var name = assistant.getArgument( PARAM );
// Save this all, somehow.
// We may want to put it back in a context, or save it in a database,
// or something else, but there are things to be aware of:
// - We can't save it in a local variable - they will go out of scope
// after we send the next reply.
// - We can't directly save it in a global variable - other users who
// call the Action will end up writing to the same place.
loopSave( index, name );
// Increment the counter to ask for the next name.
index++;
}
if( index < NUM_NAMES ){
// We don't have all the names yet, ask for the next one
// Build the outgoing context and store the new index value
var contextValues = {};
contextValues[VALUE] = index;
// Save the context as part of what we send back to API.AI
assistant.setContext( CONTEXT, 5, contextValues );
// Ask for the name
assistant.ask( `Please give me name ${index}` );
} else {
// We have reached the end of the loop counter.
// Clear the context, making sure we don't continue through the loop
// (Not really needed in this case, since we're about to end the
// conversation, but useful in other cases, and a good practice.)
assistant.setContext( CONTEXT, 0 );
// End the conversation
assistant.tell( `I got all ${index}, thanks!` );
}
};