/alexa-runtime

Voiceflow Alexa Service

Primary LanguageTypeScript

alexa-runtime

circle ci Coverage sonar quality gate

alexa-runtime is an http webhook service that handles Alexa requests and generates a response. It manages the state of the Alexa user based on the programs (flows) made on the Voiceflow Creator tool. It can be run independently from Voiceflow.

This is the same service that hosts all Alexa skills created on Voiceflow. This includes serving production apps on and handling millions of requests.

image

client architecture

client architecture

Upon uploading to Alexa through the desktop, it is important that on your Alexa Developer Console for the skill, that the webhook endpoint is pointed at the alexa-runtime - it essentially acts in place of the typical Lambda Function.

Screen Shot 2021-04-08 at 2 41 31 PM

It is important to understand the Alexa Request/Response webhook model https://developer.amazon.com/en-US/docs/alexa/custom-skills/request-and-response-json-reference.html

Anatomy of an interaction

  1. user says something to Alexa, Alexa uses natural language processing to transcribe user intent, then sends it via webhook (along with other metadata i.e. userID) to alexa-runtime
  2. fetch user state (JSON format) from end user session storage based on a userID identifier
  3. fetch project version data for initialization parameters from Voiceflow API/Project File
  4. fetch the current program (flow) that the user is on from Voiceflow API/Project File
  5. go through each block and update the user state
  6. save the final user state to end user session storage
  7. generate a response based on the final user state, send back to Alexa
  8. Alexa interprets response and speaks to user

repeat all steps each time a user speaks to the Alexa skill, to perform a conversation

configurations

local/debugging setup

export your voiceflow project from the creator tool. Each time you update your project you will need to export again. You can find the export option here:

Screenshot from 2020-09-07 12-14-44

It should save a .vfr (voiceflow runtime) JSON file from your browser that would be named similar to this: VF-Project-nPDdD6qZJ9.vfr

fork voiceflow/alexa-runtime and clone to your local machine. Ensure nodejs, npm, and yarn are set up on your local machine. Run yarn to install all dependencies.

Add your VF-Project JSON file under projects/

Also add the following file to the local repository:

.env.local

SESSIONS_SOURCE='local'
PROJECT_SOURCE='[YOUR EXPORTED PROJECT FILE HERE (i.e. VF-Project-nPDdD6qZJ9.json)]'

PORT=4000
SESSIONS_DYNAMO_TABLE="none"

LOG_LEVEL="debug"
MIDDLEWARE_VERBOSITY="short"

PG_USERNAME='PG_USERNAME'
PG_HOST='PG_HOST'
PG_DBNAME='PG_DBNAME'
PG_PASSWORD='PG_PASSWORD'
PG_PORT='PG_PORT'

Install a localhost tunnel tool such as ngrok, or localtunnel, or bespoken proxy. This will allow you expose a localhost endpoint on the internet for Alexa to hit. For the purposes of this guide, we will implement ngrok

Run your local instance of voiceflow/alexa-runtime with

yarn start:local

This will now be running on port 4000 of localhost. Expose this with

ngrok http 4000

In your shell you will see a link similar to this - https://e9g1335dd0ac.ngrok.io, note this down. Ensure you copy the https:// version instead of http://

On https://developer.amazon.com/alexa/console/ask find the skill uploaded by the creator tool, click into it. On the left bar, select "Endpoint", it should say something similar to https://alexa.voiceflow.app/state/skill/[versionID]. Replace the https://alexa.voiceflow.app portion with your own ngrok endpoint. It should end up looking something like this:

Screenshot from 2020-09-07 12-48-15 (make sure that it ends with /state/skill/[versionID])

You should now be able to test your skill using the Alexa Developer Console Skill Testing tool or on an actual Alexa device and see that it is executing on your local machine.

with this .env.local configuration, the google sheets, zapier blocks will not work

every time you make changes on Alexa you will need to export again, move the project file to /projects and update PROJECT_SOURCE in .env.local and restart voiceflow/client - finally update the endpoint again on ADC (it will be overwritten by https://alexa.voiceflow.app again)

Notable Code Locations

lib/controllers/alexa.ts - this is where the raw request and response are handled. You can log the request object and response object to help debug.

lib/services/voiceflow/handlers - handlers for all the various blocks and defining their behavior

lib/services/alexa/request/lifecycle - various side effects during the request/response lifecycle

lib/services/alexa/local.ts - If SESSIONS_SOURCE='local', this is where user state is being saved, can be logged.

environment variables

voiceflow/alexa-runtime reads environment variables from a .env.[environment] file, where [environment] is either local or production depending on if you run yarn start:local or yarn start, respectively. (there is also an .env.test for integration tests)

key types

name example/values desc required
PORT 4000 http port that service will run on YES
PROJECT_SOURCE VF-Project-nPDdD6qZJ9.json JSON File inside /projects to read project - uses remote VF_DATA_ENDPOINT if undefined NO
SESSIONS_SOURCE local | dynamo | postgres | mongo if local read/write sessions to memory, otherwise default to dynamo NO
VF_DATA_ENDPOINT http://localhost:8200 cloud endpoint to read Voiceflow project, ignored if PROJECT_SOURCE is defined YES
LOG_LEVEL none | warn logging verbosity and detail NO
MIDDLEWARE_VERBOSITY none | warn | debug request/response logging verbosity and detail NO

session source

  • local
    • stored in memory. All user sessions are lost if the server restarts, this is meant for debugging and prototyping.
  • dynamo
    • Amazon's preferred method. If using dynamo define the DYNAMO_ENDPOINT, AWS_REGION, SESSIONS_DYNAMO_TABLE env variables.

If you want to add your own database or custom methods, feel free to look at the lib/services/alexa folder and contribute there.

still under development

  • mongo
    • alternative NoSQL solution. If using mongo define the MONGO_URI, MONGO_DB env variable. Reads from a runtime-sessions collection.
  • postgres
    • SQL solution. If using postgres define the PG_USERNAME,PG_HOST,PG_DBNAME,PG_PASSWORD,PG_PORT env variables. Reads from the _sessions table.

handlers

These environment variables are optional and meant for specific blocks that have microservices that perform external functions. If left undefined the code/API block will run their requests locally on this server, as long as the project is trusted it is not an issue.

name example/values desc required
CODE_HANDLER_ENDPOINT http://localhost:8804 stateless cloud service endpoint to execute the code block NO