Add Slack app_mention handling behind slack_duo_agent feature flag

What does this MR do and why?

We recently worked on a PoC for a Slack bot that allows to interact with Duo (e.g. creating issues from Slack).

We want to push this closer to production and this MR is the first step of a Duo Agent-powered Slack bot by handling @mention events — i.e. when a user @mentions the GitLab bot in Slack.

This is intentionally minimal: the bot echoes back the user's message as proof that the full pipeline works end-to-end.

The Duo Workflow integration will be wired in a follow-up MR to make this a MVC.

The feature is gated behind the slack_duo_agent beta feature flag (per-user actor), so it can be selectively enabled on GitLab.com without affecting other users or self-managed instances.

What's included:

  • Routes app_mention Slack events through the existing SlackEventWorker
  • AppMentionedService handles the full flow:
    • Unauthenticated users: 🔒 reaction + ephemeral prompt to connect their GitLab account
    • Authenticated users without the flag: 🔒 reaction + ephemeral "you do not have access" message
    • Authenticated users with the flag: 👀 reaction → echo reply → reaction
  • Slack::API#get added to support future thread fetching and user lookups
  • Beta feature flag slack_duo_agent (default off)

What's NOT included (follow-up MRs):

  • Slack app manifest changes — the new bot uses a separate manually-configured Slack app for now (see setup instructions below)
  • Thread context fetching (conversations.replies) and user name resolution
  • Duo Workflow integration (the actual AI response)

Screenshots or screen recordings

Slack app manifest

This MR does not modify the downloadable Slack manifest (Slack::Manifest). To test or use this feature, manually configure a separate Slack app with the following manifest:

{
  "display_information": {
    "name": "GitLab Duo (gdk.test)",
    "description": "Interact with GitLab Duo without leaving your Slack workspace!",
    "background_color": "#171321"
  },
  "features": {
    "app_home": {
      "home_tab_enabled": true,
      "messages_tab_enabled": false,
      "messages_tab_read_only_enabled": true
    },
    "bot_user": {
      "display_name": "Duo",
      "always_online": true
    },
    "slash_commands": [
      {
        "command": "/gitlab",
        "url": "https://<change-this-to-your-url>/api/v4/slack/trigger",
        "description": "GitLab slash commands",
        "usage_hint": "your-project-name-or-alias command",
        "should_escape": false
      }
    ]
  },
  "oauth_config": {
    "redirect_urls": ["http://gdk.test:3000"],
    "scopes": {
      "bot": [
        "app_mentions:read",
        "commands",
        "chat:write",
        "chat:write.public",
        "channels:history",
        "groups:history",
        "reactions:write",
        "users:read"
      ]
    }
  },
  "settings": {
    "event_subscriptions": {
      "request_url": "https://<change-this-to-your-url>/api/v4/integrations/slack/events",
      "bot_events": ["app_home_opened", "app_mention"]
    },
    "interactivity": {
      "is_enabled": true,
      "request_url": "https://<change-this-to-your-url>/api/v4/integrations/slack/interactions",
      "message_menu_options_url": "http://<change-this-to-your-url>/api/v4/integrations/slack/options"
    },
    "org_deploy_enabled": false,
    "socket_mode_enabled": false,
    "token_rotation_enabled": false
  }
}

Note that you need to change the <change-this-to-your-url> to the URL that you expose your instance to (more in the testing section).

How to set up and validate locally

  1. Configure a Slack app using the manifest above, pointed <change-this-to-your-url> at your GDK tunnel URL (e.g. via Cloudflare Tunnel or ngrok)

  2. Make sure to start your rails app with RAILS_HOSTS=<change-this-to-your-url>

  3. Install the Slack app to your workspace and connect it to a GitLab integration

  4. Enable the feature flag for your user in the rails console:

    Feature.enable(:slack_duo_agent, User.find_by(username: 'your-username'))
  5. Test unauthenticated flow: Remove any existing Slack-GitLab user link, then @mention the bot. You should see a 🔒 reaction and an ephemeral message prompting you to connect your GitLab account:

    ChatName.where(team_id: '<your-team-id>', chat_id: '<your-slack-user-id>').destroy_all
  6. Click the auth link and connect your GitLab account

  7. Test flag-off flow: Disable the flag, then @mention the bot. You should see a 🔒 reaction and an ephemeral "you do not have access" message:

    Feature.disable(:slack_duo_agent)
  8. Test flag-on flow: Re-enable the flag, @mentionthe bot with any message. You should see:

    • 👀 reaction appears
    • Bot replies in the thread: "You said: {your message}"
    • reaction replaces 👀
    Feature.enable(:slack_duo_agent, User.find_by(username: 'your-username'))
Edited by Thomas Schmidt

Merge request reports

Loading