I’m developing an Alexa Skill with ASK-SDK v2 for Node.js that needs to retrieve data from an Airtable database. When users ask about a character’s name, the skill should query the database and return a simple description.
However, during my testing in the Skill Builder, even when the JSON input shows an ER_SUCCESS_MATCH, the output displays the recognized value as UNDEFINED. I hear the message, “I can’t find UNDEFINED in my database,” regardless of the character name I inquire about.
I suspect the skill is not properly connecting to the Airtable base, even though I believe I have entered the correct API key and Airtable parameters in my code. I would expect an ‘IN AIRTABLE GET’ entry to appear in my AWS Lambda logs, between ‘IN CHARACTER HANDLER’ and ‘END RequestID’, but instead, I’m going directly from ‘IN CHARACTER HANDLER’ to ‘END RequestID’, indicating that the Airtable database isn’t being accessed.
Here’s the entire Index.js code (excluding the Skill number, API Key, and character name column key). Can anyone identify any issues? Thank you for your assistance!
'use strict';
const Alexa = require('ask-sdk');
const https = require('https');
const APP_ID = "amzn1.ask.skill.xxxxxxxxxxxxxxxxxxxx";
const EmptyHandler = {
canHandle(handlerInput) {
return false;
},
handle(handlerInput, error) {
return handlerInput.responseBuilder
.speak()
.reprompt()
.getResponse();
}
};
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "LaunchRequest";
},
handle(handlerInput, error) {
console.log("IN LAUNCH REQUEST");
return handlerInput.responseBuilder
.speak("Accessing the Skill. Ask me any character's name.")
.reprompt("Go ahead, start asking.")
.getResponse();
},
};
const CharacterHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.requestEnvelope.request.intent.name === "CharacterIntent";
},
handle(handlerInput, error) {
console.log("IN CHARACTER HANDLER");
var spokenValue = getSpokenValue(handlerInput.requestEnvelope, "character");
var resolvedValues = getResolvedValues(handlerInput.requestEnvelope, "character");
//NO MATCHES FOUND
if (resolvedValues === undefined) {
return handlerInput.responseBuilder
.speak("I can't find " + spokenValue + " in my database." + getRandomQuestion())
.reprompt("" + spokenValue + " is not in my database. " + getRandomQuestion())
.getResponse();
}
//ONLY ONE MATCH FOUND
else if (resolvedValues.length === 1) {
var filter = "&filterByFormula=%7BName%7D%3D%22" + encodeURIComponent(resolvedValues[0].value.name) + "%22";
return new Promise((resolve) => {
airtableGet("appXXXXXXXXXX", "Character", filter, (record) => {
console.log("AIRTABLE RECORD = " + JSON.stringify(record));
var speechText = "Accessing to " + spokenValue + "<break time='.5s'/>" + record.records[0].fields.VoiceDescription;
console.log("RESPONSE BUILDER = " + JSON.stringify(handlerInput.responseBuilder));
resolve(handlerInput.responseBuilder
.speak(speechText)
.reprompt(getRandomQuestion())
.getResponse());
});
});
}
//MORE THAN ONE MATCH FOUND. DISAMBIGUATE.
else if (resolvedValues.length > 1) {
var valuesString = getValuesString(resolvedValues);
return handlerInput.responseBuilder
.speak("You asked for " + spokenValue + ", but I have different matches for that name. Did you mean " + valuesString + "?")
.reprompt("Which one do you mean: " + valuesString + "?")
.getResponse();
}
}
};
// Remaining code omitted for brevity
Does anyone see what’s wrong with my implementation?