Skip to content

· 9 min

Build an Alexa skill for your own project on AWS

How to put a voice front end on a project you already run: the three parts of a custom skill, the two ways to host it on AWS, the commands that build and test it, and why the skill should stay a thin adapter over your own API.

By Effective Networks TeamAWSHow-toDeveloper education

"Alexa, ask the lab how the build is doing." Most projects already have the answer to that question sitting in an API, a database or a log file. What they lack is a way to ask for it without opening a laptop.

This post walks through putting a voice front end on a project you already run. It covers the three parts of a custom skill, the two ways to host it on AWS, and the commands that build and test it. It ends with the one design rule that stops the skill becoming a second copy of your project.

Why it matters

A skill is the smallest user interface your project will ever have. There is no screen to hide behind: the skill either answers the question in one sentence or it fails. Building one is a fast way to find out whether your project's API can answer the questions people ask of it, which is useful whether or not anyone ever talks to it.

It is also a cheap second interface. A status check, a sensor reading, a "start the overnight job" command: each is an afternoon of work once the first skill exists, and each works hands-free in a workshop, a kitchen or a lab.

The skill is an adapter, not an application. Every line of logic you put into the skill is a line you cannot reach from the web page, the command line or the next assistant platform. Put the logic in your project's API and let the skill translate.

A custom skill is three things

Strip away the console and a custom skill is three artefacts:

  1. An interaction model. A JSON document with an invocation name ("the lab"), a set of intents (the things a user can ask for), the sample utterances that map to each intent, and slots for the variable parts ("how is the nightly build" has a slot for the build name). Amazon's built-in intents cover help, cancel, stop and the fallback for anything the model does not recognise.
  2. An endpoint. The code Alexa calls with a request and expects a response from. It is almost always an AWS Lambda function, though an HTTPS endpoint you run yourself is allowed.
  3. A skill manifest. Name, description, the locales it supports, the endpoint's address and the permissions it asks for.

The Alexa Skills Kit (ASK) gives you a console that edits all three, a command line interface (CLI) that keeps them in a git repository, and software development kits (SDKs) for Node.js, Python and Java. The SDKs handle the request and response format, so a handler is a few lines.

The interaction model for a status skill is short:

{
  "interactionModel": {
    "languageModel": {
      "invocationName": "the lab",
      "intents": [
        { "name": "AMAZON.HelpIntent", "samples": [] },
        { "name": "AMAZON.CancelIntent", "samples": [] },
        { "name": "AMAZON.StopIntent", "samples": [] },
        { "name": "AMAZON.FallbackIntent", "samples": [] },
        {
          "name": "BuildStatusIntent",
          "slots": [{ "name": "pipeline", "type": "PIPELINE" }],
          "samples": [
            "how is the {pipeline} build",
            "how is the build doing",
            "did the {pipeline} build pass"
          ]
        }
      ],
      "types": [
        { "name": "PIPELINE", "values": [{ "name": { "value": "nightly" } }, { "name": { "value": "release" } }] }
      ]
    }
  }
}
Developers working at a row of desks with multiple monitors
The skill is three JSON documents and a handler. Everything it knows comes from the API you already run.

Pick the hosting route before you write a line

AWS gives you two ways to host the endpoint, and the choice decides how much of the work is yours.

Alexa-hosted skills are the fast route. Amazon provisions the AWS resources for you: a Lambda endpoint in each of the three Alexa service regions (Ireland, Northern Virginia and Oregon), a Simple Storage Service (S3) bucket for media and a DynamoDB table for state, with no AWS account of your own.

You edit the code in the console or through the command line and deploy with one command. The limits are real: custom skills only, a runtime you cannot change once chosen, encryption keys you do not control, and a usage allowance beyond which you provision resources in your own account anyway.

The runtime list also lags behind what Lambda offers, so check it before you commit to a language version.

Your own Lambda is the route for a project that already lives in your AWS account. The function can be in any Lambda region; Amazon recommends Ireland for European locales so the round trip is short, and the same region as your project's other resources if they are elsewhere. You add an Alexa Skills Kit trigger to the function, turn on skill ID verification so only your skill can invoke it, and give the function a role that can reach your project's API and nothing else. The Lambda free tier covers a million requests a month, so a personal skill costs nothing to run.

Our rule: if the project already has an AWS account and an API, use your own Lambda in the project's region. If you want a skill working tonight and the project is a hobby, start Alexa-hosted and move the endpoint later. Changing the endpoint is a setting in the manifest, not a rewrite, which is one more reason to keep the skill thin.

Wire it up from the command line

The console works, but the command line puts the three artefacts in a repository where you can review and version them. The ASK CLI needs Node.js, git, an Amazon developer account and, for the own-Lambda route, AWS credentials.

npm install -g ask-cli
ask configure            # names a profile, picks an AWS profile, signs you in through the browser
ask new                  # choose the language, the interaction model stack, and the hosting route
cd your-skill
ask deploy               # builds the model, uploads the manifest, deploys the code, enables testing
ask dialog               # a text conversation with the deployed skill, no device needed

ask new asks for a modelling stack and a deployment method. For a project of your own, pick the interaction model stack and either Alexa-hosted or AWS Lambda; the CloudFormation option is there when the skill needs other AWS resources created alongside it. The generated project has a skill-package/ folder for the manifest and interaction models, a lambda/ folder for the handler and an ask-resources.json that records the deployment choice.

While you are iterating on the handler, ask run starts a local debugging session and ask dialog can talk to it, so you can set breakpoints in the handler without deploying each change.

Write the handler as a translator

The handler's whole job is to turn an intent into a request to your project's API and the response into one spoken sentence. With the Node.js SDK that is one request handler per intent:

const Alexa = require("ask-sdk-core");

const BuildStatusHandler = {
  canHandle(input) {
    return Alexa.getRequestType(input.requestEnvelope) === "IntentRequest"
      && Alexa.getIntentName(input.requestEnvelope) === "BuildStatusIntent";
  },
  async handle(input) {
    const pipeline = Alexa.getSlotValue(input.requestEnvelope, "pipeline") || "nightly";
    const res = await fetch(`${process.env.PROJECT_API}/builds/${pipeline}/latest`, {
      headers: { Authorization: `Bearer ${process.env.PROJECT_TOKEN}` },
    });
    if (!res.ok) {
      return input.responseBuilder.speak("I could not reach the build server.").getResponse();
    }
    const build = await res.json();
    const speech = `The ${pipeline} build ${build.passed ? "passed" : "failed"} ${build.ago}.`;
    return input.responseBuilder.speak(speech).getResponse();
  },
};

exports.handler = Alexa.SkillBuilders.custom()
  .addRequestHandlers(BuildStatusHandler /* , LaunchRequestHandler, HelpHandler, ... */)
  .lambda();

Three things about that handler matter more than the code.

Answer in under eight seconds. Alexa gives your endpoint eight seconds before it gives up, and a user starts to wonder after two. If your project's API is slow, have the skill read a cached value your project writes on a schedule, rather than computing the answer on demand.

Write the sentence for the ear. A JSON payload with six fields becomes one sentence with one number in it. "The nightly build passed forty minutes ago" is a good answer. A list of commit hashes is not. If a question needs a table, it is a web page question and the skill should say so.

Give the API an endpoint for the skill. The /builds/{pipeline}/latest route in the example is small, read-only and shaped for a sentence. Adding it to your project is usually the most useful hour of the whole build, because it forces you to decide what the one-line answer to "how is the build" is.

Lock it down like any other client

A skill is a client of your project with an API token, and it deserves the same care as any other.

  • Turn on skill ID verification on the Lambda trigger, so a request from any other skill is rejected before your code runs. Amazon documents the trigger and the skill ID check; you can disable it while testing and should re-enable it before anyone else uses the skill.
  • Give the skill its own token in your project, with read-only scope and a name you will recognise in the logs. Never hand it the admin credentials.
  • Keep the token in a Lambda environment variable or in Secrets Manager, not in the repository the ASK CLI commits to.
  • Add account linking only when more than one person will use the skill. It wires an OAuth 2.0 flow between the Alexa app and your project so each user's requests carry their own token. For a skill that only you use, on devices on your own Amazon account, a single server-side token is enough and the account linking screens are a day you do not need to spend.

You also do not need certification. A skill in development is available on every Alexa device signed in to the developer account that owns it, and the console's beta test feature lets you invite a few other people without submitting it to the store. Submit for certification only when strangers need to find it.

For the sceptic: is Alexa worth building for now?

A fair question, because the platform is changing under developers. Amazon's generative assistant, Alexa+, arrived with three new integration kits for API-backed actions, website tasks and third-party agents, all of them in early access by application. The same announcement says customers on the original Alexa keep access to existing skills, that developers can keep refining and publishing skills for it, and that a skill wanting direct invocation on Alexa+ is evaluated on request. Meanwhile the deprecated features list has grown through 2026: the Routines Kit, the skill quality score in the console and the automotive skill kit have all been retired.

Read that two ways. The custom skill model still works and is still the documented way to build for your own devices today. And anything you build on it should expect the surface to move, which is the strongest argument for the rule above: the skill is a translator, the API is the product. If the skill model changes, you rewrite a handler and an interaction model. The API you added, and the one-line answers you decided on, carry over to whatever replaces it, including a chat interface, a dashboard widget or an agent that calls your API directly.

If your project's whole value is in a voice interface, the uncertainty is a real cost and you should price it in. If voice is one more way to reach a project that stands on its own, it is an evening's work with a long tail of small wins.

Getting started: the first evening in seven steps

  1. Write the five questions you most often ask your project out loud, and the one-sentence answer to each. If you cannot write the sentence, the API is not ready for a skill yet.
  2. Add a read-only endpoint to your project for each sentence, returning the two or three fields the sentence needs.
  3. Install the ASK CLI, run ask configure, and ask new with the interaction model stack and the hosting route you chose above.
  4. Write the interaction model: one intent per question, three to five sample utterances each, a slot only where the question has a variable part.
  5. Write the handlers as translators. Keep the token in an environment variable. Return one sentence.
  6. Deploy, then test with ask dialog before you go near a device. Ask the questions badly on purpose and check the fallback intent answers sensibly.
  7. Turn on skill ID verification, enable the skill on your own account, and ask the device the five questions from step 1. Note which answers needed a follow-up question: those are the next intents.

Resources to keep open while you build

The takeaway: the skill tests your API, not your voice

Every answer the skill gives is only as good as the one-line answer your API can give. The handler, the interaction model and the hosting route are an evening of work. Deciding what "how is the build" should say, and giving the project an endpoint that says it, is the part that lasts, and it improves every other interface your project has.

Which question about your own project would you most like to ask out loud?

Documenting a build like this for your own developers? Our developer education work turns one engineer's working notes into the tutorial the next one can follow.

All insights

More from Effective Networks

Laptops and notebooks on a shared table, seen from above
Community

A practical measurement model for developer community programmes: four metric families, how to define them, and how to report them without overclaiming.

A darkened conference audience lit by the stage

Let’s map your network.

Thirty minutes. We look at your product, your current developer motion, and where adoption is leaking. You leave with a point of view either way.