Join the Actions on Google Developer Challenge to win a trip to Google I/O 2018 and more than 20 other prizes.

Build Fulfillment

Fulfillment defines the conversational interface for your app to obtain user input and the logic to process the input and eventually fulfill the action.

Define your conversation

Now that you've defined actions, you can build the corresponding conversation for those actions. You do this by creating API.AI intents that define the grammar or what users need to say to trigger the intent and the corresponding fulfillment to process the intent when it's triggered.

You can create as many intents as you'd like to define your entire conversation's grammar.

Create intents

Click the + sign by the Intents menu item in API.AI's left navigation. The Intent Editor appears where you can enter the following information:

  • Intent name is the name of the intent that's displayed in the IDE.
  • Contexts let you scope the triggering of the intent to specific cases. This is an advanced feature of API.AI, so read the API.AI documentation on Contexts for more information.
  • User says phrases define what users need to say (the grammar) to trigger the intent. Type a few phrases here (5-10) of what users can say to trigger the intent. API.AI automatically handles natural variations of the example phrases you provide.
  • Events trigger intents without the need for users to say anything. The only event that is currently supported is the GOOGLE_ASSISTANT_WELCOME event, which allows the Google Assistant to invoke your app. This event is used for your app's default action.
  • Action defines what to data to pass to fulfillment, if fulfillment is enabled for this intent. This includes data parsed from the user input and the name that you can use in your fulfillment to detect which intent was triggered. You'll use this name later when you create an action map, which maps an intent its corresponding fulfillment logic. See the Actions and Parameters in the API.AI documentation for more information about defining actions.

  • Response - The API.AI Response Builder lets you define the response to this intent directly within API.AI, without calling fulfillment. This feature is useful for responses that are static and don't require fulfillment. You might use this for things such as simple welcome or goodbye messages. However, you will likely use fulfillment to respond to your users for most intents.

  • Fulfillment specifies whether or not you want to call your fulfillment when this intent is triggered. You most likely will enable this for most intents in your API.AI agent. To see this item in the intent, you must have fulfillment enabled for the agent in the Fulfillment menu.

  • Actions on Google lets you specify platform-specific settings for the intent. Currently, only End conversation is supported. This closes the mic and ends the conversation after the corresponding response is returned to the user. This setting only honored if you don't use fulfillment for the intent.

Building responses in API.AI

For some intents, you might not need to have your fulfillment return a response. In these cases, you can use the response builder in API.AI to create responses.

In the Response area, specify either a Default Text Response or an Actions on Google Response. Default text responses are simple TTS text responses that can work across multiple API.AI integrations. Responses for the Google Assistant, which you'll most likely want to use, are described in the Responses document.

Building fulfillment responses

When an intent is triggered that uses fulfillment, you receive a request from API.AI that contains information about the intent. You then respond to the request by processing the intent and returning a response. This request and response is defined by the API.AI webhook.

However, we highly recommend that you use the Node.js client library to process requests and return responses. Here's the general process for using the client library:

  1. Initialize the ApiAiApp object. This object automatically handles listening for requests and parsing them so that you can process them in your fulfillment.
  2. Create functions to handle requests. These functions process the user input and other components of the intent and build the response to return to API.AI.
  3. Build and initialize an action map that maps intents to functions. Whenever an intent is triggered in your API.AI agent, it contains an action name. You can map action names to functions to automatically have the appropriate function called.

Initialize the ApiAiApp object

The following code instantiates ApiAiApp and does some boilerplate Node.js setup for Google Cloud Functions:

'use strict';

const ApiAiApp = require('actions-on-google').ApiAiApp;

exports.echoNumber = (req, res) => {
  const app = new ApiAiApp({request: req, response: res});

  // Create functions to handle requests here

}

Create functions to handle requests

When users speak a phrase that triggers an intent, you receive a request from API.AI that you handle with a function in your fulfillment. In this function, you'll generall do following things:

  1. Carry out any logic required to process the user input. You'll typically call the following get functions to get user input from the request.

    • getArgument() - Gets values from query pattern arguments by name
    • getRawInput() - Gets the user's raw input as a string.
  2. Build your responses to respond to triggered intents. Take into account the surface that your users are using to construct appropriate responses. See conversation basics for more information on how to cater responses for different surfaces.

  3. Call the ask() or tell() function with your response.

The following code shows you how to build two TTS reponses that handles an invocation intent (input.welcome) and a dialog intent (input.number) that welcomes the user to your app and echoes back a number that a user has spoken for an API.AI intent with the name:

const app = new ApiAiApp({request: request, response: response});

const WELCOME_INTENT = 'input.welcome';  // the action name from the API.AI intent
const NUMBER_INTENT = 'input.number';  // the action name from the API.AI intent
const NUMBER_ARGUMENT = 'input.mynum'; // the action name from the API.AI intent

function welcomeIntent (app) {
  app.ask('Welcome to number echo! Say a number.');
}

function numberIntent (app) {
  let number = app.getArgument(NUMBER_ARGUMENT);
  app.tell('You said ' + number);
}

Build and initialize an action map

Once you have all your functions to handle triggered intents, build an action map to map intents to functions. For example, the following code:

  • Instantiates a new action map
  • Maps the input.welcome action name to the welcomeIntent() function
  • Maps the input.number action name to the numberIntent() function.
  • Tells the ApiAiApp object to route incoming intents to the corresponding function defined by the action map.

let actionMap = new Map(); actionMap.set(WELCOME_INTENT, welcomeIntent); actionMap.set(NUMBER_INTENT, numberIntent); app.handleRequest(actionMap);

If you have only one handler function, then you don't need to do this and just pass in the function name to handleRequest(). In this case, all triggered intents will call this function, so you have to check for the intent that is triggered to do the appropriate thing.

const WELCOME_INTENT = 'input.welcome';
const NUMBER_INTENT = 'input.number';
const NUMBER_ARGUMENT = 'input.mynum';

function responseHandler (app) {
  // intent contains the name of the intent you defined in the Actions area of API.AI
  let intent = app.getIntent();
  switch (intent) {
    case WELCOME_INTENT:
      app.ask('Welcome! Say a number.');
      break;

    case NUMBER_INTENT:
      let number = app.getArgument(NUMBER_ARGUMENT);
      app.tell('You said ' + number);
      break;
  }
}
// you can add the function name instead of an action map
app.handleRequest(responseHandler);

No-match reprompting

When API.AI cannot match any of the input grammars defined in the User says portion of your intents, it triggers a fallback intent. Fallback intents typically reprompt the user to provide the necessary input for your action. You can provide reprompt phrases by specifying them in the Response area of a fallback intent or you can use a webhook to provide responses.

To create fallback intents:

  1. Click Intents in the left navigation of API.AI.
  2. Click the menu icon to the right of the Create Intent button and select Create Fallback Intent. Alternatively, click the Default Fallback Intent to edit it.

  3. Specify reprompt phrases to speak back to users. These phrases should be conversational and be as useful as possible to the user's current context.

    To do this without fulfillment:

    Specify phrases in the Response area of the intent. API.AI randomly chooses phrases from this list to speak back to users until a more specific intent is triggered.

    To do this with fulfillment:

    1. Select the Use webhook checkbox in the Fulfillment area of the intent.
    2. In your fulfillment logic, handle the fallback intent that gets triggered like with any other intent, as described in creating functions to handle requests.

    For example, the following function uses the app.data object (an arbitrary data payload that you can use to maintain state) to store a counter that tracks how many times a fallback intent is triggered. If it's triggered more than once, the action quits. You can then reset the counter when any other intent is triggered.

    function defaultFallback (app) {
        app.data.fallbackCount++;
        // Provide two prompts before ending game
        if (app.data.fallbackCount === 1) {
          app.setContext(DONE_YES_NO_CONTEXT);
          app.ask('Are you done playing Number Genie?');
        } else {
          app.tell('Since I\'m still having trouble, so I\'ll stop here. Let’s play again soon.');
        }
      }
    

    See the Number Genie sample for details on how to implement this.

Using contexts

Use contexts if you want API.AI to trigger falllback intents only in certain situations. This is helpful if you want to have different fallback intents for different no-match scenarios.

  • If you don't set contexts on a fallback intent, it's considered to be a global fallback intent that API.AI triggers when no other intent is matched. You should only have one of these defined if you choose to use one.
  • If you set input contexts on a fallback intent, API.AI triggers this fallback intent when the following is true:

    • The user's current contexts are a superset of the contexts defined in the intent.
    • No other intent matches.

    This lets you use multiple fallback intents with different input contexts to customize no-match reprompting to specific scenarios.

  • If you set an output context on a fallback intent, you keep the user in the same context after the fallback intent is triggered and processed.

See API.AI Contexts for more information.

No-input reprompting

When you call the ask() method to return responses to users, you can specify an array of prompts that is spoken to users if the Google Assistant can't detect any input. The Google Assistant speaks these prompts in order, and you can specify up to three prompts. For example:

app.ask(`Guess a number`,
  ['I didn\'t hear a number', 'If you\'re still there, what\'s your guess?',
    'We can stop here. Let\'s play again soon.']);