{"id":20726891,"url":"https://github.com/hmcts/slack-help-bot","last_synced_at":"2025-04-23T18:46:37.646Z","repository":{"id":37091771,"uuid":"331628530","full_name":"hmcts/slack-help-bot","owner":"hmcts","description":null,"archived":false,"fork":false,"pushed_at":"2025-04-17T13:48:07.000Z","size":4523,"stargazers_count":2,"open_issues_count":21,"forks_count":6,"subscribers_count":103,"default_branch":"main","last_synced_at":"2025-04-18T00:31:32.334Z","etag":null,"topics":["platops-owned-app","slack"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hmcts.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-01-21T12:58:18.000Z","updated_at":"2025-04-17T09:50:27.000Z","dependencies_parsed_at":"2024-01-26T12:10:31.827Z","dependency_job_id":"c2b6d33a-f90e-4760-8475-5ee1553af371","html_url":"https://github.com/hmcts/slack-help-bot","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hmcts%2Fslack-help-bot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hmcts%2Fslack-help-bot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hmcts%2Fslack-help-bot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hmcts%2Fslack-help-bot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hmcts","download_url":"https://codeload.github.com/hmcts/slack-help-bot/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250495539,"owners_count":21440200,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["platops-owned-app","slack"],"created_at":"2024-11-17T04:28:00.970Z","updated_at":"2025-04-23T18:46:37.639Z","avatar_url":"https://github.com/hmcts.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Slack help bot\n\nA tool to make it easier for Platform users to get help.\nWith a focus on sign-posting, tooling and documentation to allow users to help themselves without needing an engineers help.\n\n## Features\n\n- Users can request help from Platform Operations by:\n  - Using the `/PlatOps help` shortcut.\n  - Messaging the PlatOps help bot and saying `help`.\n- While requesting help the bot will:\n  - Provide initial guidance, linking to documentation, recent announcements and providing guidance on what should be raised here.\n  - Link to our QnA maker bot Plato which has pre-programmed answers to some common questions.\n  - Ask users to fill in some details about their request.\n  - Search the `help-requests` index in `Azure AI Search` which will return the top 3 most relevant results from previous requests.\n  - Search the `the-hmcts-way` index in `Azure AI Search` which will return the top 3 most relevant results from the HMCTS Way.\n  - Send the data to `Azure AI Services` to determine which area, environment and team the request is likely about and will preselect these fields for the user.\n  - Create a ticket in Jira with the data provided.\n  - Post the request in the `#platops-help` channel.\n- Help request threads support these commands by messaging `@PlatOps help \u003ccommand\u003e`:\n  - `help` - list of all available commands\n  - `duplicate \u003cjira ticket id\u003e` - mark a request as a duplicate of another ticket\n  - `summarise` - an AI will summarise all replies in the Slack thread into one message\n- On close of a request the bot will ask for what type of help was required and what was done to resolve the issue.\n- `@PlatOps help` home page displays the following reports:\n  - Open unassigned help requests\n  - Assigned to me\n  - Raised by me\n- Auto close inactive issues\n  - A cron job built into the bot will close any issues that have been not been updated for 10 days\n- Analytics on usage of the bot\n  - Events are recorded in Application Insights when user actions are taken, for more details see [analytics](#analytics).\n  - Labels are added to Jira tickets that can be reported on in Jira to see what team / area / environment is requesting the most help\n\n## Architecture\n\n![Architecture diagram](images/slack-help-bot.svg)\n\nDuring help request workflow the application:\n\n1. Asks Azure AI services for recommendation for area, environment and team.\n2. Searches Azure AI search for similar requests.\n3. Searches Azure AI search for anything on the hmcts way that might be relevant.\n4. Creates the request in Slack and Jira.\n5. Stores the request in Cosmos DB.\n6. Replies on the help request Slack thread are added to Jira.\n   - Replies on Jira are not added to Slack.\n\nOn close of the help request:\n\n1. Status, resolution type and resolution comment added to cosmos DB.\n\nSearch index:\n\n1. Search service has an indexer configured to pull new data from Cosmos DB every 5 minutes.\n   - Only certain fields are configured, see the [indexer configuration](./components/infrastructure/ai-search-index.tf).\n2. Knowledge store data is stored in Azure Blob Storage, which is uploaded to by a GitHub action in [hmcts/hmcts.github.io](https://github.com/hmcts/hmcts.github.io).\n   - The GitHub action then triggers the indexer to update the knowledge store index.\n\nAI summarising:\n\n1. If a user requests a help request to be summarised, all comments are retrieved and sent to AI services for summarisation.\n\nAzure resources:\n\n- All azure resources are created in the [`components/infrastructure`](./components/infrastructure) folder.\n\n## Getting Started with the Bot\n\n### Prerequisites\n\nRunning the application requires the following tools to be installed in your environment:\n\n- [Node.js](https://nodejs.org/) v20.0.0 or later\n- [npm](https://www.npmjs.com/)\n- [Docker](https://www.docker.com)\n- [Azure CLI](https://docs.microsoft.com/en-gb/cli/azure/install-azure-cli) - locally only\n\nYou need to create a Slack App as detailed in the steps below.\n\n## Creating the Slack App\n\nFor members of Platform Operations we have a test workspace that you can use `hmcts-platops-sandbox`, ask in #platform-operations for an invitation.\nYou'll be able to install and test changes to your app there without waiting for someone to approve the change.\n\n1. Create a new app in your workspace. Follow the Slack documentation for [creating an app from a manifest](https://api.slack.com/reference/manifests).\n\nOpen a browser and navigate to [api.slack.com/apps](https://api.slack.com/apps). This is where we will create a new app with our previously copied manifest details. Click the **Create New App** button, then select **From an app manifest** when prompted to choose how you'd like to configure your app's settings.\n\n\u003cimg alt=\"Image showing how to create app\" src=\"images/create-app.png\" width=30% height=30% /\u003e\n\nNext, select a workspace where you have permissions to install apps `hmcts-platops-sandbox`, then confirm **Next**. Select the **YAML** tab and clear the existing contents. Paste the Manifest content below, make sure you update the name:\n\n```yaml\ndisplay_information:\n  name: \u003cyour name\u003e PlatOps help\n  description: Help requests for Platform Operations\n  background_color: \"#262626\"\nfeatures:\n  app_home:\n    home_tab_enabled: true\n    messages_tab_enabled: true\n    messages_tab_read_only_enabled: false\n  bot_user:\n    display_name: PlatOps help\n    always_online: true\n  shortcuts:\n    - name: PlatOps Help Request\n      type: global\n      callback_id: begin_help_request_sc\n      description: Request help from Platform Operations\noauth_config:\n  scopes:\n    bot:\n      - app_mentions:read\n      - channels:history\n      - channels:read\n      - chat:write\n      - chat:write.customize\n      - groups:history\n      - groups:read\n      - groups:write\n      - im:read\n      - im:write\n      - reactions:write\n      - users.profile:read\n      - users:read\n      - users:read.email\n      - im:history\n      - commands\nsettings:\n  event_subscriptions:\n    user_events:\n      - app_home_opened\n    bot_events:\n      - app_home_opened\n      - app_mention\n      - message.channels\n      - message.im\n      - function_executed\n  interactivity:\n    is_enabled: true\n  org_deploy_enabled: true\n  socket_mode_enabled: true\n  token_rotation_enabled: false\n  hermes_app_type: remote\n  function_runtime: remote\nfunctions:\n  begin_help_request:\n    title: Begin Help Request\n    description: \"\"\n    input_parameters: {}\n    output_parameters: {}\n```\n\n2. Add a custom workflow\n\n**Steps from Apps** for legacy workflows is now [deprecated](https://api.slack.com/changelog/2023-08-workflow-steps-from-apps-step-back).\n\nInstead of using the now deprecated **Step from App**, it is recommended that you re-implement your step as a [custom function](https://api.slack.com/automation/functions/custom). Here is some more slack documentation that covers [Create a custom step for Workflow Builder](https://api.slack.com/tutorials/tracks/bolt-custom-function-existing).\n\nBelow takes you through the basics of how to implement a custom function:\n\nNavigate to **Org Level Apps** in the left nav and click **Opt-In**, then confirm **Yes**, Opt-In.\n\n\u003cimg alt=\"Image showing how to opt in\" src=\"images/opt-in.png\" width=30% height=30% /\u003e\n\nNavigate to **Workflow Steps** in the left nav and click **Add Step**. This is where we'll configure our step's inputs, outputs, name, and description.\n\n\u003cimg alt=\"Image showing how to add a workflow step\" src=\"images/adding-workflow-steps.png\" width=30% height=30% /\u003e\n\nFor illustration purposes, we're going to write a custom step called Begin Help Request. When the step is invoked, a message will be sent to the provided manager with an option to request some dedicated help from Platform Operations Help Bot.\n\n\u003cimg alt=\"Image showing how to create a custom step\" src=\"images/write-custom-step.png\" width=30% height=30% /\u003e\n\nOnce you have saved your changes click on the **Workflow Steps** in the left nav will show you that one workflow step has been added! This reflects the function defined in our manifest; functions are workflow steps. Below is an example of what it would look like:\n\n\u003cimg alt=\"Image showing what an added workflow step looks like\" src=\"images/workflow-steps-example.png\" width=30% height=30% /\u003e\n\n3. Collect Tokens\n\nIn order to connect our app here with the logic of our sample code set up locally, we need to gather two tokens, a bot token and an app token.\n\n**Bot tokens** are associated with bot users, and are only granted once in a workspace where someone installs the app.\n\n**App-level** tokens represent your app across organizations, including installations and are commonly used for creating websocket connections to your app.\n\nTo generate an app token, navigate to **Basic Information** and scroll down to **App-Level Token**.\n\n\u003cimg alt=\"Image showing how to generate app level token\" src=\"images/generate-app-level-token.png\" width=30% height=30% /\u003e\n\nClick **Generate Token and Scopes**, then **Add Scope** and choose `connections:write`. Choose a name for your token and click **Generate**. Copy that value, save it somewhere accessible, and click **Done** to close out of the modal.\n\n\u003cimg alt=\"Image showing how to view your app level token\" src=\"images/view-app-level-token.png\" width=30% height=30% /\u003e\n\nNext up is the bot token. We can only get this token by installing the app into the workspace.\n\n4. Installing App\n\nNavigate to **Install App** and click the button to install, choosing **Allow** at the next screen.\n\n\u003cimg alt=\"Image showing how to install app to slack workspace\" src=\"images/install-app-to-slack.png\" width=30% height=30% /\u003e\n\nYou will then have a bot token. Again, copy that value and save it somewhere accessible.\n\n\u003cimg alt=\"Image showing how to access the bot token\" src=\"images/bot-token.png\" width=30% height=30% /\u003e\n\n5. Invite the app in the channel where you would like it to be used in Slack. Navigate to the channel where you want the app to be active. Type /invite @YourAppName in the message box and hit enter. Replace @YourAppName with the actual name of your Slack app.\n\n6. Make a note of the **channel ID** as this will later be required in the slack-help-bot configuration. You can get the channel ID by right-clicking, 'copy link', and then it will be the bit after archives in the url, e.g. `C01APTJAM7D`.\n\n## Running the application\n\nWe use 'Socket mode' so no need to proxy Slack's requests.\n\n### Running on Kubernetes\n\nThe application is deployed on Kubernetes using the [HMCTS nodejs chart](https://github.com/hmcts/chart-nodejs).\nTo avoid exposing sensitive data from the configuration above you can add them as secrets from an Azure Key Vault.\nSee the [chart-library documentation](https://github.com/hmcts/chart-library#keyvault-secret-csi-volumes) for further info.\n\nThe configuration for the deployed instance can be found in [hmcts/cnp-flux-config in the slack-help-bot kustomization](https://github.com/hmcts/cnp-flux-config/blob/master/apps/slack-help-bot/slack-help-bot/slack-help-bot.yaml).\n\n### Running locally\n\nAll configuration requirements listed above can be found in the \"env.template.txt\" file.\n\n### Initial setup\n\nRename \"env.template.txt\" to \".env\" which is gitignored and safe for secrets.\n\nSource into your shell with:\n\n```bash\n$ set -o allexport; source .env; set +o allexport\n```\n\nInstall dependencies by executing the following command:\n\n```bash\n$ npm install\n```\n\n### Azure connection\n\nThe AI features of the bot are powered by a number of Azure services. To connect to these services you will need to authenticate with Azure.\nIf you are in the `DTS Platform Operations` Security Group you will have the permissions needed to use the services.\n\nTo authenticate with Azure, run the following command:\n\n```bash\naz login\n```\n\n[See more information on authenticating with Azure in a local development environment](https://learn.microsoft.com/en-us/javascript/api/overview/azure/identity-readme?view=azure-node-latest#authenticate-the-client-in-development-environment).\n\nIf you aren't in the `DTS Platform Operations group` you will need at least the following permissions on their respective resources:\n\n- Cosmos DB Built-in Data Contributor - This is a cosmos specific permission and can't be assigned using the Azure Portal\n- Cognitive Services OpenAI User\n- Search Index Data Reader\n\n### Starting\n\nRun:\n\n```bash\nnpm start\n```\n\n#### Running locally with Docker\n\nThere is no need to source your configuration. The \".env\" file will be loaded automatically.\n\nCreate docker image:\n\n```bash\ndocker compose build\n```\n\n##### Login to Azure\n\nWe are using the [azure-cli-credentials-proxy](https://github.com/gsoft-inc/azure-cli-credentials-proxy) to re-use\nyour local access token without having to pass credentials to the container.\n\nFollow the same instructions as in [Azure connection](#azure-connection) to authenticate with Azure.\n\n##### Start the application\n\nRun the application by executing the following command:\n\n```bash\ndocker compose up\n```\n\nThis will start the frontend container exposing the application's port\n(set to `3000` in this template app).\n\nIn order to test if the application is up, you can visit https://localhost:3000/health in your browser.\nYou should get a very basic health page.\n\n## Analytics\n\nThe bot uses Application Insights to record events when users interact with the bot.\nThe resource is called `slack-help-bot-ptl`.\n\nHere are a couple of useful queries:\n\n[Pie chart query in Log Analytics](https://portal.azure.com#@531ff96d-0ae9-462a-8d2d-bec7c0b42082/blade/Microsoft_OperationsManagementSuite_Workspace/Logs.ReactView/resourceId/%2Fsubscriptions%2F1baf5470-1c3e-40d3-a6f7-74bfbce4b348%2FresourceGroups%2Fslack-help-bot-cftptl-intsvc-rg%2Fproviders%2FMicrosoft.Insights%2Fcomponents%2Fslack-help-bot-ptl/source/LogsBlade.AnalyticsShareLinkToQuery/q/H4sIAAAAAAAAA0suLS7Jz3UtS80rKeaqUSguzc1NLMqsSlVIBQnFJ%252BeX5pUo2CqAaQ1NhaRKhbzE3FSgyqLUvJTUIoWCzNTkjMSiEgA13VyNSAAAAA%253D%253D/timespan/P7D/limit/1000)\n\n```kql\ncustomEvents\n| summarize event_count = count() by name\n| render piechart\n```\n\n[Column chart query in Log Analytics](https://portal.azure.com#@531ff96d-0ae9-462a-8d2d-bec7c0b42082/blade/Microsoft_OperationsManagementSuite_Workspace/Logs.ReactView/resourceId/%2Fsubscriptions%2F1baf5470-1c3e-40d3-a6f7-74bfbce4b348%2FresourceGroups%2Fslack-help-bot-cftptl-intsvc-rg%2Fproviders%2FMicrosoft.Insights%2Fcomponents%2Fslack-help-bot-ptl/source/LogsBlade.AnalyticsShareLinkToQuery/q/H4sIAAAAAAAAAx2LSQqAMAwA774ixxZ68QEefYekbcCCSSVNBcXHu5wGhpnUm1WeDxJrww2tM6OWi4A%252BtaTaxWCCn85DPCEWcVaYmiHvAcbsAwgyvbeSZNI33jpLWlHtAQAQGCVfAAAA/timespan/P7D/limit/1000)\n\n```kql\ncustomEvents\n| summarize event_count = count() by bin(timestamp, 1d), name\n| render columnchart\n```\n\n## Deploying\n\nThis application is deployed with continuous delivery, every merge to the main branch will be automatically deployed.\nThe [GitHub action](./.github/workflows/main.yml) will build the docker image and push it to the Azure Container Registry.\n\nThe deployment configuration can be found in the [hmcts/cnp-flux-config repository](https://github.com/hmcts/cnp-flux-config/blob/master/apps/slack-help-bot/slack-help-bot/slack-help-bot.yaml).\n\nThe infrastructure from the [architecture diagram](#architecture) is created using Terraform in the [components/infrastructure](./components/infrastructure) folder.\nThe [terraform pipeline](pipeline/azure-pipelines.yml) is run from Azure DevOps, a plan is run on a pull request and it will automatically apply on merge to main.\n\n## Adding new fields to dropdowns\n\nIf you want to add new fields to dropdowns like the area or resolution type the easiest way is to search for the text of another option in the codebase and then add your new option there.\nThey are normally sorted in alphabetical order although environments are generally in increasing order of importance and Other is normally last.\n\nFor most dropdowns you will also need to update the [LLM prompt](./src/ai/prompts.js) to allow it to suggest the new option, resolution type doesn't need to be added there.\n\nDropdowns use the `optionBlock` function, it can take either one or two arguments, the first argument is the display name and the second is the label that will be used in Jira.\nCertain characters can't be used in Jira labels so if you have a complex display name then supply a simpler label or if a team is commonly known by a short name it is common to use the short name in the label as well.\n\ne.g.\n\n```javascript\noptionBlock(\"GitHub\");\n```\n\nor\n\n```javascript\noptionBlock(\"Security Operations / Secure Design\", \"security\");\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhmcts%2Fslack-help-bot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhmcts%2Fslack-help-bot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhmcts%2Fslack-help-bot/lists"}