diff --git a/backend/danswer/danswerbot/slack/handlers/handle_message.py b/backend/danswer/danswerbot/slack/handlers/handle_message.py
index 90b3b354c..2cd309547 100644
--- a/backend/danswer/danswerbot/slack/handlers/handle_message.py
+++ b/backend/danswer/danswerbot/slack/handlers/handle_message.py
@@ -37,6 +37,7 @@ from danswer.danswerbot.slack.constants import SLACK_CHANNEL_ID
from danswer.danswerbot.slack.models import SlackMessageInfo
from danswer.danswerbot.slack.utils import ChannelIdAdapter
from danswer.danswerbot.slack.utils import fetch_userids_from_emails
+from danswer.danswerbot.slack.utils import fetch_userids_from_groups
from danswer.danswerbot.slack.utils import respond_in_thread
from danswer.danswerbot.slack.utils import slack_usage_report
from danswer.danswerbot.slack.utils import SlackRateLimiter
@@ -262,6 +263,7 @@ def handle_message(
respond_tag_only = channel_conf.get("respond_tag_only") or False
respond_team_member_list = channel_conf.get("respond_team_member_list") or None
+ respond_slack_group_list = channel_conf.get("respond_slack_group_list") or None
if respond_tag_only and not bypass_filters:
logger.info(
@@ -271,7 +273,11 @@ def handle_message(
return False
if respond_team_member_list:
- send_to, _ = fetch_userids_from_emails(respond_team_member_list, client)
+ user_ids, _ = fetch_userids_from_emails(respond_team_member_list, client)
+ send_to = (send_to + user_ids) if send_to else user_ids
+ if respond_slack_group_list:
+ user_ids, _ = fetch_userids_from_groups(respond_slack_group_list, client)
+ send_to = (send_to + user_ids) if send_to else user_ids
# If configured to respond to team members only, then cannot be used with a /DanswerBot command
# which would just respond to the sender
diff --git a/backend/danswer/danswerbot/slack/utils.py b/backend/danswer/danswerbot/slack/utils.py
index 892734e99..12f7b4662 100644
--- a/backend/danswer/danswerbot/slack/utils.py
+++ b/backend/danswer/danswerbot/slack/utils.py
@@ -308,6 +308,31 @@ def fetch_userids_from_emails(
return user_ids, failed_to_find
+def fetch_userids_from_groups(
+ group_names: list[str], client: WebClient
+) -> tuple[list[str], list[str]]:
+ user_ids: list[str] = []
+ failed_to_find: list[str] = []
+ for group_name in group_names:
+ try:
+ # First, find the group ID from the group name
+ response = client.usergroups_list()
+ groups = {group["name"]: group["id"] for group in response["usergroups"]}
+ group_id = groups.get(group_name)
+
+ if group_id:
+ # Fetch user IDs for the group
+ response = client.usergroups_users_list(usergroup=group_id)
+ user_ids.extend(response["users"])
+ else:
+ failed_to_find.append(group_name)
+ except Exception as e:
+ logger.error(f"Error fetching user IDs for group {group_name}: {str(e)}")
+ failed_to_find.append(group_name)
+
+ return user_ids, failed_to_find
+
+
def fetch_groupids_from_names(
names: list[str], client: WebClient
) -> tuple[list[str], list[str]]:
diff --git a/backend/danswer/db/models.py b/backend/danswer/db/models.py
index 29ca74bfc..01cd4c6e3 100644
--- a/backend/danswer/db/models.py
+++ b/backend/danswer/db/models.py
@@ -1059,6 +1059,7 @@ class ChannelConfig(TypedDict):
respond_tag_only: NotRequired[bool] # defaults to False
respond_to_bots: NotRequired[bool] # defaults to False
respond_team_member_list: NotRequired[list[str]]
+ respond_slack_group_list: NotRequired[list[str]]
answer_filters: NotRequired[list[AllowedAnswerFilters]]
# If None then no follow up
# If empty list, follow up with no tags
diff --git a/backend/danswer/server/manage/models.py b/backend/danswer/server/manage/models.py
index cbc3251bf..1e4f44789 100644
--- a/backend/danswer/server/manage/models.py
+++ b/backend/danswer/server/manage/models.py
@@ -104,6 +104,7 @@ class SlackBotConfigCreationRequest(BaseModel):
respond_to_bots: bool = False
# If no team members, assume respond in the channel to everyone
respond_team_member_list: list[str] = []
+ respond_slack_group_list: list[str] = []
answer_filters: list[AllowedAnswerFilters] = []
# list of user emails
follow_up_tags: list[str] | None = None
diff --git a/backend/danswer/server/manage/slack_bot.py b/backend/danswer/server/manage/slack_bot.py
index aade420ad..979776983 100644
--- a/backend/danswer/server/manage/slack_bot.py
+++ b/backend/danswer/server/manage/slack_bot.py
@@ -37,6 +37,9 @@ def _form_channel_config(
respond_team_member_list = (
slack_bot_config_creation_request.respond_team_member_list
)
+ respond_slack_group_list = (
+ slack_bot_config_creation_request.respond_slack_group_list
+ )
answer_filters = slack_bot_config_creation_request.answer_filters
follow_up_tags = slack_bot_config_creation_request.follow_up_tags
@@ -58,7 +61,7 @@ def _form_channel_config(
detail=str(e),
)
- if respond_tag_only and respond_team_member_list:
+ if respond_tag_only and (respond_team_member_list or respond_slack_group_list):
raise ValueError(
"Cannot set DanswerBot to only respond to tags only and "
"also respond to a predetermined set of users."
@@ -71,6 +74,8 @@ def _form_channel_config(
channel_config["respond_tag_only"] = respond_tag_only
if respond_team_member_list:
channel_config["respond_team_member_list"] = respond_team_member_list
+ if respond_slack_group_list:
+ channel_config["respond_slack_group_list"] = respond_slack_group_list
if answer_filters:
channel_config["answer_filters"] = answer_filters
if follow_up_tags is not None:
diff --git a/web/src/app/admin/bot/SlackBotConfigCreationForm.tsx b/web/src/app/admin/bot/SlackBotConfigCreationForm.tsx
index 6a5984125..cfcca211d 100644
--- a/web/src/app/admin/bot/SlackBotConfigCreationForm.tsx
+++ b/web/src/app/admin/bot/SlackBotConfigCreationForm.tsx
@@ -74,6 +74,9 @@ export const SlackBotCreationForm = ({
respond_team_member_list:
existingSlackBotConfig?.channel_config
?.respond_team_member_list || ([] as string[]),
+ respond_slack_group_list:
+ existingSlackBotConfig?.channel_config
+ ?.respond_slack_group_list || ([] as string[]),
still_need_help_enabled:
existingSlackBotConfig?.channel_config?.follow_up_tags !==
undefined,
@@ -102,6 +105,7 @@ export const SlackBotCreationForm = ({
respond_tag_only: Yup.boolean().required(),
respond_to_bots: Yup.boolean().required(),
respond_team_member_list: Yup.array().of(Yup.string()).required(),
+ respond_slack_group_list: Yup.array().of(Yup.string()).required(),
still_need_help_enabled: Yup.boolean().required(),
follow_up_tags: Yup.array().of(Yup.string()),
document_sets: Yup.array().of(Yup.number()),
@@ -119,6 +123,9 @@ export const SlackBotCreationForm = ({
respond_team_member_list: values.respond_team_member_list.filter(
(teamMemberEmail) => teamMemberEmail !== ""
),
+ respond_slack_group_list: values.respond_slack_group_list.filter(
+ (slackGroupName) => slackGroupName !== ""
+ ),
usePersona: usingPersonas,
};
if (!cleanedValues.still_need_help_enabled) {
@@ -237,6 +244,15 @@ export const SlackBotCreationForm = ({
out the occasional incorrect answer.`}
values={values}
/>
+
Post Response Behavior
diff --git a/web/src/app/admin/bot/lib.ts b/web/src/app/admin/bot/lib.ts
index b6c6bec16..07feab85d 100644
--- a/web/src/app/admin/bot/lib.ts
+++ b/web/src/app/admin/bot/lib.ts
@@ -14,6 +14,7 @@ interface SlackBotConfigCreationRequest {
respond_tag_only: boolean;
respond_to_bots: boolean;
respond_team_member_list: string[];
+ respond_slack_group_list: string[];
follow_up_tags?: string[];
usePersona: boolean;
response_type: SlackBotResponseType;
@@ -40,6 +41,7 @@ const buildRequestBodyFromCreationRequest = (
respond_tag_only: creationRequest.respond_tag_only,
respond_to_bots: creationRequest.respond_to_bots,
respond_team_member_list: creationRequest.respond_team_member_list,
+ respond_slack_group_list: creationRequest.respond_slack_group_list,
answer_filters: buildFiltersFromCreationRequest(creationRequest),
follow_up_tags: creationRequest.follow_up_tags?.filter((tag) => tag !== ""),
...(creationRequest.usePersona
diff --git a/web/src/lib/types.ts b/web/src/lib/types.ts
index 138765c5c..30c336f97 100644
--- a/web/src/lib/types.ts
+++ b/web/src/lib/types.ts
@@ -475,6 +475,7 @@ export interface ChannelConfig {
respond_tag_only?: boolean;
respond_to_bots?: boolean;
respond_team_member_list?: string[];
+ respond_slack_group_list?: string[];
answer_filters?: AnswerFilterOption[];
follow_up_tags?: string[];
}