title: Skill host generating new conversation IDs every turn, breaking waterfall dialogs
body: <p>I'm working on converting some existing bots to skills so that we can create a Skill Host bot that can call multiple &quot;child bots&quot;. I used the <a href="https://github.com/microsoft/BotBuilder-Samples/tree/main/samples/javascript_nodejs/80.skills-simple-bot-to-bot" rel="nofollow noreferrer">skills-simple-bot-to-bot</a> sample, and it kind of works. I can call the skill bot from the host and it works...for a single turn. But the host is creating a new conversation ID every turn, clearing the conversation state which makes my multi-turn waterfall dialogs not work. It is also causing any other values stored in conversation state to be cleared (e.g. I capture email address in conversation state so I don't have to reprompt it). The skill bot works fine when invoked directly (i.e. not through the skill host), so it's definitely something with the way the skill host works. I found <a href="https://github.com/microsoft/botbuilder-dotnet/issues/4374" rel="nofollow noreferrer">this issue</a> on GitHub which seems to be the same thing (that's for .NET but there are links to the other SDKs including js), though it seems to have been resolved years ago yet I'm still having the issue so I'm not sure it's the same.</p>
  <p>So in short, how do I set up the skill host so that it doesn't generate new conversation IDs every turn?</p>
  <p>Not sure this will help as it's almost exactly the same as the sample, but here's a snippet of the code where it appears conversation ID is being generated by the host. It seems maybe I need some way to NOT call <code>createSkillConversationIdWithOptions</code>, but if that's what is required I'm not sure what I need to do to generate the skillConversationId other than what is currently in the sample.</p>
  <pre class="lang-js prettyprint-override"><code>    async sendToSkill(context, targetSkill) {
          // NOTE: Always SaveChanges() before calling a skill so that any activity generated by the skill
          // will have access to current accurate state.
          await this.conversationState.saveChanges(context, true);
  
          // Create a conversationId to interact with the skill and send the activity
          const skillConversationId = await this.conversationIdFactory.createSkillConversationIdWithOptions({
              fromBotOAuthScope: context.turnState.get(context.adapter.OAuthScopeKey),
              fromBotId: this.botId,
              activity: context.activity,
              botFrameworkSkill: this.targetSkill
          });
  
          // route the activity to the skill
          const response = await this.skillClient.postActivity(this.botId, targetSkill.appId, targetSkill.skillEndpoint, this.skillsConfig.skillHostEndpoint, skillConversationId, context.activity);
  
          // Check response status
          if (!(response.status &gt;= 200 &amp;&amp; response.status &lt;= 299)) {
              throw new Error(`[RootBot]: Error invoking the skill id: &quot;${ targetSkill.id }&quot; at &quot;${ targetSkill.skillEndpoint }&quot; (status is ${ response.status }). \r\n ${ JSON.stringify(response.body) }`);
          }
      }
  </code></pre>