{"id":461,"date":"2019-05-31T14:38:22","date_gmt":"2019-05-31T12:38:22","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=461"},"modified":"2021-03-29T17:30:16","modified_gmt":"2021-03-29T15:30:16","slug":"amazon-alexa-anatomia-di-una-skill","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/","title":{"rendered":"Amazon Alexa: Anatomy of a Skill"},"content":{"rendered":"

How many of you have an Alexa-enabled device<\/strong> or a voice assistant?<\/p>\n

These devices create a way of interacting with services and applications that are completely different from what we are used to.<\/p>\n

Through Alexa<\/strong>, Amazon has become one of the main players in a real revolution of user experience.<\/p>\n

In this article, we will explain in detail how an Alexa Skills works<\/strong>. We will also provide you with an interaction model<\/strong> plus the code snippet<\/strong> for creating a minimal back-end.<\/p>\n

Definitions are important. Before going further, we will introduce the terms and concepts that we are going to use throughout the following paragraphs of\u00a0this article.<\/p>\n

What is Alexa?<\/h2>\n

Alexa is Amazon’s cloud-based voice assistant<\/strong> that enables\u00a0the functioning of the Amazon Echo.<\/strong>\u00a0 In addition to Amazon Echo, it is possible to find a wide range of devices that support Alexa. You can also build new ones using AVS<\/a> (Alexa Voice Service: the kit and the APIs offered by Amazon).<\/p>\n

Alexa Skills<\/h2>\n

Alexa Skills are the “skills” or the applications that enhance its capacity.<\/strong> Everything that Alexa does is implemented in the Skills. Alexa has specific predefined abilities available in all supported languages, such as the clock, lists, timers, and reminders. All the others, however, are developed by third parties and collected in a catalog that is similar to an app store. To activate a third-party skill, search the Alexa app catalog and enable it for your own devices. Alternatively, activate a skill only through voice. For example, this can be done by asking Amazon Echo to start it.<\/p>\n

The anatomy of a skill<\/h2>\n

Essentially, a skill is composed of two parts:<\/p>\n

    \n
  1. An interaction model<\/strong><\/li>\n
  2. A back-end API<\/strong><\/li>\n<\/ol>\n

    The interaction model consists of a json file that models all intents,<\/strong> i.e., the type of actions made possible for users in which the skill can manage. You will need to define the parameters for each inquiry, including their type and the phrases that Alexa needs for requesting them. The model also contains many example sentences for each intent (utterances)<\/strong> and phrases that will be used by the AI in recognizing user requests through its own skill.<\/p>\n

    The skill’s back-end is a web service. <\/strong><\/p>\n

    It can be hosted on AWS Lambda.<\/strong>\u00a0This enables easy authentication of Alexa and has a rather attractive pricing model.<\/p>\n

    Alternatively, it can be hosted on any service. This means it can expose a public endpoint accessible through https.<\/p>\n

    Regardless of the hosting choice, the back-end must be accessible for Alexa calls. It needs to reply within a few seconds with a message containing instructions for Alexa, e.g. the synthesized user text and\/or another instruction (IoT commands, data to be shown on any display, etc.).<\/p>\n

    We will go further into how the back-end functions in a few paragraphs.<\/p>\n

    \"alexa_schema\"<\/p>\n

    Here is how a high-level skill interaction works:<\/p>\n

    When the user speaks to an Echo device, it records the audio and sends it to Alexa via AVS.<\/strong>\u00a0 At this point, Alexa will be able to identify and address the skill in one of the following ways:<\/p>\n

      \n
    1. The request explicitly contains the name of the desired skill, e.g. “Alexa ask [name of skill] about …” or similar forms.<\/li>\n
    2. The user has already enabled a skill that can satisfy the expressed intent. In this case, Alexa will select this skill.<\/li>\n
    3. If the user has not enabled any skills capable of satisfying the request, then the default intent skill will be chosen (selected by Amazon).<\/li>\n<\/ol>\n

      Once the user’s intended skill has been identified, then the programmer-developed interaction model comes into play.<\/p>\n

      Alexa uses the sample sentences and intent definition parameters to understand what the user wants. If the request fails to contain all the necessary parameters, then the user will be interrogated until all information is provided.<\/p>\n

      Once the first phase of the interaction is complete, Alexa contacts the application back-end via a POST. It provides all the details and waits for the output to be communicated to the user.<\/p>\n

      For complicated skills, it is possible to keep the rules and the logic for retrieving the parameters in the back-end. This enables them to be modified according to what was acquired up to that point.<\/p>\n

      Alexa’s functions include maintaining session data.<\/strong> This makes maintaining the status of a conversation possible by inserting and modifying variables in a specific section of the message returned by the back-end. This information will be sent by Alexa to subsequent calls in the back-end until the user concludes the interaction with the skill.<\/p>\n

      You can then create complex skills that “remember” the user’s previous answers or requests. This makes for a realistic\u00a0conversation.<\/strong><\/p>\n

      A trivial skill<\/h2>\n

      So far, we have not gone into too much detail when talking about the interaction model and the back-end.<\/p>\n

      So here is an example:<\/p>\n

      {\r\n    \"interactionModel\": {\r\n        \"languageModel\": {\r\n            \"invocationName\": \"saluti\",\r\n            \"intents\": [\r\n                {\r\n                    \"name\": \"AMAZON.CancelIntent\",\r\n                    \"samples\": [\r\n                        \"no\",\r\n                        \"niente\",\r\n                        \"non fa niente\",\r\n                        \"lascia perdere\",\r\n                        \"annulla\"\r\n                    ]\r\n                },\r\n                {\r\n                    \"name\": \"AMAZON.HelpIntent\",\r\n                    \"samples\": []\r\n                },\r\n                {\r\n                    \"name\": \"AMAZON.StopIntent\",\r\n                    \"samples\": [\r\n                        \"abbandona\",\r\n                        \"esci\",\r\n                        \"fine\",\r\n                        \"stop\"\r\n                    ]\r\n                },\r\n                {\r\n                    \"name\": \"Salutare\",\r\n                    \"slots\": [],\r\n                    \"samples\": [\r\n                        \"salutarmi\",\r\n                        \"salutami\",\r\n                        \"saluti\",\r\n                        \"ciao\"\r\n                    ]\r\n                }\r\n            ],\r\n            \"types\": []\r\n        }\r\n    }\r\n}\r\n<\/pre>\n

      This model defines a single intent with the “Greeting”\u00a0 identification, plus the standard Amazon intent of “cancel”, “stop”, and “help”. No parameters are required. Rather, a few sample phrases are provided.<\/p>\n

      It is a working model<\/strong> in its simplicity. Additionally, it fulfills the purpose of being greeted by Alexa.<\/p>\n

      The back-end, meaning the service that is able to respond to the requests that Alexa performs once the intent has been identified is, however, missing.<\/p>\n

      Here is a snippet to correctly answer calls related to the intent defined above, assuming the use of AWS Lambda.<\/p>\n

      It involves a Nodejs function,<\/strong> whose code uses the Alexa SDK for each node. In red, we have highlighted in red the function that is invoked for the “Greeting” intent.<\/p>\n

      The rest of the code is essentially a boilerplate. It remains almost completely unaltered, even for more complex skills.<\/p>\n

      let speechOutput;\r\nlet reprompt;\r\nlet welcomeOutput = \"Benvenuto in 'Ciao' in italiano. Puoi salutarmi per essere salutato a tua volta\";\r\nlet welcomeReprompt = \"puoi solo dire 'ciao' per essere salutato\";\r\n\r\n\"use strict\";\r\nconst Alexa = require('alexa-sdk');\r\nconst APP_ID = undefined;\r\nspeechOutput = '';\r\nconst handlers = {\r\n'LaunchRequest': function() {\r\nthis.emit(':ask', welcomeOutput, welcomeReprompt);\r\n},\r\n'AMAZON.HelpIntent': function() {\r\nspeechOutput = 'Placeholder response for AMAZON.HelpIntent.';\r\nreprompt = '';\r\nthis.emit(':ask', speechOutput, reprompt);\r\n},\r\n'AMAZON.CancelIntent': function() {\r\nspeechOutput = 'Ok, annullato\u2019;\r\nthis.emit(':tell', speechOutput);\r\n},\r\n'AMAZON.StopIntent': function() {\r\nspeechOutput = 'Arrivederci';\r\nthis.emit(':tell', speechOutput);\r\n},\r\n'SessionEndedRequest': function() {\r\nspeechOutput = '';\r\nthis.emit(':tell', speechOutput);\r\n},\r\n'Salutare': function() {\r\nspeechOutput = '';\r\nspeechOutput = \"Ciao! Questo \u00e8 tutto quello che puoi fare per ora\u201d;\r\nthis.emit(\":tell\", speechOutput, speechOutput);\r\n},<\/span>\r\n'Unhandled': function() {\r\nspeechOutput = \"Non ho capito. Riprova\";\r\nthis.emit(':ask', speechOutput, speechOutput);\r\n}\r\n};\r\n\r\nexports.handler = (event, context) => {\r\nconst alexa = Alexa.handler(event, context);\r\nalexa.appId = APP_ID;\r\n\/\/ To enable string internationalization (i18n) features, set a resources object.\r\n\/\/alexa.resources = languageStrings;\r\nalexa.registerHandlers(handlers);\r\n\/\/alexa.dynamoDBTableName = 'DYNAMODB_TABLE_NAME'; \/\/uncomment this line to save attributes to DB\r\nalexa.execute();\r\n};\r\n\r\n\/\/ END of Intent Handlers {} ========================================================================================\r\n\/\/ 3. Helper Function =================================================================================================\r\n\r\nfunction resolveCanonical(slot) {\r\n\/\/this function looks at the entity resolution part of request and returns the slot value if a synonyms is provided\r\nlet canonical;\r\ntry {\r\ncanonical = slot.resolutions.resolutionsPerAuthority[0].values[0].value.name;\r\n}\r\ncatch (err) {\r\nconsole.log(err.message);\r\ncanonical = slot.value;\r\n};\r\nreturn canonical;\r\n};\r\n\r\nfunction delegateSlotCollection() {\r\nconsole.log(\"in delegateSlotCollection\");\r\nconsole.log(\"current dialogState: \" + this.event.request.dialogState);\r\nif (this.event.request.dialogState === \"STARTED\") {\r\nconsole.log(\"in Beginning\");\r\nlet updatedIntent = null;\r\n\/\/ updatedIntent=this.event.request.intent;\r\n\/\/optionally pre-fill slots: update the intent object with slot values for which\r\n\/\/you have defaults, then return Dialog.Delegate with this updated intent\r\n\/\/ in the updatedIntent property\r\n\/\/this.emit(\":delegate\", updatedIntent); \/\/uncomment this is using ASK SDK 1.0.9 or newer\r\n\r\n\/\/this code is necessary if using ASK SDK versions prior to 1.0.9 \r\nif (this.isOverridden()) {\r\nreturn;\r\n}\r\nthis.handler.response = buildSpeechletResponse({\r\nsessionAttributes: this.attributes,\r\ndirectives: getDialogDirectives('Dialog.Delegate', updatedIntent, null),\r\nshouldEndSession: false\r\n});\r\nthis.emit(':responseReady', updatedIntent);\r\n\r\n}\r\nelse if (this.event.request.dialogState !== \"COMPLETED\") {\r\nconsole.log(\"in not completed\");\r\n\/\/ return a Dialog.Delegate directive with no updatedIntent property.\r\n\/\/this.emit(\":delegate\"); \/\/uncomment this is using ASK SDK 1.0.9 or newer\r\n\r\n\/\/this code necessary is using ASK SDK versions prior to 1.0.9\r\nif (this.isOverridden()) {\r\nreturn;\r\n}\r\nthis.handler.response = buildSpeechletResponse({\r\nsessionAttributes: this.attributes,\r\ndirectives: getDialogDirectives('Dialog.Delegate', null, null),\r\nshouldEndSession: false\r\n});\r\nthis.emit(':responseReady');\r\n\r\n}\r\nelse {\r\nconsole.log(\"in completed\");\r\nconsole.log(\"returning: \" + JSON.stringify(this.event.request.intent));\r\n\/\/ Dialog is now complete and all required slots should be filled,\r\n\/\/ so call your normal intent handler.\r\nreturn this.event.request.intent;\r\n}\r\n}\r\n\r\n\r\nfunction randomPhrase(array) {\r\n\/\/ the argument is an array [] of words or phrases\r\nlet i = 0;\r\ni = Math.floor(Math.random() * array.length);\r\nreturn (array[i]);\r\n}\r\n\r\nfunction isSlotValid(request, slotName) {\r\nlet slot = request.intent.slots[slotName];\r\n\/\/console.log(\"request = \"+JSON.stringify(request)); \/\/uncomment if you want to see the request\r\nlet slotValue;\r\n\r\n\/\/if we have a slot, get the text and store it into speechOutput\r\nif (slot && slot.value) {\r\n\/\/we have a value in the slot\r\nslotValue = slot.value.toLowerCase();\r\nreturn slotValue;\r\n}\r\nelse {\r\n\/\/we didn't get a value in the slot.\r\nreturn false;\r\n}\r\n}\r\n\r\n\/\/These functions are here to allow dialog directives to work with SDK versions prior to 1.0.9\r\n\/\/will be removed once Lambda templates are updated with the latest SDK\r\n\r\nfunction createSpeechObject(optionsParam) {\r\nif (optionsParam && optionsParam.type === 'SSML') {\r\nreturn {\r\ntype: optionsParam.type,\r\nssml: optionsParam['speech']\r\n};\r\n}\r\nelse {\r\nreturn {\r\ntype: optionsParam.type || 'PlainText',\r\ntext: optionsParam['speech'] || optionsParam\r\n};\r\n}\r\n}\r\n\r\nfunction buildSpeechletResponse(options) {\r\nlet alexaResponse = {\r\nshouldEndSession: options.shouldEndSession\r\n};\r\n\r\nif (options.output) {\r\nalexaResponse.outputSpeech = createSpeechObject(options.output);\r\n}\r\n\r\nif (options.reprompt) {\r\nalexaResponse.reprompt = {\r\noutputSpeech: createSpeechObject(options.reprompt)\r\n};\r\n}\r\n\r\nif (options.directives) {\r\nalexaResponse.directives = options.directives;\r\n}\r\n\r\nif (options.cardTitle && options.cardContent) {\r\nalexaResponse.card = {\r\ntype: 'Simple',\r\ntitle: options.cardTitle,\r\ncontent: options.cardContent\r\n};\r\n\r\nif (options.cardImage && (options.cardImage.smallImageUrl || options.cardImage.largeImageUrl)) {\r\nalexaResponse.card.type = 'Standard';\r\nalexaResponse.card['image'] = {};\r\n\r\ndelete alexaResponse.card.content;\r\nalexaResponse.card.text = options.cardContent;\r\n\r\nif (options.cardImage.smallImageUrl) {\r\nalexaResponse.card.image['smallImageUrl'] = options.cardImage.smallImageUrl;\r\n}\r\n\r\nif (options.cardImage.largeImageUrl) {\r\nalexaResponse.card.image['largeImageUrl'] = options.cardImage.largeImageUrl;\r\n}\r\n}\r\n}\r\nelse if (options.cardType === 'LinkAccount') {\r\nalexaResponse.card = {\r\ntype: 'LinkAccount'\r\n};\r\n}\r\nelse if (options.cardType === 'AskForPermissionsConsent') {\r\nalexaResponse.card = {\r\ntype: 'AskForPermissionsConsent',\r\npermissions: options.permissions\r\n};\r\n}\r\n\r\nlet returnResult = {\r\nversion: '1.0',\r\nresponse: alexaResponse\r\n};\r\n\r\nif (options.sessionAttributes) {\r\nreturnResult.sessionAttributes = options.sessionAttributes;\r\n}\r\nreturn returnResult;\r\n}\r\n\r\nfunction getDialogDirectives(dialogType, updatedIntent, slotName) {\r\nlet directive = {\r\ntype: dialogType\r\n};\r\n\r\nif (dialogType === 'Dialog.ElicitSlot') {\r\ndirective.slotToElicit = slotName;\r\n}\r\nelse if (dialogType === 'Dialog.ConfirmSlot') {\r\ndirective.slotToConfirm = slotName;\r\n}\r\n\r\nif (updatedIntent) {\r\ndirective.updatedIntent = updatedIntent;\r\n}\r\nreturn [directive];\r\n}<\/pre>\n

      Here, we have covered the fundamental concepts underlying the Alexa functioning. We then analyzed the anatomy of a simple and functional skill,<\/strong> which is the first step in realizing more complex and potentially publishable skills.<\/p>\n

      However, for publication, there are compliance limitations and rules to be considered when designing a voice interface.<\/p>\n

      We will address this and many other important aspects of the publication and implementation phase throughout the following articles. But first, we will publish a detailed tutorial for the creation of a non-“trivial” skill.<\/p>\n

      We will not give you any hints \ud83d\ude42<\/p>\n

      Stay tuned!<\/p>\n

      Would you like to learn more about AWS Lambda or Serverless development?<\/strong><\/p>\n

      Then read our series of articles on these topics!<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"

      How many of you have an Alexa-enabled device or a voice assistant? These devices create a way of interacting with […]<\/p>\n","protected":false},"author":8,"featured_media":469,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[248],"tags":[340,342,264],"yoast_head":"\nAmazon Alexa: Anatomy of a Skill - Proud2beCloud Blog<\/title>\n<meta name=\"description\" content=\"In this article, Alexa Skills working principles and an interaction model with code snippet for a minimal back-end.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Amazon Alexa: Anatomy of a Skill\" \/>\n<meta property=\"og:description\" content=\"In this article, Alexa Skills working principles and an interaction model with code snippet for a minimal back-end.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/\" \/>\n<meta property=\"og:site_name\" content=\"Proud2beCloud Blog\" \/>\n<meta property=\"article:published_time\" content=\"2019-05-31T12:38:22+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-03-29T15:30:16+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2019\/05\/copertine-blog_Tavola-disegno-1-copia-2.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1668\" \/>\n\t<meta property=\"og:image:height\" content=\"1250\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Alessio Gandini\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Amazon Alexa: Anatomy of a Skill\" \/>\n<meta name=\"twitter:description\" content=\"In this article, Alexa Skills working principles and an interaction model with code snippet for a minimal back-end.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2019\/05\/copertine-blog_Tavola-disegno-1-copia-2.png\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alessio Gandini\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/\",\"url\":\"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/\",\"name\":\"Amazon Alexa: Anatomy of a Skill - Proud2beCloud Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.besharp.it\/#website\"},\"datePublished\":\"2019-05-31T12:38:22+00:00\",\"dateModified\":\"2021-03-29T15:30:16+00:00\",\"author\":{\"@id\":\"https:\/\/blog.besharp.it\/#\/schema\/person\/e7262d28e51528c2e420327f9b18cd43\"},\"description\":\"In this article, Alexa Skills working principles and an interaction model with code snippet for a minimal back-end.\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.besharp.it\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Amazon Alexa: Anatomy of a Skill\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.besharp.it\/#website\",\"url\":\"https:\/\/blog.besharp.it\/\",\"name\":\"Proud2beCloud Blog\",\"description\":\"il blog di beSharp\",\"alternateName\":\"Proud2beCloud Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.besharp.it\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.besharp.it\/#\/schema\/person\/e7262d28e51528c2e420327f9b18cd43\",\"name\":\"Alessio Gandini\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.besharp.it\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/eeb98518768d999bff24f8358b464fe2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/eeb98518768d999bff24f8358b464fe2?s=96&d=mm&r=g\",\"caption\":\"Alessio Gandini\"},\"description\":\"Cloud-native Development Line Manager @ beSharp, DevOps Engineer e AWS expert. Computer geek da quando avevo 6 anni, appassionato di informatica ed elettronica a tutto tondo. Ultimamente sto esplorando l'esperienza utente vocale e il mondo dell'IoT. Appassionato di cinema e grande consumatore di serie TV, videogiocatore della domenica.\",\"url\":\"https:\/\/blog.besharp.it\/author\/alessio-gandini\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Amazon Alexa: Anatomy of a Skill - Proud2beCloud Blog","description":"In this article, Alexa Skills working principles and an interaction model with code snippet for a minimal back-end.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/","og_locale":"en_US","og_type":"article","og_title":"Amazon Alexa: Anatomy of a Skill","og_description":"In this article, Alexa Skills working principles and an interaction model with code snippet for a minimal back-end.","og_url":"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/","og_site_name":"Proud2beCloud Blog","article_published_time":"2019-05-31T12:38:22+00:00","article_modified_time":"2021-03-29T15:30:16+00:00","og_image":[{"width":1668,"height":1250,"url":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2019\/05\/copertine-blog_Tavola-disegno-1-copia-2.png","type":"image\/png"}],"author":"Alessio Gandini","twitter_card":"summary_large_image","twitter_title":"Amazon Alexa: Anatomy of a Skill","twitter_description":"In this article, Alexa Skills working principles and an interaction model with code snippet for a minimal back-end.","twitter_image":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2019\/05\/copertine-blog_Tavola-disegno-1-copia-2.png","twitter_misc":{"Written by":"Alessio Gandini","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/","url":"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/","name":"Amazon Alexa: Anatomy of a Skill - Proud2beCloud Blog","isPartOf":{"@id":"https:\/\/blog.besharp.it\/#website"},"datePublished":"2019-05-31T12:38:22+00:00","dateModified":"2021-03-29T15:30:16+00:00","author":{"@id":"https:\/\/blog.besharp.it\/#\/schema\/person\/e7262d28e51528c2e420327f9b18cd43"},"description":"In this article, Alexa Skills working principles and an interaction model with code snippet for a minimal back-end.","breadcrumb":{"@id":"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.besharp.it\/amazon-alexa-anatomia-di-una-skill\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.besharp.it\/"},{"@type":"ListItem","position":2,"name":"Amazon Alexa: Anatomy of a Skill"}]},{"@type":"WebSite","@id":"https:\/\/blog.besharp.it\/#website","url":"https:\/\/blog.besharp.it\/","name":"Proud2beCloud Blog","description":"il blog di beSharp","alternateName":"Proud2beCloud Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.besharp.it\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.besharp.it\/#\/schema\/person\/e7262d28e51528c2e420327f9b18cd43","name":"Alessio Gandini","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.besharp.it\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/eeb98518768d999bff24f8358b464fe2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/eeb98518768d999bff24f8358b464fe2?s=96&d=mm&r=g","caption":"Alessio Gandini"},"description":"Cloud-native Development Line Manager @ beSharp, DevOps Engineer e AWS expert. Computer geek da quando avevo 6 anni, appassionato di informatica ed elettronica a tutto tondo. Ultimamente sto esplorando l'esperienza utente vocale e il mondo dell'IoT. Appassionato di cinema e grande consumatore di serie TV, videogiocatore della domenica.","url":"https:\/\/blog.besharp.it\/author\/alessio-gandini\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/posts\/461"}],"collection":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/comments?post=461"}],"version-history":[{"count":0,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/posts\/461\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/media\/469"}],"wp:attachment":[{"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/media?parent=461"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/categories?post=461"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.besharp.it\/wp-json\/wp\/v2\/tags?post=461"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}