diff --git a/ee/app/assets/javascripts/ai/tanuki_bot/components/app.vue b/ee/app/assets/javascripts/ai/tanuki_bot/components/app.vue
index cc4701e2297a1946baa99ca74798ec8482f93b31..04299155786a264f6dee91ffd4442d57da9bf9c7 100644
--- a/ee/app/assets/javascripts/ai/tanuki_bot/components/app.vue
+++ b/ee/app/assets/javascripts/ai/tanuki_bot/components/app.vue
@@ -11,6 +11,7 @@ import aiResponseSubscription from 'ee/graphql_shared/subscriptions/ai_completio
 import DuoChatCallout from 'ee/ai/components/global_callout/duo_chat_callout.vue';
 import getAiMessages from 'ee/ai/graphql/get_ai_messages.query.graphql';
 import chatMutation from 'ee/ai/graphql/chat.mutation.graphql';
+import duoUserFeedbackMutation from 'ee/ai/graphql/duo_user_feedback.mutation.graphql';
 import Tracking from '~/tracking';
 import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
 import { i18n, GENIE_CHAT_RESET_MESSAGE, GENIE_CHAT_CLEAN_MESSAGE } from 'ee/ai/constants';
@@ -162,7 +163,7 @@ export default {
     onCalloutDismissed() {
       this.helpCenterState.showTanukiBotChatDrawer = true;
     },
-    onTrackFeedback({ feedbackChoices, didWhat, improveWhat } = {}) {
+    onTrackFeedback({ feedbackChoices, didWhat, improveWhat, message } = {}) {
       this.track(TANUKI_BOT_TRACKING_EVENT_NAME, {
         action: 'click_button',
         label: 'response_feedback',
@@ -173,6 +174,29 @@ export default {
           prompt_location: 'after_content',
         },
       });
+
+      if (message) {
+        const { id, requestId, extras, role, content } = message;
+        this.$apollo
+          .mutate({
+            mutation: duoUserFeedbackMutation,
+            variables: {
+              input: {
+                aiMessageId: id,
+              },
+            },
+          })
+          .catch(() => {
+            // silent failure because of fire and forget
+          });
+
+        this.addDuoChatMessage({
+          requestId,
+          role,
+          content,
+          extras: { ...extras, hasFeedback: true },
+        });
+      }
     },
   },
 };
diff --git a/ee/spec/frontend/ai/tanuki_bot/components/app_spec.js b/ee/spec/frontend/ai/tanuki_bot/components/app_spec.js
index 70befa0de631db0cbcdf4450329a7b9043bc8879..d65100af89c8dd42611e0c9c00c882cbe4c7bc48 100644
--- a/ee/spec/frontend/ai/tanuki_bot/components/app_spec.js
+++ b/ee/spec/frontend/ai/tanuki_bot/components/app_spec.js
@@ -10,6 +10,7 @@ import { GENIE_CHAT_RESET_MESSAGE, GENIE_CHAT_CLEAN_MESSAGE } from 'ee/ai/consta
 import { TANUKI_BOT_TRACKING_EVENT_NAME } from 'ee/ai/tanuki_bot/constants';
 import aiResponseSubscription from 'ee/graphql_shared/subscriptions/ai_completion_response.subscription.graphql';
 import chatMutation from 'ee/ai/graphql/chat.mutation.graphql';
+import duoUserFeedbackMutation from 'ee/ai/graphql/duo_user_feedback.mutation.graphql';
 import getAiMessages from 'ee/ai/graphql/get_ai_messages.query.graphql';
 import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
 import createMockApollo from 'helpers/mock_apollo_helper';
@@ -43,8 +44,24 @@ describe('GitLab Duo Chat', () => {
 
   const subscriptionHandlerMock = jest.fn().mockResolvedValue(MOCK_TANUKI_SUCCESS_RES);
   const chatMutationHandlerMock = jest.fn().mockResolvedValue(MOCK_TANUKI_BOT_MUTATATION_RES);
+  const duoUserFeedbackMutationHandlerMock = jest.fn().mockResolvedValue({});
   const queryHandlerMock = jest.fn().mockResolvedValue(MOCK_CHAT_CACHED_MESSAGES_RES);
 
+  const feedbackData = {
+    feedbackChoices: ['useful', 'not_relevant'],
+    didWhat: 'provided clarity',
+    improveWhat: 'more examples',
+    message: {
+      requestId: '1234567890',
+      id: 'abcdefgh',
+      role: 'user',
+      content: 'test',
+      extras: {
+        exampleExtraContent: 1,
+      },
+    },
+  };
+
   const findCallout = () => wrapper.findComponent(DuoChatCallout);
 
   const createComponent = ({
@@ -62,6 +79,7 @@ describe('GitLab Duo Chat', () => {
     const apolloProvider = createMockApollo([
       [aiResponseSubscription, subscriptionHandlerMock],
       [chatMutation, chatMutationHandlerMock],
+      [duoUserFeedbackMutation, duoUserFeedbackMutationHandlerMock],
       [getAiMessages, queryHandlerMock],
     ]);
 
@@ -295,6 +313,34 @@ describe('GitLab Duo Chat', () => {
           },
         });
       });
+
+      it('calls the feedback GraphQL mutation when message is passed', async () => {
+        createComponent();
+        findGlDuoChat().vm.$emit('track-feedback', feedbackData);
+
+        await waitForPromises();
+        expect(duoUserFeedbackMutationHandlerMock).toHaveBeenCalledWith({
+          input: {
+            aiMessageId: feedbackData.message.id,
+          },
+        });
+      });
+
+      it('updates Vuex store correctly when message is passed', async () => {
+        createComponent();
+        findGlDuoChat().vm.$emit('track-feedback', feedbackData);
+
+        await waitForPromises();
+        expect(actionSpies.addDuoChatMessage).toHaveBeenCalledWith(
+          expect.any(Object),
+          expect.objectContaining({
+            requestId: feedbackData.message.requestId,
+            role: feedbackData.message.role,
+            content: feedbackData.message.content,
+            extras: { ...feedbackData.message.extras, hasFeedback: true },
+          }),
+        );
+      });
     });
   });