Your Alexa Dashboards Settings

Steps to Build a Smart Home Skill

This topic provides the steps for creating a smart home skill that responds synchronously to directives. The steps will walk you through skill creation in the developer portal, creating an AWS Lambda function, configuring and testing your skill, and submitting it for certification.

Register as an Amazon Developer and Create the Skill

To configure a new smart home skill, you need an account on the Amazon Developer Portal. If you don’t already have an account, go to https://developer.amazon.com/login.html and create an account. Registering is free. Once you’ve registered:

  1. Open the Amazon Developer Portal in a browser and log in.
  2. Navigate to the Alexa section by selecting Alexa in the top navigation.
  3. In the Alexa Skills Kit box, click Get Started.
  4. Click the Add a New Skill button.
  5. On the Skill Information page, select Smart Home Skill API, and enter the Name for your skill. Note that your skill’s name must not indicate that it’s functionality is limited. For example, you should not use “basic”, “reduced” or “simple” in the title of your skill.
  6. Select the language for your skill. You can add additional languages later. For more information on adding another language to your skill, see Develop Smart Home Skills in Multiple Languages
  7. Under Payload Version, select v3. Building skills that target v2 is strongly discouraged.
  8. Click Save. and copy the Application Id for the skill to the clipboard. The application Id will be in a format similar to the following: amzn1.ask.skill.1a2b55555-c325-1234-d56e-1f234d5e6a78

Add a Lambda Function

You will need an AWS account and some basic knowledge of AWS. The code for your smart home skill is hosted as a Lambda function on AWS. AWS Lambda is a service that lets you run code in the cloud without managing servers. Alexa sends your skill requests and your code inspects the request, takes any necessary actions such as communicating with the device cloud for that customer, and then sends back a response.

To get started, sign in to your AWS Account,.

Create an IAM Role for Lambda

If you haven’t worked with Lambda before, you will need to create an Identity and Access Management (IAM) role that enables basic execution. To create an IAM role. Navigate to the IAM console. If you already have a role that enables Lambda basic execution, skip to the next section.

  1. Choose Roles and click Create a new role.
  2. Select AWS Lambda under AWS Service Role.
  3. Type “basic” in the filter box and choose the AWSLambdaBasicExecutionRole, and click Next Step.
  4. Enter a name that identifies this role and click Create role.

Create a Lambda function and add code

  1. On the AWS Console, under Compute, select Lambda.
  2. Make sure you’ve selected N.Virginia for English (US) skills, EU (Ireland) region for English (UK), English (India) or German skills, or US West (Oregon) for Japanese and English (Australia) skills. The region is displayed in the upper right corner. Providing your Lambda function in the correct region prevents latency issues.
  3. Click Create a Lambda function.
  4. On the Select blueprint page, type home in the filter box. Select the alexa-smart-home-skill-adapter.
  5. On the Configure triggers page, the Alexa Smart Home trigger will already be configured. Add the Application Id from the developer portal. 
  6. Leave Enable trigger checked. This enables the Amazon Alexa service to call your Lambda function. If you don’t enable it when you create, you will not be able to enable it in the console later.
  7. Click Next.
  8. On Step 3: Configure function, enter the following:
    • Name: A name for your Lambda function. This name is appears in the AWS console and is also returned by the AWS command-line interface (CLI) ListFunctions API. It should be unique across your Lambda functions.
    • Description: Optionally provide a description.
    • Runtime: To use the sample code provided in this topic, choose Node.js 6.10 or alternatively, select the runtime for the code you plan to write. Supported languages are: Node.js, Java, Python, or C#.
  9. For Lambda function code, make sure Edit code inline is selected.
  10. Paste in the following code. This code provides a starting point for implementing a smart home skill and provides the basic structure for responding to a discovery and one control request. You will need to add code for your device types and the interfaces your devices support. You can find additional sample code in the GitHub repository for Alexa smart home.
exports.handler = function (request, context) {
    if (request.directive.header.namespace === 'Alexa.Discovery' && request.directive.header.name === 'Discover') {
        log("DEGUG:", "Discover request",  JSON.stringify(request));
        handleDiscovery(request, context, "");
    }
    else if (request.directive.header.namespace === 'Alexa.PowerController') {
        if (request.directive.header.name === 'TurnOn' || request.directive.header.name === 'TurnOff') {
            log("DEBUG:", "TurnOn or TurnOff Request", JSON.stringify(request));
            handlePowerControl(request, context);
        }
    }

    function handleDiscovery(request, context) {
        var payload = {
            "endpoints":
            [
                {
                    "endpointId": "demo_id",
                    "manufacturerName": "Smart Device Company",
                    "friendlyName": "Bedroom Outlet",
                    "description": "Smart Device Switch",
                    "displayCategories": ["SWITCH"],
                    "cookie": {
                        "key1": "arbitrary key/value pairs for skill to reference this endpoint.",
                        "key2": "There can be multiple entries",
                        "key3": "but they should only be used for reference purposes.",
                        "key4": "This is not a suitable place to maintain current endpoint state."
                    },
                    "capabilities":
                    [
                        {
                          "type": "AlexaInterface",
                          "interface": "Alexa",
                          "version": "3"
                        },
                        {
                            "interface": "Alexa.PowerController",
                            "version": "3",
                            "type": "AlexaInterface",
                            "properties": {
                                "supported": [{
                                    "name": "powerState"
                                }],
                                 "retrievable": true
                            }
                        }
                    ]
                }
            ]
        };
        var header = request.directive.header;
        header.name = "Discover.Response";
        log("DEBUG", "Discovery Response: ", JSON.stringify({ header: header, payload: payload }));
        context.succeed({ event: { header: header, payload: payload } });
    }

    function log(message, message1, message2) {
        console.log(message + message1 + message2);
    }

    function handlePowerControl(request, context) {
        // get device ID passed in during discovery
        var requestMethod = request.directive.header.name;
        // get user token pass in request
        var requestToken = request.directive.payload.scope.token;
        var powerResult;

        if (requestMethod === "TurnOn") {

            // Make the call to your device cloud for control 
            // powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
            powerResult = "ON";
        }
       else if (requestMethod === "TurnOff") {
            // Make the call to your device cloud for control and check for success 
            // powerResult = stubControlFunctionToYourCloud(endpointId, token, request);
            powerResult = "OFF";
        }
        var contextResult = {
            "properties": [{
                "namespace": "Alexa.PowerController",
                "name": "powerState",
                "value": powerResult,
                "timeOfSample": "2017-09-03T16:20:50.52Z", //retrieve from result.
                "uncertaintyInMilliseconds": 50
            }]
        };
        var responseHeader = request.directive.header;
        responseHeader.name = "Alexa.Response";
        responseHeader.messageId = responseHeader.messageId + "-R";
        var response = {
            context: contextResult,
            event: {
                header: responseHeader
            },
            payload: {}

        };
        log("DEBUG", "Alexa.PowerController ", JSON.stringify(response));
        context.succeed(response);
    }
};

Finish configuring and test the Lambda function

  1. On the Configuration For Handler, for this example, leave the default name index.handler. A function handler is the main entry point for a Lambda function, and you specify it with the format fileName.entryPointFunctionName. For this example, the default file name is index and the handler function is the entry point in this code.
  2. For Role, select a role you previously created, or a role with Lambda basic execution policy attached.
  3. Leave the Advanced settings at the defaults and click Next.
  4. Click Create function. (Do not select Enable trigger unless your function implementation is complete. You can enable your event source later.)
  5. Copy the Amazon Resource Name (ARN) for your Lambda function, which is found in the upper right corner, into your clipboard. You will use this value when you configure the smart home skill in the developer portal. The ARN should be similar to the following: arn:aws:Lambda:us-east-1:012345678901:function:FunctionName.
  6. If you want to perform a quick test of the Discovery request in the Lambda code editor, you can click on Test and for the Sample event template, leave the default Hello World. Replace the entire contents in the test editor with the following code.
{
    "directive": {
        "header": {
            "namespace": "Alexa.Discovery",
            "name": "Discover",
            "payloadVersion": "3",
            "messageId": "1bd5d003-31b9-476f-ad03-71d471922820"
        },
        "payload": {
            "scope": {
                "type": "BearerToken",
                "token": "access-token-from-skill"
            }
        }
    }
}
  • Select Save and test. If successful, the Execution result should be similar to the following:
{
  "event": {
    "header": {
      "correlationToken": "12345692749237492",
      "messageId": "1bd5d003-31b9-476f-ad03-71d471922820",
      "name": "Discover.Response",
      "namespace": "Alexa.Discovery",
      "payloadVersion": "3"
    },
    "payload": {
      "endpoints": [
        {
          "endpointId": "demo_id",
          "manufacturerName": "Smart Device Company",
          "friendlyName": "Bedroom Outlet",
          "description": "Smart Device Switch",
          "displayCategories": ["SWITCH"],
          "cookie": {
            "key1": "arbitrary key/value pairs for skill to reference this endpoint.",
            "key2": "There can be multiple entries",
            "key3": "but they should only be used for reference purposes.",
            "key4": "This is not a suitable place to maintain current endpoint state."
          },
          "capabilities": [
            {
              "type": "AlexaInterface",
              "interface": "Alexa",
              "version": "3"
            },
            {
              "interface": "Alexa.PowerController",
              "version": "3",
              "type": "AlexaInterface",
              "properties": {
                "supported": [
                  {
                    "name": "powerState"
                  }
                ],
                "proactivelyReported": true,
                "retrievable": true
              }
            }
          ]
        }
      ]
    }
  }
}

Configure ARNs

You must provide the ARN for your Lambda function in the skill configuration in the developer portal.

  1. Navigate back to your skill in the Developer Portal. To do this, log in, and navigate to the Alexa section. Select your skill from the displayed list.
  2. Click past the Interaction model tab. The interaction model, which is what a user can say to invoke a smart home skill, is predefined and does not need to be specified. For details of the smart home voice interaction model, see the phrases listed in each interface topic.
  3. On the Configuration page, in the Default box of the Endpoint region, provide the ARN number from the Lambda function you created. You must provide geographic-specific endpoints. The following table lists mapping between the language you select for your skill, the regional endpoint and regions for your Lambda function.
Skill language Endpoint Region Lambda Function Region
English (US), English (Canada) North America US East (N. Virginia)
English (UK), German Europe EU (Ireland)
English (India) India EU (Ireland)
Japanese, English (Australia) Far East US West (Oregon)
  • If your skill only supports one language/region, provide the same ARN for the default ARN and the selected regional ARN.
  • If your skill supports multiple languages/regions, you must provide ARNs for each region. Provide one of the regional ARNs for the default.

The following image shows an example of this:

Provide Account Linking Information

You must provide account linking information from your OAuth 2.0 provider, which enables customers to associate their device cloud account with your smart home skill. You can use Login with Amazon or another OAuth provider for this section. You provide:

  • Authorization URL for your OAuth provider
  • Client Id and, client secret to identify and authenticate requests to the authorization server
  • A scope, if required by your OAuth provider

For more details and instructions about the required fields, see Authenticate-an Alexa User in Your System.

Test Your Skill

When your implementation is complete, and you’ve tested your Lambda function, you can functionally test your smart home skill. You will test your skill with an Alexa-enabled device or app. As a prerequisite you must have an account configured for your device cloud and discoverable devices for that account.

  1. In the developer portal, open your skill and on the Test tab, move the slider to Yes to show the skill in the Alexa app.
  2. Make sure you have a smart home trigger added and enabled. To check this, go to the Lambda console, select your smart home skill, and make sure you have an Alexa Smart Home trigger.
  3. Sign in to the Alexa app (available on Android, IOS or the web at https://alexa.amazon.com) with the same credentials as your developer account.
  4. Find your skill in the Alexa app. To do this, go to Skills, and tap Your Skills in the upper right corner of the All Skills page. Find your skill in the list of skills.
  5. Click the ENABLE button to enable the skill, and you will be directed to account-link the skill to a device cloud account. If you are unable to complete account linking, make sure you are using valid credentials for the device cloud. Otherwise, it is likely there is an issue with account-linking information you provided in the developer portal. For help with this, see Alexa: Debugging account linking in the developer forums. If you want to remove account linking later, you should disable your skill in the Skills tab.
  6. Close the window and tap the DISCOVER DEVICES button in the Alexa app.
  7. If the skill does not discover devices, check the logs for your Lambda function to see if it received a discover directive from Alexa, and use the logs to troubleshoot the issue. Common issues include incorrectly formatted event responses.
  8. If your skill successfully discovers devices, give Alexa commands using the device names found in the discovery process and utterances your skill supports. Make sure and test the skill with valid utterances and invalid ones, meaning ask your skill to do things that should work, and things that should not work, and in a variety of conditions, such as with a target device powered off.
  9. When you are satisfied with your smart home skill’s performance, you can, provide it for beta testing or submit it for certification.

Provide Publishing Information and Optionally Do Beta Testing

To provide your skill to customers for beta testing or submit your skill for certification, you must provide some publishing information that is used to describe your skill in the Alexa app.

  • On the Skill Information tab, you must specify a Language and Name.
  • On the Configuration tab, you must provide an endpoint (ARN) for your skill’s Lambda function.
  • Navigate to the Publishing Information page. The information requested on this page displays with your skill in the Alexa app. Provide all of the information such as a short and long description, and Example Phrases that you have successfully validated.
  • On the Privacy & Compliance tab, you must answer all of the questions questions. Provide a Privacy Policy URL and optionally provide a Terms of Use URL. For detailed instructions about how to complete these fields, see the Smart Home Skill Publishing Guide.

At this point, the Beta Test Your Skill button will be enabled, and you can complete information to start a beta test. For more information, see Skills Beta Testing.

Submit Your Skill for Certification

When you have completed all of the sections in the developer portal, and they show a green check mark, you can submit your skill for certification.

  1. Prior to submitting your skill, check that your testing instructions and other publishing information follows the guidelines in our Publishing Guide.
  2. At the bottom of the page, click Submit for Certification.

Submit Changes to a Live Skill

Once your skill is live, any changes to the skill must be certified. For example, your skill must be recertified as part of changing the information you provided about your skill in the developer portal or changing the AWS Lambda function. The certification review varies depending on the changes, and updating the Lambda function may trigger additional review.

When a skill status is changed to live, a new Development version is automatically created in the developer portal. This version has the same information as the original live version. You can use it to continue to work on your skill to improve it and add features.

The live and development versions are displayed together in the list of skills in the developer portal. If you expand the row, you can see both the development and live versions:

Published skill with row expanded
Published skill with row expanded

When you submit your updated skill to the developer portal, in the Testing Instructions field, add a change log that provides a detailed description of all changes.

To Update Your Lambda function

Do the following to update your AWS Lambda function:

  1. Create a new Lambda function with a new ARN, and copy your live Lambda function into the new Lambda function.

  2. Make your updates in the new Lambda function. Avoid updating the live Lambda function that supports your live skill, and avoid Lambda aliases or versioning because they do not work reliably once your skill is updated.

  3. In the development stage for your skill, update the Lambda ARN configuration to point to the new Lambda ARN.

After your skill is recertified and pushed live, your skill points to the new Lambda ARN. You can then deprecate the previous Lambda function or use the function for future development or updates.

Implement Asynchronous Responses and Proactive State Reporting

You are not required to implement state reporting and asynchronous responses, but it’s recommended. As a prerequisite to to completing this section, you must select the option to Provide geographical region endpoints? in the developer portal and provide a Lambda ARN for each region your skill is offered. This is required because you must store and use customer authentication from the Lambda function in the customer’s geographic region. Then complete the following steps:

Request permission

To request permission to send Alexa events to Alexa:

  1. Sign in to the developer portal and select your skill.
  2. In the Permissions section of the the configuration page, select Send Alexa Events.
  3. Note the clientId and clientSecret as you will need these to send messages to Alexa.

Add code for authentication

  1. Add code to handle the AcceptGrant directive, which is described in the Alexa.Authorization interface.
  2. Extract the authorization token from the AcceptGrant message. Use this along with the clientId and clientSecret from the developer portal to request an authentication and refresh token for each skill customer from Login with Amazon (LWA). For details on this flow, see Authenticating a Customer to Alexa
  3. Store the tokens in a secure place that is accessible in that region.

Add code to send messages to the Alexa event gateway.

Finally, format HTTP Post messages to the event gateway that contain the authentication token for the customer in the message headers as well as the relevant directive in the message body. Send messages to one of the following endpoints:

  • North America: https://api.amazonalexa.com/v3/events
  • Europe: https://api.eu.amazonalexa.com/v3/events
  • Far East: https://api.fe.amazonalexa.com/v3/events

Following is an example of how one of these messages might look. For more details, see Send Events to the Alexa Event Gateway.

POST /v3/events HTTP/1.1
Host: api-amazonalexa.com
Authorization: Bearer access-token-from-Amazon
Content-Type: application/json

{
  "context": {
    "properties": [
    ]
  },
  "event": {
    "header": {
      "messageId": "abc-123-def-456",
      "correlationToken": "abcdef-123456",
      "namespace": "Alexa",
      "name": "Response",
      "payloadVersion": "3"
    },
    "endpoint": {
      "scope": {
        "type": "BearerToken",
        "token": "access-token-from-Amazon"
       },
       "endpointId" :  "endpoint-id"
    },
    "payload": {
    }
  }
}