Plugins allow you to modify how the StateMachineSkill handles an alexa event. When a plugin is registered it will use the different hooks in your skill to add functionality. If you have several skills with similar behavior then your answer is to create a plugin.

Using a plugin

After instantiating a StateMachineSkill you can register plugins on it. Built in plugins can be accessed through Voxa.plugins

'use strict';
const { VoxaApp, plugins } = require('voxa');
const Model = require('./model');
const views = require('./views'):
const variables = require('./variables');

const app = new VoxaApp({ Model, variables, views });


State Flow plugin

Stores the state transitions for every alexa event in an array.


State Flow attaches callbacks to onRequestStarted(), onBeforeStateChanged() and onBeforeReplySent() to track state transitions in a voxaEvent.flow array



const alexa = require('alexa-statemachine');

app.onBeforeReplySent((voxaEvent) => {
  console.log(voxaEvent.flow.join(' > ')); // entry > firstState > secondState > die

Replace Intent plugin

It allows you to rename an intent name based on a regular expression. By default it will match /(.*)OnlyIntent$/ and replace it with $1Intent.

replaceIntent(app[, config])

Replace Intent plugin uses onIntentRequest() to modify the incoming request intent name

  • app (VoxaApp) – The stateMachineSkill
  • config – An object with the regex to look for and the replace value.


const app = new Voxa({ Model, variables, views });

Voxa.plugins.replaceIntent(app, { regex: /(.*)OnlyIntent$/, replace: '$1Intent' });
Voxa.plugins.replaceIntent(app, { regex: /^VeryLong(.*)/, replace: 'Long$1' });

Why OnlyIntents?

A good practice is to isolate an utterance into another intent if it contains a single slot. By creating the OnlyIntent, Alexa will prioritize this intent if the user says only a value from that slot.

Let’s explain with the following scenario. You need the user to provide a zipcode. You would have an intent called ZipCodeIntent. But you still have to manage if the user only says a zipcode without any other words. So that’s when we create an OnlyIntent. Let’s call it ZipCodeOnlyIntent.

Our utterance file will be like this:

ZipCodeIntent here is my {ZipCodeSlot}
ZipCodeIntent my zip is {ZipCodeSlot}

ZipCodeOnlyIntent {ZipCodeSlot}

But now we have two states which are basically the same. Replace Intent plugin will rename all incoming requests intents from ZipCodeOnlyIntent to ZipCodeIntent.

CloudWatch plugin

It logs a CloudWatch metric when the skill catches an error or success execution.


cloudwatch(app, cloudwatch[, eventMetric])

CloudWatch plugin uses VoxaApp.onError() and VoxaApp.onBeforeReplySent() to log metrics



const AWS = require('aws-sdk');
const app = new Voxa({ Model, variables, views });

const cloudWatch = new AWS.CloudWatch({});
const eventMetric = {
  MetricName: 'Caught Error', // Name of your metric
  Namespace: 'SkillName' // Name of your skill

Voxa.plugins.cloudwatch(app, cloudWatch, eventMetric);

Autoload plugin

It accepts an adapter to autoload info into the model object coming in every alexa request.


autoLoad(app[, config])

Autoload plugin uses app.onSessionStarted to load data the first time the user opens a skill

  • app (VoxaApp) – The stateMachineSkill.
  • config – An object with an adapter key with a get Promise method in which you can handle your database access to fetch information from any resource.


const app = new VoxaApp({ Model, variables, views });

plugins.autoLoad(app, { adapter });