Search code examples
azurebotframework

Lost ability to capture unique Conversation_ID for each new session


Using Bot Builder 4.11.1 .Net and seemed to have lost the ability to capture any unique identifier for each new session. I need a unique identifier to keep state with the AI engine I am using to respond to input. Any suggestions? So, to expand, if I have a slack bot, for example, each time a user logs into Slack and starts a conversation with MyBot, I need a new unique identifier.

protected override async Task OnMembersAddedAsync(IList<ChannelAccount> membersAdded, ITurnContext<IConversationUpdateActivity> turnContext, CancellationToken cancellationToken)
        {
            var welcomeText = "Hello and welcome!";
            Random rnd1 = new Random();
            foreach (var member in membersAdded)
            {
                if (member.Id != turnContext.Activity.Recipient.Id)
                {
                    await turnContext.SendActivityAsync(MessageFactory.Text(welcomeText, welcomeText), cancellationToken);
                }
                
            }
        }
    }      

Solution

  • Unless I'm missing something, you should be able to get the information you need from TurnContext. In my code I'm running this in onMessage only (as in my case I only will message the user if they have sent the bot a message), but I don't see why you couldn't use this in onMembersAdded as well. I don't know how channels like Slack work, but in Microsoft Teams the user is just "added" when they first talk to the bot, and you don't end up in onMembersAdded unless they remove and read the bot in Teams. So if you may want to grab the conversation reference in the future, you may want to have it in onMessage or in both places. Also if you need the activity ID for some reason, as this will obviously update with each activity (though I haven't had any need for this information). Here is how you get the conversation reference. I am storing this in my conversation state and have assumed you are familiar with that but let me know if you need further help there. I also store in an Azure table to be accessed outside of the bot (e.g. I have an Azure Function that uses this to send proactive followups).

    const { TurnContext } = require('botbuilder');
    
    const conversationData = await this.dialogState.get(context, {});
    conversationData.conversationReference = TurnContext.getConversationReference(context.activity);
    await this.conversationState.saveChanges(context);
    

    And that's it! Here is a sample conversation reference. Note that if you are storing this in Azure Tables or similar, you'll likely need to stringify it and re-parse when you pull it out.

    {
        "activityId":"ACTIVITY_ID",
        "user": {
            "id":"USER_ID",
            "name":"USER_NAME",
            "aadObjectId":"AAD_OBJECT_ID",
            "role":"user"
        },
        "bot": {
            "id":"BOT_ID",
            "name":"BOT_NAME"
        },
        "conversation": { 
            "conversationType":"personal",
            "tenantId":"YOUR_TENANT_ID",
            "id":"YOUR_CONVERSATION_ID"
        },
        "channelId":"msteams",
        "locale":"en-US",
        "serviceUrl":"https://smba.trafficmanager.net/amer/"
    }
    

    What you are looking for (I think) is conversationReference.conversation.id. Different channels are going to have different attributes in the conversation reference, but this ID should always be there.