Skill Builder Objects – To Customize or Not To Customize

When building your skill using the Alexa Skills Kit Software Development Kit (SDK), one of the first things you do is choose which type of skill builder object to use – Standard or Custom. If you copied a sample skill, this choice may not have been a conscious choice. If you’re not sure which one your skill is using, find the block of code that looks like this:

const skillBuilder = Alexa.SkillBuilders.custom();

exports.handler = skillBuilder

  .addRequestHandlers(

    LaunchRequestHandler,

…

    SessionEndedRequestHandler

  )

  .addErrorHandlers(ErrorHandler)

.lambda();

This example is from a skill built using the Alexa Skills Kit SDK for Node.js. If you’re using the SDK for Python it’ll look similar; search for “SkillBuilder.”  If you’re using the SDK for Java, your SkillBuilder will extend SkillStreamHandler.

Now that you’ve found the SkillBuilder you’re using, what are the differences, and when should you use each type? Let’s take a look.

Skill-Building Foundation

Both types of SkillBuilders derive from a common base type, which means they have some things in common. You can add Request Handlers, Request Interceptors, Response Interceptors and Error Handlers to all SkillBuilders. (If you’re not familiar with these features, you can learn more in this blog.) Additionally, you can further customize the User Agent reported as part of your skill’s response or set the SkillId used for request validation if you don’t want to use the AWS Lambda trigger validation (for example, when you’re using the SDK but not using Lambda).

Here’s where things start to diverge. The SDK provides tools and utilities that make skill building easier. This frees you up from having to create code to manage persistent attributes, or to implement retries when calling a throttled API. While these tasks may be common, the SDK does not require you to use a specific persistence layer (or database); you can choose from the available persistence adapters or even create your own, yet still fully leverage the SDK. Similarly, you might want to use your own API client rather than use the one provided with the SDK. This flexibility is why there are different SkillBuilders.

SkillBuilder Tradeoffs

The Standard SkillBuilder object comes preconfigured to use the “default API client” and the Amazon DynamoDB persistence adapter and is included in the full SDK. (Note: Using the Amazon DynamoDB persistence adapter does not automatically grant your skill access to DynamoDB – access is controlled through an AWS IAM policy.) In general, using the Standard SkillBuilder is the simplest way to get started. To use Standard, include the full SDK (ask-sdk), which also includes the core SDK. The core SDK (ask-sdk-core) only includes the Custom SkillBuilder to avoid requiring unneeded dependencies.

The most common reasons to use the Custom SkillBuilder instead are that you need to use a different persistence adapter, or you don’t want to include extra dependencies in your code package. Let’s look at both of these scenarios.

Setting the Persistence Layer

The most common case for needing a different persistence adapter is for those skills which are Alexa-hosted skills. This offering currently includes Amazon S3 as the persistence layer, so when creating your skill, you will be required to use the Custom SkillBuilder if you are persisting any attributes. To use the S3 persistence adapter in Node.js, add this line of code to your SkillBuilder setup:

.withPersistenceAdapter(new s3Adapter.S3PersistenceAdapter({bucketName:process.env.S3_PERSISTENCE_BUCKET})

Note: In the above example, it’s assumed you’re using Alexa-hosted and your S3 bucket name is available as an environment variable. To use a different bucket, change the bucketName value passed to the constructor.

In addition, you’ll need to import the S3 persistence adapter since it isn’t included by default. Add this to your code:

const s3Adapter = require('ask-sdk-s3-persistence-adapter');

Include this code as a dependency by adding this to your package.json:

"ask-sdk-s3-persistence-adapter": "^2.0.0"

It’s important to remember that since you’ve taken advantage of persistence layer flexibility, you must also add an API client since one wasn’t included by default. If you miss this step, you may see errors like the below when you attempt to use one of the Alexa APIs:

Cannot read property 'getMonetizationServiceClient' of undefined

Adding the default API client can be done by adding this line of code to your SkillBuilder setup:

.withApiClient(new Alexa.DefaultApiClient())

If you are only getting API client related errors, a cleaner fix is to change your SkillBuilder type to Standard; however, that’s only recommended if you can also use the DynamoDB persistence adapter.

Avoid Extra Dependencies

The second common reason to use the Custom object over the Standard object is to avoid extra dependencies. If you use only the Custom SkillBuilder, you only need to include the core SDK (ask-sdk-core). This does not include the DynamoDB persistence adapter, which in turn means the AWS SDK is not included since it is not required. A smaller deployment package is helpful if you are bundling your dependencies and want to edit your code directly in the Lambda console, or if you want quicker deployments. With the introduction of features like Layers, you should be freed from some of these restrictions and able to focus on choosing the right SkillBuilder for your use case.

Not a One-Way Door

If you started with one SkillBuilder type and decide you want to switch, you’re in luck. To move to the Standard SkillBuilder, first ensure you are including the full SDK (ask-sdk), then change “SkillBuilder.Custom()” to “SkillBuilder.Standard()” and remove any persistence or api client setup calls.

Note: If you have customized your persistence adapter configuration, you will need to bring that along in your conversion. If you have done that, it’s likely better to stick with the Custom SkillBuilder rather than risk break something.

To move to a Custom SkillBuilder that is configured the same as the Standard one, change “SkillBuilder.Standard()” to “SkillBuilder.Custom()”.  Then add these lines of code to your SkillBuilder setup:

.withPersistenceAdapter(new DynamoDbPersistenceAdapter({

    tableName: 'MySkillTableName',

    createTable: true

})

.withApiClient(new Alexa.DefaultApiClient())

The last step is to adjust your dependencies (if you want to). The full SDK (ask-sdk) includes all the required dependencies, but you can decompose them into the core SDK (ask-sdk-core) and the DynamoDB persistence adapter (ask-sdk-dynamodb-persistence-adapter).

More Resources

I hope this information helps you in understanding the difference between Standard and Custom SkillBuilders so you can confidently choose the one that is best for your skill. We look forward to seeing what you build. Tweet me @franklinlobb and I’d be happy to check it out! Check out the following resources to dive deeper: