Blog Post

Modern Work App Consult Blog
2 MIN READ

Persist Bot Conversation States in Azure Cosmos DB with Bot Framework Composer V2.1.2

freistli's avatar
freistli
Icon for Microsoft rankMicrosoft
Nov 02, 2022


Large business scale often requires scaling Bot Framework App Instance from one to many. To make this work, the bot application needs to serialize memory info to storage, otherwise users may hit conversation state lost issues intermittently, for example, the next request doesn’t affinity on the same instance and then user feels bot doesn’t smartly follow previous conversation, or Skills Bot calling back with the same conversation ID but different instance, and root bot returns 404, etc. A typical root + skills bot infrastructure is like this:

 

 

 

To solve this problem in Bot Framework Composer, developers can configure Bot Framework Composer project setting. However after several updates in Bot Framework Composer, this part configuration guide becomes unclear and not up to date. Therefore, based on practical experience and code understanding on Bot Framework Composer microsoft/BotFramework-Composer, I have compiled the configuration considerations for this part, hoping to help developers and projects that encounter similar situations.

 

  1. Create Cosmos DB Azure Resource firstly.
  1. Open Bot Composer. Click Configuration, and choose the default bot, please choose the root bot if there are skills bots in the same project
  1. Choose Advanced Settings View

 

  1. Inside the runtimeSettings section, add this "storage" setting, please use the same key word CosmosDbPartitionedStorage:

 

 

 

"runtimeSettings": {

……………….

    "storage": "CosmosDbPartitionedStorage",

    "telemetry": {

      "logActivities": true,

      "logPersonalInformation": false,

      "options": {

        "connectionString": ""

      }

    }

  },

 

 

 

  1. At the same level of runtimSettings (not the child node of runtimeSettings), add details for CosmosDbPartitionedStorage:

 

 

 


"runtimeSettings": {

…….

},

  "CosmosDbPartitionedStorage": {

    "authKey": "XXXXXXXXXXXXXXXXXXXXXXXXXXX",

    "cosmosDBEndpoint": https://XXXXXXXXXXXXXXX.documents.azure.com:443/,

    "databaseId": "botstate-db",

    "containerId": "botstate-container"

  },

  "skillConfiguration": {},

 

 

 

  1. Publish the bot project to Azure.

If everything works well, after several round chats with the root bot, you will find the Cosmos DB has similar data like this:

 

 

This means main/root bot persists the conversation data successfully on Cosmos DB, and correct information can be retrieved for multiple instances, or after instances reboot.

 

If you don’t want the conversation states store there long time, can choose the container Scale & Settings, to change its TTL:

 

 

Regarding the usage of CosmosDbPartitionedStorage, can be found from the previous discussion thread in Bot Composer issues:

 

https://github.com/microsoft/BotFramework-Composer/issues/8864#issuecomment-998963464

https://github.com/microsoft/BotFramework-Composer/issues/8864#issuecomment-1002832254

 

Happy Bot Framework Development!

Updated Nov 02, 2022
Version 5.0

2 Comments

  • Duncan-Hicksons's avatar
    Duncan-Hicksons
    Copper Contributor

    Ok worked this out:

      "runtimeSettings": {
    ...
    "storage": "BlobsStorage",
    ...
    }
    "blobsStorage": {
        "connectionString": "myString",
        "containerName": "myContainer"

    Whether you save to CosmosDb or Azure Blob Storage, this works great ... until you restart the bot, in which case it will crash the whole bot with stack overflow error. Since for me the use case was to persist data across restarts, that makes it unhelpful. Oh well. Nice idea.

  • Duncan-Hicksons's avatar
    Duncan-Hicksons
    Copper Contributor

    Thanks for this clear article  freistli

    It used to be possible to save bot state to Azure Table Storage but I can no longer find how to do that. I tried to adapt your suggestion:

     

     

      "runtimeSettings": {
        "storage": "blobStorage",
        "blobStorage": {
            "connectionString": "myString",
            "container": "botstate"
        }

     

    but this didn't work.

     

    I don't suppose you know what I should try instead?