diff --git a/ee/app/assets/javascripts/vulnerabilities/components/explain_vulnerability/explain_vulnerability.vue b/ee/app/assets/javascripts/vulnerabilities/components/explain_vulnerability/explain_vulnerability.vue
index 0682c3bc99235e48c807dab3b60da446ae620651..476fec6947b2cd13950abbdc7b4087cea505a43b 100644
--- a/ee/app/assets/javascripts/vulnerabilities/components/explain_vulnerability/explain_vulnerability.vue
+++ b/ee/app/assets/javascripts/vulnerabilities/components/explain_vulnerability/explain_vulnerability.vue
@@ -4,8 +4,7 @@ import { s__ } from '~/locale';
 import { helpPagePath } from '~/helpers/help_page_helper';
 import { convertToGraphQLId } from '~/graphql_shared/utils';
 import { TYPENAME_VULNERABILITY } from '~/graphql_shared/constants';
-import chatMutation from 'ee/ai/graphql/chat.mutation.graphql';
-import { duoChatGlobalState } from '~/super_sidebar/constants';
+import { sendDuoChatCommand } from 'ee/ai/utils';
 
 export default {
   components: {
@@ -28,14 +27,9 @@ export default {
   },
   methods: {
     triggerDuoChat() {
-      duoChatGlobalState.isShown = true;
-
-      this.$apollo.mutate({
-        mutation: chatMutation,
-        variables: {
-          question: '/vulnerability_explain',
-          resourceId: this.vulnerabilityGraphqlId,
-        },
+      sendDuoChatCommand({
+        question: '/vulnerability_explain',
+        resourceId: this.vulnerabilityGraphqlId,
       });
     },
   },
diff --git a/ee/app/assets/javascripts/vulnerabilities/components/header.vue b/ee/app/assets/javascripts/vulnerabilities/components/header.vue
index 36d415fe45b86ef0d3cb224b549aba57dba49172..63d719c98fc013b8e026aa9773fc587a2a2b134c 100644
--- a/ee/app/assets/javascripts/vulnerabilities/components/header.vue
+++ b/ee/app/assets/javascripts/vulnerabilities/components/header.vue
@@ -3,6 +3,7 @@ import { GlLoadingIcon, GlTooltipDirective as GlTooltip } from '@gitlab/ui';
 import { v4 as uuidv4 } from 'uuid';
 import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
 import glAbilitiesMixin from '~/vue_shared/mixins/gl_abilities_mixin';
+import { sendDuoChatCommand } from 'ee/ai/utils';
 import vulnerabilityStateMutations from 'ee/security_dashboard/graphql/mutate_vulnerability_state';
 import StatusBadge from 'ee/vue_shared/security_reports/components/status_badge.vue';
 import { createAlert } from '~/alert';
@@ -14,8 +15,6 @@ import download from '~/lib/utils/downloader';
 import { visitUrl } from '~/lib/utils/url_utility';
 import UsersCache from '~/lib/utils/users_cache';
 import { __, s__ } from '~/locale';
-import { duoChatGlobalState } from '~/super_sidebar/constants';
-import chatMutation from 'ee/ai/graphql/chat.mutation.graphql';
 import aiResponseSubscription from 'ee/graphql_shared/subscriptions/ai_completion_response.subscription.graphql';
 import aiResolveVulnerability from '../graphql/ai_resolve_vulnerability.mutation.graphql';
 import {
@@ -247,14 +246,9 @@ export default {
       }
     },
     explainVulnerability() {
-      duoChatGlobalState.isShown = true;
-
-      this.$apollo.mutate({
-        mutation: chatMutation,
-        variables: {
-          question: '/vulnerability_explain',
-          resourceId: this.vulnerabilityGraphqlId,
-        },
+      sendDuoChatCommand({
+        question: '/vulnerability_explain',
+        resourceId: this.vulnerabilityGraphqlId,
       });
     },
     resolveVulnerability() {
diff --git a/ee/spec/frontend/vulnerabilities/explain_vulnerability/explain_vulnerability_spec.js b/ee/spec/frontend/vulnerabilities/explain_vulnerability/explain_vulnerability_spec.js
index b70692826329c0e0300e3502c1f9e03fe939452b..0a741804615c10bd66a0c3dee7aa7159316026da 100644
--- a/ee/spec/frontend/vulnerabilities/explain_vulnerability/explain_vulnerability_spec.js
+++ b/ee/spec/frontend/vulnerabilities/explain_vulnerability/explain_vulnerability_spec.js
@@ -2,11 +2,11 @@ import Vue from 'vue';
 import VueApollo from 'vue-apollo';
 import { GlLink, GlSprintf } from '@gitlab/ui';
 import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import * as utils from 'ee/ai/utils';
 import ExplainVulnerability from 'ee/vulnerabilities/components/explain_vulnerability/explain_vulnerability.vue';
-import { duoChatGlobalState } from '~/super_sidebar/constants';
-import chatMutation from 'ee/ai/graphql/chat.mutation.graphql';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import { MOCK_TANUKI_BOT_MUTATATION_RES } from 'ee_jest/ai/tanuki_bot/mock_data';
+
+jest.mock('ee/ai/utils');
+jest.spyOn(utils, 'sendDuoChatCommand');
 
 Vue.use(VueApollo);
 
@@ -15,17 +15,12 @@ const MOCK_VULNERABILITY_ID = 1;
 describe('Explain Vulnerability component', () => {
   let wrapper;
 
-  const chatMutationHandlerMock = jest.fn().mockResolvedValue(MOCK_TANUKI_BOT_MUTATATION_RES);
-
   const createWrapper = () => {
-    const apolloProvider = createMockApollo([[chatMutation, chatMutationHandlerMock]]);
-
     wrapper = shallowMountExtended(ExplainVulnerability, {
       propsData: { vulnerabilityId: MOCK_VULNERABILITY_ID },
       stubs: {
         GlSprintf,
       },
-      apolloProvider,
     });
   };
 
@@ -65,20 +60,12 @@ describe('Explain Vulnerability component', () => {
   });
 
   describe('when the "Explain vulnerability" button is clicked', () => {
-    it('opens the global DuoChat drawer', () => {
-      expect(duoChatGlobalState.isShown).toBe(false);
-
-      clickExplainVulnerabilityButton();
-
-      expect(duoChatGlobalState.isShown).toBe(true);
-    });
-
-    it('calls a custom chat mutation with the correct prompt and resource-id', () => {
-      expect(chatMutationHandlerMock).not.toHaveBeenCalled();
+    it('calls sendDuoChatCommand with correct prompt and resource-id', () => {
+      expect(utils.sendDuoChatCommand).not.toHaveBeenCalled();
 
       clickExplainVulnerabilityButton();
 
-      expect(chatMutationHandlerMock).toHaveBeenCalledWith({
+      expect(utils.sendDuoChatCommand).toHaveBeenCalledWith({
         question: '/vulnerability_explain',
         resourceId: `gid://gitlab/Vulnerability/${MOCK_VULNERABILITY_ID}`,
       });
diff --git a/ee/spec/frontend/vulnerabilities/header_spec.js b/ee/spec/frontend/vulnerabilities/header_spec.js
index 8426b7f980d64d1506c6bc76e73b04d6303fb6a3..a9a417e1ab8ff88c9ffc91dc4cac6f65990eedd4 100644
--- a/ee/spec/frontend/vulnerabilities/header_spec.js
+++ b/ee/spec/frontend/vulnerabilities/header_spec.js
@@ -5,6 +5,7 @@ import MockAdapter from 'axios-mock-adapter';
 import VueApollo from 'vue-apollo';
 import { createMockSubscription } from 'mock-apollo-client';
 import { createMockDirective } from 'helpers/vue_mock_directive';
+import * as aiUtils from 'ee/ai/utils';
 import aiResponseSubscription from 'ee/graphql_shared/subscriptions/ai_completion_response.subscription.graphql';
 import aiResolveVulnerability from 'ee/vulnerabilities/graphql/ai_resolve_vulnerability.mutation.graphql';
 import Api from 'ee/api';
@@ -25,9 +26,6 @@ import { convertObjectPropsToSnakeCase } from '~/lib/utils/common_utils';
 import download from '~/lib/utils/downloader';
 import { HTTP_STATUS_INTERNAL_SERVER_ERROR, HTTP_STATUS_OK } from '~/lib/utils/http_status';
 import { visitUrl } from '~/lib/utils/url_utility';
-import chatMutation from 'ee/ai/graphql/chat.mutation.graphql';
-import { MOCK_TANUKI_BOT_MUTATATION_RES } from 'ee_jest/ai/tanuki_bot/mock_data';
-import { duoChatGlobalState } from '~/super_sidebar/constants';
 import {
   getVulnerabilityStatusMutationResponse,
   dismissalDescriptions,
@@ -51,6 +49,8 @@ jest.mock('~/lib/utils/url_utility', () => ({
   ...jest.requireActual('~/lib/utils/url_utility'),
   visitUrl: jest.fn(),
 }));
+jest.mock('ee/ai/utils');
+jest.spyOn(aiUtils, 'sendDuoChatCommand');
 
 describe('Vulnerability Header', () => {
   let wrapper;
@@ -637,18 +637,11 @@ describe('Vulnerability Header', () => {
     });
 
     describe('explain with AI button', () => {
-      let chatMutationHandlerMock;
-
       const findExplainWithAIButton = () => findSplitButton().props('buttons')[1];
 
       beforeEach(() => {
-        chatMutationHandlerMock = jest.fn().mockResolvedValue(MOCK_TANUKI_BOT_MUTATATION_RES);
-
-        const apolloProvider = createApolloProvider([chatMutation, chatMutationHandlerMock]);
-
         createWrapper({
           vulnerability: getVulnerability(),
-          apolloProvider,
         });
       });
 
@@ -662,19 +655,13 @@ describe('Vulnerability Header', () => {
         });
       });
 
-      it('opens the global DuoChat drawer when clicked', async () => {
-        expect(duoChatGlobalState.isShown).toBe(false);
-
-        await clickButton('explain-vulnerability');
-
-        expect(duoChatGlobalState.isShown).toBe(true);
-      });
+      it('calls sendDuoChatCommand with the correct parameters when clicked', async () => {
+        expect(aiUtils.sendDuoChatCommand).not.toHaveBeenCalled();
 
-      it('calls the correct mutation with the correct parameters when clicked', async () => {
         await clickButton('explain-vulnerability');
         await waitForPromises();
 
-        expect(chatMutationHandlerMock).toHaveBeenCalledWith({
+        expect(aiUtils.sendDuoChatCommand).toHaveBeenCalledWith({
           question: '/vulnerability_explain',
           resourceId: `gid://gitlab/Vulnerability/${defaultVulnerability.id}`,
         });