{"id":4755,"date":"2017-09-15T07:32:24","date_gmt":"2017-09-15T14:32:24","guid":{"rendered":"https:\/\/www.microsoft.com\/reallifecode\/?p=4755"},"modified":"2020-03-14T20:03:40","modified_gmt":"2020-03-15T03:03:40","slug":"using-microsoft-bot-framework-proxy-publish-bot-stack-different-supported-channels","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/ise\/using-microsoft-bot-framework-proxy-publish-bot-stack-different-supported-channels\/","title":{"rendered":"Using Microsoft Bot Framework as a Proxy to Publish your Bot Stack"},"content":{"rendered":"<p><em><span style=\"font-family: 'Calibri',sans-serif\">Image: <a href=\"https:\/\/pixabay.com\/en\/silver-jubilee-bridge-402943\/\">Silver Jubilee Bridge<\/a> by <a href=\"https:\/\/pixabay.com\/en\/users\/k_r_craft-355968\/\">k_r_craft<\/a>, used under\u00a0<a href=\"https:\/\/pixabay.com\/en\/service\/terms\/#usage\">CC0 Creative Commons<\/a><\/span><\/em><\/p>\n<h2>Background<\/h2>\n<p><a href=\"http:\/\/www.exceed.ai\">Exceed.ai<\/a> provides a platform for authoring and developing bots, focusing on brands\u2019 digital strategy by introducing AI into the sales funnel. They develop their own stack for managing bots&#8217; dialogs, state, and logic. The bots are hosted mainly on their customers&#8217; Facebook pages, and their customers can author their bots&#8217; dialogs using an administration dashboard. Exeed.ai wanted the ability to publish their bot dialogs over multiple channels, such as those that <a href=\"https:\/\/dev.botframework.com\/\">Microsoft Bot Framework<\/a> supports (Web, Skype, Slack, etc.), without having to rewrite their backend logic or dialogs from scratch, using the Bot Framework SDK.<\/p>\n<p>We collaborated with Exceed.ai to create a solution which uses their current content management system while providing the capability to expose dialogs across different channels using Bot Framework. The layout for our solution is based on the use of the\u00a0<a href=\"https:\/\/github.com\/CatalystCode\/bot-graph-dialog\">bot-graph-dialog<\/a>\u00a0extension developed as part of our\u00a0collaborations with <a href=\"https:\/\/www.microsoft.com\/developerblog\/2016\/11\/11\/extending-microsofts-bot-framework-with-graph-based-dialogs\">Pager<\/a> and <a href=\"https:\/\/www.microsoft.com\/developerblog\/2016\/12\/12\/integrating-an-existing-bot-platform-with-microsofts-bot-framework\">SMARK.io<\/a>.<\/p>\n<h2 id=\"the-solution\">The Solution<\/h2>\n<p>In our<a href=\"https:\/\/www.microsoft.com\/developerblog\/2016\/12\/12\/integrating-an-existing-bot-platform-with-microsofts-bot-framework\">\u00a0engagement with SMARK.io<\/a>, we converted the dialogs that they maintain on their backend to dialogs that were managed and run using the bot-graph-dialog extension.<!--more--><\/p>\n<p>In order to provide support for Exceed.ai&#8217;s existing content management system, we added a \u201cproxy mode\u201d to the bot-graph-dialog, so that every message sent to\/from the user is tunneled through the bot-graph-dialog extension to Exceed.ai&#8217;s backend service where it can be processed and continue\u00a0the flow.<\/p>\n<p>To implement this proxy feature, we created and extended a\u00a0<code><span style=\"font-size: 10.0pt\">Navigator<\/span><\/code> interface, responsible for navigating the conversation graph (steps in the conversation) to the <code><span style=\"font-size: 10.0pt\">GraphDialog<\/span><\/code> class that manages the conversation. The navigator implementation is responsible for calling their backend to get the next step and providing the previous step\u2019s results.<\/p>\n<p class=\"p1\">Essentially, the translation between the external backend (e.g., Exceed.ai) models and Microsoft Bot Framework models can be done in the backend or in the Navigator, depending on your business scenario and implementation.<\/p>\n<h2>The Code<\/h2>\n<p>The critical components of the solution code are outlined below.\u00a0Our\u00a0<a href=\"https:\/\/github.com\/CatalystCode\/bot-trees\/blob\/master\/exceed.js#L25\">full implementation of the Exceed.ai scenario<\/a>\u00a0can be found on GitHub.<\/p>\n<p>You can also follow the instructions in the <a href=\"https:\/\/github.com\/CatalystCode\/bot-trees\">bot-trees repository<\/a>\u00a0and use the <a href=\"https:\/\/github.com\/CatalystCode\/bot-trees\/blob\/master\/proxyMode.js\">proxyMode.js file<\/a>\u00a0to run a local implementation that does not depend on a remote API.<\/p>\n<h3>Implementing the Navigator Interface<\/h3>\n<pre class=\"lang:default decode:true\">\/\/ an implementation of the Navigator interface\r\n\/\/ which will act as the proxy for the backend API\r\nclass ProxyNavigator {\r\n\r\n  constructor() {\r\n    \/\/ backend root URL\r\n    this.apiUrl = \"https:\/\/&lt;backend api url&gt;\";\r\n  }\r\n\r\n  \/\/ returns the current node of the dialog\r\n  async getCurrentNode(session) {\r\n    var node = \/\/ TODO: Implement logic to resolve current step to process\r\n    return node;\r\n  };\r\n\r\n  \/\/ resolves the next node in the dialog\r\n  async getNextNode(session) {\r\n    console.log(`getNextNode, message: ${session.message}`);\r\n    var node = \/\/ TODO: Implement logic to resolve next step to process\r\n    return node;\r\n  }\r\n\r\n}<\/pre>\n<p>The node that is returned by these methods is an object with a similar schema to the nodes that the\u00a0<code>GraphDialog<\/code>\u00a0uses in its JSON files (see <a href=\"https:\/\/github.com\/CatalystCode\/bot-trees\/tree\/master\/bot\/scenarios\">example 1<\/a> and <a href=\"https:\/\/github.com\/CatalystCode\/bot-trees\/blob\/master\/proxyMode.js#L31\">example 2<\/a>).<\/p>\n<p>By extending the existing\u00a0<code>GraphDialog<\/code>\u00a0library with the &#8220;proxyMode&#8221; feature, we can leverage its translation logic, transforming its JSON-based nodes into the actual responses of the bot framework.<\/p>\n<p>When creating the <code>GraphDialog<\/code>\u00a0instance, inject the ProxyNavigator <code>implementation<\/code>\u00a0into its constructor:<\/p>\n<h3>Using The Proxy Navigator<\/h3>\n<pre class=\"lang:js decode:true\">var navigator = new ProxyNavigator();\r\nvar graphDialog = await GraphDialog.create({ bot, navigator, proxyMode: true });\r\nbot.dialog('\/', graphDialog.getDialog());\r\nconsole.log(`proxy graph dialog loaded successfully`);\r\n<\/pre>\n<p>Our bot is now up and ready for users&#8217; interactions.<\/p>\n<h2>Summary<\/h2>\n<p>With our solution, users can publish bot dialogs from any backend directly to Bot Framework channels, with custom <code><span style=\"font-size: 10.0pt\">Navigator<\/span><\/code> logic if needed. This approach can be used in any scenario where you want to develop your dialogs (both logic and state) using a different SDK than Microsoft Bot Framework, or even your own custom stack, but still want to use the functionality of Microsoft Bot Framework to publish those dialogs to different channels.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>With our solution, users can publish bot dialogs from any backend directly to MIcrosoft Bot Framework channels, with custom Navigator logic if needed. <\/p>\n","protected":false},"author":21349,"featured_media":10895,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[13,14],"tags":[107,249],"class_list":["post-4755","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-bots","category-cognitive-services","tag-bot","tag-microsoft-bot-framework-mbf"],"acf":[],"blog_post_summary":"<p>With our solution, users can publish bot dialogs from any backend directly to MIcrosoft Bot Framework channels, with custom Navigator logic if needed. <\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/4755","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/users\/21349"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/comments?post=4755"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/posts\/4755\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media\/10895"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/media?parent=4755"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/categories?post=4755"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/ise\/wp-json\/wp\/v2\/tags?post=4755"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}