Start building your own chatbot now >

More and more chatbots are being created every day, basically covering every automatable use case. Most of these chatbots are textual, we can discuss with them either on Messenger, SMS, website chat, etc. They’re very accessible and easy to use, but I’m sure you’d love to be able to speak to them as well as write to them. Sometimes, speaking is the most natural and easiest way to interact, say when you’re at home cooking or reading. I’ve got some news for you: you can build your own Alexa bot backed by Recast.AI! Why would you do that? Well, Recast.AI’s language technology allows you to build a skill in any language much faster than any other provider. It’s a great solution to become a master bot maker and pimp your home. 

A simple but very useful use case is the banking assistant. Wouldn’t it be marvellous if you could manage your daily finances directly by speaking with your banking assistant?

In this article, I’ll explain how you can create your own Alexa bot, powered by Recast.AI’s NLP, like you’ve seen above.

Deep dive

To begin, you’ll need your bank to have API endpoints to have a real integration but others use cases follow the same pattern.

Here is the global design of our project:alexa bot

  1. Login or create an account on the Amazon Developer console:
  2. Go to the “Alexa” tab and click on “Get started” under “Alexa skills”, then “Add a new skill”

Skill configuration

Now let’s configure each tab:

Skill information tab

Under the “Skill information” tab, fill in the information as shown below:

alexa bot

Interaction model tab

Now, the most important tab, the interaction model. Amazon doesn’t allow us to get the user’s input, so we have to use a little trick. We’ll configure a slot (an entity) matching all the user’s input.
To do this, enter this JSON configuration in the “Intent Schema” text area:

  "intents": [
      "slots": [
          "name": "sentence",
          "type": "AMAZON.LITERAL"
      "intent": "SaySomething"

In “Sample Utterance”, enter this example which matches the whole input:

SaySomething {do something | sentence} 

Configuration tab

Next, the “Configuration” tab. If you’ve mastered lambda, you can configure your lambda endpoint here directly, but to make things as generic as possible, we’ll use a simple https endpoint using ngrok.

To do so, install ngrok and create a tunnel (we’ll add the code server later) :

 ngrok http 3000

Enter the https url provided by ngrok in the “Default” input.

Leave other configurations with default values.

alexa bot

SSL certificate tab

An “SSL certificate” tab should have appeared. Select “My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority”. This way, we tell Amazon to let us (ngrok) manage the SSL certificate.

Test tab

Now we can test it by entering a sample utterance. We won’t get any response from our bot because we haven’t configured it, but we can see the JSON sent by Amazon to our bot. The whole sentence is in the slot “sentence”.

Publishing information and Privacy & Compliance tabs

You won’t need these details until you want to deploy your Alexa bot to the world.

Alexa configuration

If you have an Alexa device under the same account as your Amazon developer account, you can integrate your skill into Alexa.

alexa bot

alexa bot

Note: The following steps come from the Amazon help page:

To integrate your skill, go to the Alexa configuration page. This is the web versions of the mobile Alexa app. Once logged in, go to the Skills tab, and click on “Your skills” in the top right corner. You should see your newly created skill. Click on it and check that it’s enabled for your Alexa.

At this point, you should be able to ask Alexa to open your skill using your invocation name configured in the “Skill information” tab. For instance: “Alexa, open banking assistant.”. Alexa should understand the skill and reply with an error (“There was a problem with the requested skill response”). That’s normal, as we haven’t configured our bot yet, but it shows Alexa is now aware of the skill! Well done.

Alexa Bot configuration

First, create a bot on Recast.AI. If you haven’t used Recast.AI in the past, this tutorial will explain how to create a bot easily.

You can also fork a sample banking chatbot here.

Now that we have a trained bot, we have to code the integration between Alexa and Recast.AI. You can use this code, which is an adaptation of Recast.AI’s starter kit.

Once cloned, simply run this command:

REQUEST_TOKEN=xxxxxxxxxx node server.js.

This will start a server on port 3000, to which ngrok will send Alexa’s requests.

You should now be able to talk to Alexa, invoking your skill and talking with it, as defined in your Recast.AI Bot Builder.

Next steps

Congrats! You now have a talking Alexa chatbot, backed by Recast.AI’s NLP. You can now start customizing your use case and the code. It’s simple and well commented so it should be easy to work with.

When you’re ready for production or if you wish to have your bot always up, deploy it to a custom server or to a lambda, either using Bot Hosting or the Alexa integration in the “Configuration tab.”

Finally, to submit your skill and make it available to every Alexa owner, follow the instructions on the “Publishing Information” and “Privacy & Compliance” tabs.

That’s it, you know everything! Enjoy experimenting and feel free to come and discuss it on our Slack Community. Cheers! 

🤖 Happy bot building 🤖


Also published on Medium.

Want to build your own conversational bot? Get started with Recast.AI !

  • Anonymous

    According to Amazon official docs “AMAZON.LITERAL” is only supported for English (US) and not for any other languages.

    • Julien

      You’re right, this is a solution for developers who want to experiment and try in English. We are building a new solution which will be working for all Alexa languages.

      • Anonymous

        is the solution for other languages ​​ready ?

  • Ryan G

    Should the code be cloned to the root of my own git repository, or in a ‘my-bot’ sub-folder?

  • Anonymous


    When I say “alexa, ask recast”: it says “welcome, how can I help you?”
    When I say “Whats the balance on my account?”, then Im getting unauthorized 401 error. FYI, Im on SAP-Internet.

    { Error: Unauthorized
    at PromiseRequest.Request.callback (/Users/i302342/Documents/SAPGit/cool_sample_apps/RecastAI/my-bot/node_modules/superagent/lib/node/index.js:626:17)
    at /Users/i302342/Documents/SAPGit/cool_sample_apps/RecastAI/my-bot/node_modules/superagent/lib/node/index.js:795:18
    at IncomingMessage. (/Users/i302342/Documents/SAPGit/cool_sample_apps/RecastAI/my-bot/node_modules/superagent/lib/node/parsers/json.js:16:7)
    at IncomingMessage.emit (events.js:185:15)
    at endReadableNT (_stream_readable.js:1101:12)
    at process._tickCallback (internal/process/next_tick.js:114:19)
    original: null,
    Response {
    _events: {},
    _eventsCount: 0,
    _maxListeners: undefined,
    IncomingMessage {
    _readableState: [ReadableState],
    readable: false,
    _events: [Object],
    _eventsCount: 4,
    _maxListeners: undefined,
    socket: [TLSSocket],
    connection: [TLSSocket],
    httpVersionMajor: 1,
    httpVersionMinor: 1,
    httpVersion: ‘1.1’,
    complete: true,
    headers: [Object],
    rawHeaders: [Array],
    trailers: {},
    rawTrailers: [],
    upgrade: false,
    url: ”,
    method: null,
    statusCode: 401,
    statusMessage: ‘Unauthorized’,
    client: [TLSSocket],
    _consuming: true,
    _dumped: false,
    req: [ClientRequest],
    text: ‘{“results”:null,”message”:”Request can not be processed without authentication”}’,
    read: [Function],
    body: [Object] },
    Request {
    _events: [Object],
    _eventsCount: 1,
    _maxListeners: undefined,
    _agent: false,
    _formData: null,
    method: ‘POST’,
    url: ‘’,
    _header: [Object],
    header: [Object],
    writable: true,
    _redirects: 0,
    _maxRedirects: 5,
    cookies: ”,
    qs: {},
    qsRaw: [],
    _redirectList: [],
    _streamRequest: false,
    _data: [Object],
    req: [ClientRequest],
    protocol: ‘https:’,
    host: ‘’,
    _callback: [Function],
    res: [IncomingMessage],
    _timeout: 0,
    response: [Circular],
    called: true },
    ClientRequest {
    _events: [Object],
    _eventsCount: 4,
    _maxListeners: undefined,
    output: [],
    outputEncodings: [],
    outputCallbacks: [],
    outputSize: 0,
    writable: true,
    _last: true,
    upgrading: false,
    chunkedEncoding: false,
    shouldKeepAlive: false,
    useChunkedEncodingByDefault: true,
    sendDate: false,
    _removedConnection: false,
    _removedContLen: false,
    _removedTE: false,
    _contentLength: 101,
    _hasBody: true,
    _trailer: ”,
    finished: true,
    _headerSent: true,
    socket: [TLSSocket],
    connection: [TLSSocket],
    _header: ‘POST /v2/converse HTTP/1.1\r\nHost:\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: node-superagent/2.3.0\r\nAuthorization: Token xxxxxxxxxx\r\nContent-Type: application/json\r\nContent-Length: 101\r\nConnection: close\r\n\r\n’,
    _onPendingData: [Function: noopPendingOutput],
    agent: [Agent],
    socketPath: undefined,
    timeout: undefined,
    method: ‘POST’,
    path: ‘/v2/converse’,
    _ended: true,
    res: [IncomingMessage],
    aborted: undefined,
    timeoutCb: null,
    upgradeOrConnect: false,
    parser: null,
    maxHeadersCount: null,
    [Symbol(isCorked)]: false,
    [Symbol(outHeadersKey)]: [Object] },
    links: {},
    text: ‘{“results”:null,”message”:”Request can not be processed without authentication”}’,
    { results: null,
    message: ‘Request can not be processed without authentication’ },
    files: undefined,
    buffered: true,
    { date: ‘Mon, 02 Apr 2018 06:52:56 GMT’,
    ‘content-type’: ‘application/json; charset=utf-8’,
    ‘transfer-encoding’: ‘chunked’,
    connection: ‘close’,
    server: ‘nginx’,
    ‘x-ratelimit-limit-second’: ‘6’,
    ‘x-ratelimit-remaining-second’: ‘5’,
    status: ‘401 Unauthorized’,
    ‘cache-control’: ‘no-cache’,
    vary: ‘Origin’,
    ‘x-request-id’: ‘8c4aae7f-da32-449d-aaf2-65126d14fb15’,
    ‘x-runtime’: ‘0.001197’,
    ‘x-kong-upstream-latency’: ‘5’,
    ‘x-kong-proxy-latency’: ‘0’,
    via: ‘kong/0.10.3’ },
    { date: ‘Mon, 02 Apr 2018 06:52:56 GMT’,
    ‘content-type’: ‘application/json; charset=utf-8’,
    ‘transfer-encoding’: ‘chunked’,
    connection: ‘close’,
    server: ‘nginx’,
    ‘x-ratelimit-limit-second’: ‘6’,
    ‘x-ratelimit-remaining-second’: ‘5’,
    status: ‘401 Unauthorized’,
    ‘cache-control’: ‘no-cache’,
    vary: ‘Origin’,
    ‘x-request-id’: ‘8c4aae7f-da32-449d-aaf2-65126d14fb15’,
    ‘x-runtime’: ‘0.001197’,
    ‘x-kong-upstream-latency’: ‘5’,
    ‘x-kong-proxy-latency’: ‘0’,
    via: ‘kong/0.10.3’ },
    statusCode: 401,
    status: 401,
    statusType: 4,
    info: false,
    ok: false,
    redirect: false,
    clientError: true,
    serverError: false,
    { Error: cannot POST /v2/converse (401)
    at Response.toError (/Users/i302342/Documents/SAPGit/cool_sample_apps/RecastAI/my-bot/node_modules/superagent/lib/node/response.js:106:13)
    at Response._setStatusProperties (/Users/i302342/Documents/SAPGit/cool_sample_apps/RecastAI/my-bot/node_modules/superagent/lib/node/response.js:183:12)
    at new Response (/Users/i302342/Documents/SAPGit/cool_sample_apps/RecastAI/my-bot/node_modules/superagent/lib/node/response.js:42:8)
    at PromiseRequest.Request._emitResponse (/Users/i302342/Documents/SAPGit/cool_sample_apps/RecastAI/my-bot/node_modules/superagent/lib/node/index.js:659:20)
    at /Users/i302342/Documents/SAPGit/cool_sample_apps/RecastAI/my-bot/node_modules/superagent/lib/node/index.js:795:38
    at IncomingMessage. (/Users/i302342/Documents/SAPGit/cool_sample_apps/RecastAI/my-bot/node_modules/superagent/lib/node/parsers/json.js:16:7)
    at IncomingMessage.emit (events.js:185:15)
    at endReadableNT (_stream_readable.js:1101:12)
    at process._tickCallback (internal/process/next_tick.js:114:19)
    status: 401,
    text: ‘{“results”:null,”message”:”Request can not be processed without authentication”}’,
    method: ‘POST’,
    path: ‘/v2/converse’ },
    accepted: false,
    noContent: false,
    badRequest: false,
    unauthorized: true,
    notAcceptable: false,
    forbidden: false,
    notFound: false,
    charset: ‘utf-8’,
    type: ‘application/json’,
    setEncoding: [Function: bound ],
    redirects: [] },
    status: 401 }

  • Anonymous

    Is there an alternative to using ngrok? I am working with a student that only has access to a Chromebook or a windows machine without Admin access. Is it possible to use a cloud service like cloud9 instead of hosting off a local machine?

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies

Please confirm that you accept cookies to monitor the performance of our website