From 668643c4d722f0bc2217f6a98a015c9b111b508d Mon Sep 17 00:00:00 2001
From: Juan Valacco <97040903+jvalacco-dataherald@users.noreply.github.com>
Date: Fri, 3 Nov 2023 16:23:19 -0300
Subject: [PATCH] DH-4804 Query Editor Page Redesign (#274)

* DH-4875 [Enterprise] Save Send Run Refactor (#256)

* DH-4875 separation of save send and run

* DH-4875 refactor save send run

* DH-4875 [Enterprise] fix migration script location and adds enumarations

* query editor header

* remove default padding from page layout - wip query editor sections

* finished most of the layout

* add secondary message buttons

* finished query status - partial message section - partial resubmit

* added workflow limitations

* finished all flows -- cleanup pending

* cleanup

* fix bug (#277)

* set confidence score to none (#278)

* DH-4945 [ai][admin-console] display plain status when no evaluation score is present

* save generated message

* update submodule

* fix test

---------

Co-authored-by: Dishen <44216194+DishenWang2023@users.noreply.github.com>
Co-authored-by: dishenwang2023 <dishenwang1021@gmail.com>
---
 apps/ai/clients/admin-console/package.json    |   1 +
 apps/ai/clients/admin-console/pnpm-lock.yaml  |  33 ++
 .../public/images/slack-black.png             | Bin 0 -> 12831 bytes
 .../{slack-white.png => slack-color.png}      | Bin
 .../src/components/layout/page-layout.tsx     |   9 +-
 ...e-dialog.tsx => custom-message-dialog.tsx} |  45 +-
 ...oading-sql-results.tsx => loading-box.tsx} |   8 +-
 .../src/components/query/loading.tsx          |  23 +-
 .../src/components/query/message-section.tsx  | 205 ++++++++
 .../src/components/query/query-metadata.tsx   |  66 +++
 .../src/components/query/question.tsx         |  16 +-
 .../src/components/query/section-header.tsx   |  13 +
 .../components/query/send-message-dialog.tsx  | 106 ++++
 .../src/components/query/sql-editor.tsx       |  10 +-
 .../src/components/query/verify-select.tsx    |  80 ---
 .../src/components/query/workspace.tsx        | 497 ++++++++----------
 .../src/components/ui/radio-group.tsx         |  42 ++
 .../src/hooks/api/{ => query}/useQueries.ts   |   0
 .../src/hooks/api/{ => query}/useQuery.ts     |   0
 .../api/{ => query}/useQueryExecution.ts      |   2 +-
 .../api/query/useQueryGenerateMessage.ts      |  26 +
 .../hooks/api/{ => query}/useQueryPatch.ts    |  18 +-
 .../hooks/api/query/useQuerySendMessage.ts    |  18 +
 .../admin-console/src/lib/domain/query.ts     |  26 +-
 .../clients/admin-console/src/models/api.ts   |   8 +-
 .../admin-console/src/models/domain.ts        |   5 +-
 .../src/pages/databases/index.tsx             |   2 +-
 .../src/pages/golden-sql/index.tsx            |   2 +-
 .../src/pages/my-account/index.tsx            |   2 +-
 .../src/pages/organization-settings/index.tsx |   2 +-
 .../src/pages/queries/[queryId]/index.tsx     |  53 +-
 .../admin-console/src/pages/queries/index.tsx |   4 +-
 apps/ai/server/app.py                         |   2 +-
 apps/ai/server/config.py                      |   4 +-
 .../1_DH-4875_query_edit_refactor.py          |  21 +
 ...y => 2_DH-4904_replace_llm_credentials.py} |   0
 apps/ai/server/dataherald                     |   2 +-
 .../server/modules/db_connection/service.py   |   8 +-
 .../server/modules/golden_sql/controller.py   |   3 +-
 .../server/modules/golden_sql/repository.py   |  10 +-
 apps/ai/server/modules/golden_sql/service.py  |  23 +-
 apps/ai/server/modules/instruction/service.py |  10 +-
 apps/ai/server/modules/query/controller.py    |  36 +-
 .../server/modules/query/models/entities.py   |  24 +-
 .../server/modules/query/models/requests.py   |   5 +-
 .../server/modules/query/models/responses.py  |  24 +-
 apps/ai/server/modules/query/repository.py    |  20 +-
 apps/ai/server/modules/query/service.py       | 277 +++++-----
 .../modules/table_description/service.py      |  20 +-
 .../tests/golden_sql/test_golden_sql_api.py   |   1 +
 apps/ai/server/tests/query/test_query_api.py  |  54 +-
 apps/ai/server/utils/slack.py                 |  31 +-
 52 files changed, 1181 insertions(+), 716 deletions(-)
 create mode 100644 apps/ai/clients/admin-console/public/images/slack-black.png
 rename apps/ai/clients/admin-console/public/images/{slack-white.png => slack-color.png} (100%)
 rename apps/ai/clients/admin-console/src/components/query/{custom-response-dialog.tsx => custom-message-dialog.tsx} (62%)
 rename apps/ai/clients/admin-console/src/components/query/{loading-sql-results.tsx => loading-box.tsx} (62%)
 create mode 100644 apps/ai/clients/admin-console/src/components/query/message-section.tsx
 create mode 100644 apps/ai/clients/admin-console/src/components/query/query-metadata.tsx
 create mode 100644 apps/ai/clients/admin-console/src/components/query/section-header.tsx
 create mode 100644 apps/ai/clients/admin-console/src/components/query/send-message-dialog.tsx
 delete mode 100644 apps/ai/clients/admin-console/src/components/query/verify-select.tsx
 create mode 100644 apps/ai/clients/admin-console/src/components/ui/radio-group.tsx
 rename apps/ai/clients/admin-console/src/hooks/api/{ => query}/useQueries.ts (100%)
 rename apps/ai/clients/admin-console/src/hooks/api/{ => query}/useQuery.ts (100%)
 rename apps/ai/clients/admin-console/src/hooks/api/{ => query}/useQueryExecution.ts (88%)
 create mode 100644 apps/ai/clients/admin-console/src/hooks/api/query/useQueryGenerateMessage.ts
 rename apps/ai/clients/admin-console/src/hooks/api/{ => query}/useQueryPatch.ts (64%)
 create mode 100644 apps/ai/clients/admin-console/src/hooks/api/query/useQuerySendMessage.ts
 create mode 100644 apps/ai/server/database/migrations/sprint_62/1_DH-4875_query_edit_refactor.py
 rename apps/ai/server/database/migrations/sprint_62/{DH-4904_replace_llm_credentials.py => 2_DH-4904_replace_llm_credentials.py} (100%)

diff --git a/apps/ai/clients/admin-console/package.json b/apps/ai/clients/admin-console/package.json
index 154a6cf9..1d486f92 100644
--- a/apps/ai/clients/admin-console/package.json
+++ b/apps/ai/clients/admin-console/package.json
@@ -20,6 +20,7 @@
     "@radix-ui/react-dialog": "^1.0.4",
     "@radix-ui/react-label": "^2.0.2",
     "@radix-ui/react-popover": "^1.0.6",
+    "@radix-ui/react-radio-group": "^1.1.3",
     "@radix-ui/react-select": "^1.2.2",
     "@radix-ui/react-separator": "^1.0.3",
     "@radix-ui/react-slot": "^1.0.2",
diff --git a/apps/ai/clients/admin-console/pnpm-lock.yaml b/apps/ai/clients/admin-console/pnpm-lock.yaml
index a65cbc41..28de9024 100644
--- a/apps/ai/clients/admin-console/pnpm-lock.yaml
+++ b/apps/ai/clients/admin-console/pnpm-lock.yaml
@@ -29,6 +29,9 @@ dependencies:
   '@radix-ui/react-popover':
     specifier: ^1.0.6
     version: 1.0.6(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
+  '@radix-ui/react-radio-group':
+    specifier: ^1.1.3
+    version: 1.1.3(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
   '@radix-ui/react-select':
     specifier: ^1.2.2
     version: 1.2.2(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
@@ -1418,6 +1421,36 @@ packages:
       react-dom: 18.2.0(react@18.2.0)
     dev: false
 
+  /@radix-ui/react-radio-group@1.1.3(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0):
+    resolution: {integrity: sha512-x+yELayyefNeKeTx4fjK6j99Fs6c4qKm3aY38G3swQVTN6xMpsrbigC0uHs2L//g8q4qR7qOcww8430jJmi2ag==}
+    peerDependencies:
+      '@types/react': '*'
+      '@types/react-dom': '*'
+      react: ^16.8 || ^17.0 || ^18.0
+      react-dom: ^16.8 || ^17.0 || ^18.0
+    peerDependenciesMeta:
+      '@types/react':
+        optional: true
+      '@types/react-dom':
+        optional: true
+    dependencies:
+      '@babel/runtime': 7.22.6
+      '@radix-ui/primitive': 1.0.1
+      '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.2.15)(react@18.2.0)
+      '@radix-ui/react-context': 1.0.1(@types/react@18.2.15)(react@18.2.0)
+      '@radix-ui/react-direction': 1.0.1(@types/react@18.2.15)(react@18.2.0)
+      '@radix-ui/react-presence': 1.0.1(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
+      '@radix-ui/react-primitive': 1.0.3(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
+      '@radix-ui/react-roving-focus': 1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0)
+      '@radix-ui/react-use-controllable-state': 1.0.1(@types/react@18.2.15)(react@18.2.0)
+      '@radix-ui/react-use-previous': 1.0.1(@types/react@18.2.15)(react@18.2.0)
+      '@radix-ui/react-use-size': 1.0.1(@types/react@18.2.15)(react@18.2.0)
+      '@types/react': 18.2.15
+      '@types/react-dom': 18.2.7
+      react: 18.2.0
+      react-dom: 18.2.0(react@18.2.0)
+    dev: false
+
   /@radix-ui/react-roving-focus@1.0.4(@types/react-dom@18.2.7)(@types/react@18.2.15)(react-dom@18.2.0)(react@18.2.0):
     resolution: {integrity: sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==}
     peerDependencies:
diff --git a/apps/ai/clients/admin-console/public/images/slack-black.png b/apps/ai/clients/admin-console/public/images/slack-black.png
new file mode 100644
index 0000000000000000000000000000000000000000..c7b846eb1081d6d28b2cca8f5fb81c38049ca374
GIT binary patch
literal 12831
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
bN!(&>*$#*njs*Xi1HzeD8&{rkzy5y##(`o{

literal 0
HcmV?d00001

diff --git a/apps/ai/clients/admin-console/public/images/slack-white.png b/apps/ai/clients/admin-console/public/images/slack-color.png
similarity index 100%
rename from apps/ai/clients/admin-console/public/images/slack-white.png
rename to apps/ai/clients/admin-console/public/images/slack-color.png
diff --git a/apps/ai/clients/admin-console/src/components/layout/page-layout.tsx b/apps/ai/clients/admin-console/src/components/layout/page-layout.tsx
index bd413fe2..71515bee 100644
--- a/apps/ai/clients/admin-console/src/components/layout/page-layout.tsx
+++ b/apps/ai/clients/admin-console/src/components/layout/page-layout.tsx
@@ -4,19 +4,22 @@ import { Separator } from '@/components/ui/separator'
 import { cn } from '@/lib/utils'
 import { FC, HTMLAttributes } from 'react'
 
-export type PageLayoutProps = HTMLAttributes<HTMLDivElement>
+interface PageLayoutProps extends HTMLAttributes<HTMLDivElement> {
+  disableBreadcrumb?: boolean
+}
 
 const PageLayout: FC<PageLayoutProps> = ({
   className,
   children,
+  disableBreadcrumb = false,
   ...props
 }: PageLayoutProps) => (
   <div className={cn('flex h-screen', className)} {...props}>
     <SidebarNav />
     <div className="w-full h-full overflow-auto flex flex-col">
-      <BreadcrumbHeader />
+      {!disableBreadcrumb && <BreadcrumbHeader />}
       <Separator />
-      <main className="grow flex flex-col overflow-auto p-6">{children}</main>
+      <main className="grow flex flex-col overflow-auto">{children}</main>
     </div>
   </div>
 )
diff --git a/apps/ai/clients/admin-console/src/components/query/custom-response-dialog.tsx b/apps/ai/clients/admin-console/src/components/query/custom-message-dialog.tsx
similarity index 62%
rename from apps/ai/clients/admin-console/src/components/query/custom-response-dialog.tsx
rename to apps/ai/clients/admin-console/src/components/query/custom-message-dialog.tsx
index 3a064164..bbdfa615 100644
--- a/apps/ai/clients/admin-console/src/components/query/custom-response-dialog.tsx
+++ b/apps/ai/clients/admin-console/src/components/query/custom-message-dialog.tsx
@@ -10,63 +10,62 @@ import {
 import {
   Form,
   FormControl,
-  FormDescription,
   FormField,
   FormItem,
   FormMessage,
 } from '@/components/ui/form'
 import { Textarea } from '@/components/ui/textarea'
 import { yupResolver } from '@hookform/resolvers/yup'
-import { Info } from 'lucide-react'
 import { FC, useEffect } from 'react'
 import { useForm } from 'react-hook-form'
 import * as Yup from 'yup'
 
-const CUSTOM_RESPONSE_MAX_LENGTH = 3000
+const CUSTOM_MESSAGE_MAX_LENGTH = 3000
 
-export const customResponseFormSchema = Yup.object({
-  customResponse: Yup.string()
+export const customMessageFormSchema = Yup.object({
+  customMessage: Yup.string()
     .max(
-      CUSTOM_RESPONSE_MAX_LENGTH,
+      CUSTOM_MESSAGE_MAX_LENGTH,
       `The response can't be longer than 3000 characters`,
     )
     .required('Please enter a response for the query'),
 })
 
-type CustomResponseFormValues = Yup.InferType<typeof customResponseFormSchema>
+type CustomMessageFormValues = Yup.InferType<typeof customMessageFormSchema>
 
-interface CustomResponseDialogProps {
+interface CustomMessageDialogProps {
   initialValue: string
   isOpen: boolean
   title: string | JSX.Element
   description: string
-  onClose: (newCustomResponse?: string) => void
+  onClose: (newCustomMessage?: string) => void
 }
 
-const CustomResponseDialog: FC<CustomResponseDialogProps> = ({
+const CustomMessageDialog: FC<CustomMessageDialogProps> = ({
   initialValue,
   isOpen,
   title,
   description,
   onClose,
 }) => {
-  const form = useForm<CustomResponseFormValues>({
-    resolver: yupResolver(customResponseFormSchema),
+  const form = useForm<CustomMessageFormValues>({
+    resolver: yupResolver(customMessageFormSchema),
     defaultValues: {
-      customResponse: initialValue,
+      customMessage: initialValue,
     },
   })
 
   const handleCancel = () => {
+    form.reset({ customMessage: initialValue })
     onClose()
-    form.reset({ customResponse: initialValue })
   }
-  const handleContinue = (formValues: CustomResponseFormValues) => {
-    onClose(formValues.customResponse)
+  const handleContinue = (formValues: CustomMessageFormValues) => {
+    form.reset({ customMessage: initialValue })
+    onClose(formValues.customMessage)
   }
 
   useEffect(
-    () => form.reset({ customResponse: initialValue }),
+    () => form.reset({ customMessage: initialValue }),
     [form, initialValue],
   )
 
@@ -86,17 +85,13 @@ const CustomResponseDialog: FC<CustomResponseDialogProps> = ({
             </DialogHeader>
             <FormField
               control={form.control}
-              name="customResponse"
+              name="customMessage"
               render={({ field }) => (
                 <FormItem>
                   <FormControl>
-                    <Textarea {...field} />
+                    <Textarea {...field} rows={10} />
                   </FormControl>
                   <FormMessage />
-                  <FormDescription className="flex items-start gap-1 pt-2">
-                    <Info size={18} strokeWidth={2}></Info>
-                    {`This message will be sent as the question's response to the Slack thread.`}
-                  </FormDescription>
                 </FormItem>
               )}
             />
@@ -104,7 +99,7 @@ const CustomResponseDialog: FC<CustomResponseDialogProps> = ({
               <Button variant="outline" type="button" onClick={handleCancel}>
                 Cancel
               </Button>
-              <Button type="submit">Done</Button>
+              <Button type="submit">Save</Button>
             </DialogFooter>
           </form>
         </Form>
@@ -112,4 +107,4 @@ const CustomResponseDialog: FC<CustomResponseDialogProps> = ({
     </Dialog>
   )
 }
-export default CustomResponseDialog
+export default CustomMessageDialog
diff --git a/apps/ai/clients/admin-console/src/components/query/loading-sql-results.tsx b/apps/ai/clients/admin-console/src/components/query/loading-box.tsx
similarity index 62%
rename from apps/ai/clients/admin-console/src/components/query/loading-sql-results.tsx
rename to apps/ai/clients/admin-console/src/components/query/loading-box.tsx
index 120dfd30..e98f9a8c 100644
--- a/apps/ai/clients/admin-console/src/components/query/loading-sql-results.tsx
+++ b/apps/ai/clients/admin-console/src/components/query/loading-box.tsx
@@ -2,11 +2,9 @@ import { Skeleton } from '@/components/ui/skeleton'
 import { cn } from '@/lib/utils'
 import { FC, HTMLAttributes } from 'react'
 
-export type LoadingSqlQueryResultsProps = HTMLAttributes<HTMLDivElement>
+export type LoadingBoxProps = HTMLAttributes<HTMLDivElement>
 
-const LoadingSqlQueryResults: FC<LoadingSqlQueryResultsProps> = ({
-  className,
-}) => {
+const LoadingBox: FC<LoadingBoxProps> = ({ className }) => {
   return (
     <div
       className={cn(
@@ -19,4 +17,4 @@ const LoadingSqlQueryResults: FC<LoadingSqlQueryResultsProps> = ({
   )
 }
 
-export default LoadingSqlQueryResults
+export default LoadingBox
diff --git a/apps/ai/clients/admin-console/src/components/query/loading.tsx b/apps/ai/clients/admin-console/src/components/query/loading.tsx
index f77bd43e..10c647ff 100644
--- a/apps/ai/clients/admin-console/src/components/query/loading.tsx
+++ b/apps/ai/clients/admin-console/src/components/query/loading.tsx
@@ -1,19 +1,28 @@
+import { SectionHeader } from '@/components/query/section-header'
 import { Skeleton } from '@/components/ui/skeleton'
 import { FC } from 'react'
 
 const LoadingQuery: FC = () => {
   return (
-    <div className="w-full h-full bg-gray-50 rounded-lg flex flex-col gap-3">
-      <div className="flex justify-between gap-5">
+    <div className="w-full h-full flex flex-col gap-3">
+      <div className="flex justify-between gap-32 p-6">
         <div className="w-2/3 flex flex-col gap-1">
+          <Skeleton className="h-10" />
+          <Skeleton className="h-6" />
+        </div>
+        <div className="w-1/3 flex flex-col gap-1">
+          <Skeleton className="h-10" />
           <Skeleton className="h-6" />
-          <Skeleton className="h-4" />
         </div>
-        <Skeleton className="w-1/3 h-11" />
       </div>
-      <Skeleton className="h-1/2" />
-      <Skeleton className="h-1/2" />
-      <Skeleton className="h-6 w-2/3" />
+      <SectionHeader>
+        <div className="h-10"></div>
+      </SectionHeader>
+      <Skeleton className="h-1/2 mx-6 my-3" />
+      <SectionHeader>
+        <div className="h-10"></div>
+      </SectionHeader>
+      <Skeleton className="h-1/2 mx-6 my-3" />
     </div>
   )
 }
diff --git a/apps/ai/clients/admin-console/src/components/query/message-section.tsx b/apps/ai/clients/admin-console/src/components/query/message-section.tsx
new file mode 100644
index 00000000..1a488250
--- /dev/null
+++ b/apps/ai/clients/admin-console/src/components/query/message-section.tsx
@@ -0,0 +1,205 @@
+import CustomMessageDialog from '@/components/query/custom-message-dialog'
+import LoadingBox from '@/components/query/loading-box'
+import {
+  SectionHeader,
+  SectionHeaderTitle,
+} from '@/components/query/section-header'
+import SendMessageDialog from '@/components/query/send-message-dialog'
+import {
+  MAIN_ACTION_BTN_CLASSES,
+  SECONDARY_ACTION_BTN_CLASSES,
+} from '@/components/query/workspace'
+import {
+  AlertDialog,
+  AlertDialogAction,
+  AlertDialogCancel,
+  AlertDialogContent,
+  AlertDialogDescription,
+  AlertDialogFooter,
+  AlertDialogHeader,
+  AlertDialogTitle,
+  AlertDialogTrigger,
+} from '@/components/ui/alert-dialog'
+import { Button } from '@/components/ui/button'
+import { ToastAction } from '@/components/ui/toast'
+import { toast } from '@/components/ui/use-toast'
+import useQueryGenerateMessage from '@/hooks/api/query/useQueryGenerateMessage'
+import { cn } from '@/lib/utils'
+import { Bot, Edit, Loader } from 'lucide-react'
+import Image from 'next/image'
+import { FC, useState } from 'react'
+
+interface MessageSectionProps {
+  queryId: string
+  initialMessage: string
+  onPatchQuery: (data: { message: string }) => Promise<void>
+}
+
+const MessageSection: FC<MessageSectionProps> = ({
+  queryId,
+  initialMessage,
+  onPatchQuery,
+}) => {
+  const generateMessage = useQueryGenerateMessage()
+
+  const [currentMessage, setCurrentMessage] = useState<string>(initialMessage)
+
+  const [openEditMessageDialog, setOpenEditMessageDialog] = useState(false)
+  const [editingMessage, setEditingMessage] = useState(false)
+  const [generatingMessage, setGeneratingMessage] = useState(false)
+  const handleGenerateMessage = async () => {
+    setGeneratingMessage(true)
+    try {
+      const { message } = await generateMessage(queryId)
+      toast({
+        title: 'Message generated',
+        description: 'The query message was generated using the AI platform.',
+      })
+      setCurrentMessage(message)
+    } catch (error) {
+      console.error(error)
+    } finally {
+      setGeneratingMessage(false)
+    }
+  }
+  const handleCloseEditDialog = async (newCustomMessage?: string) => {
+    setOpenEditMessageDialog(false)
+    if (!newCustomMessage) return
+    setEditingMessage(true)
+    try {
+      await onPatchQuery({
+        message: newCustomMessage,
+      })
+      setCurrentMessage(newCustomMessage)
+      toast({
+        title: 'Message updated',
+        description: 'The query message was updated successfully.',
+      })
+    } catch (error) {
+      console.error(error)
+      toast({
+        variant: 'destructive',
+        title: 'Ups! Something went wrong.',
+        description: 'There was a problem with updating the message.',
+        action: (
+          <ToastAction
+            altText="Try again"
+            onClick={() => handleCloseEditDialog(newCustomMessage)}
+          >
+            Try again
+          </ToastAction>
+        ),
+      })
+    } finally {
+      setEditingMessage(false)
+    }
+  }
+  return (
+    <>
+      <SectionHeader>
+        <SectionHeaderTitle>
+          <Image
+            src="/images/slack-black.png"
+            width={24}
+            height={24}
+            alt="Slack icon"
+          />{' '}
+          Slack message
+        </SectionHeaderTitle>
+        <div className="flex items-center gap-5">
+          <div className="flex items-center gap-1">
+            <Button
+              variant="ghost"
+              type="button"
+              className={cn(
+                MAIN_ACTION_BTN_CLASSES,
+                SECONDARY_ACTION_BTN_CLASSES,
+              )}
+              onClick={() => setOpenEditMessageDialog(true)}
+            >
+              <Edit size={14} strokeWidth={2}></Edit>
+              Edit
+            </Button>
+            <CustomMessageDialog
+              title={
+                <div className="flex items-center gap-2">
+                  <Image
+                    src="/images/slack-color.png"
+                    width={24}
+                    height={24}
+                    alt="Slack icon"
+                  />{' '}
+                  Slack message
+                </div>
+              }
+              description="Compose the question's response message that will be sent to the Slack thread"
+              isOpen={openEditMessageDialog}
+              initialValue={currentMessage}
+              onClose={handleCloseEditDialog}
+            ></CustomMessageDialog>
+            <AlertDialog>
+              <AlertDialogTrigger asChild>
+                <Button
+                  variant="ghost"
+                  type="button"
+                  className={cn(
+                    MAIN_ACTION_BTN_CLASSES,
+                    SECONDARY_ACTION_BTN_CLASSES,
+                  )}
+                >
+                  {generatingMessage ? (
+                    <>
+                      <Loader
+                        className="mr-2 animate-spin"
+                        size={16}
+                        strokeWidth={2.5}
+                      />{' '}
+                      Generating
+                    </>
+                  ) : (
+                    <>
+                      <Bot size={16} strokeWidth={2} />
+                      Generate
+                    </>
+                  )}
+                </Button>
+              </AlertDialogTrigger>
+              <AlertDialogContent>
+                <AlertDialogHeader>
+                  <AlertDialogTitle>
+                    Generate natural language message
+                  </AlertDialogTitle>
+                </AlertDialogHeader>
+                <AlertDialogDescription>
+                  The AI will generate a response based on the last SQL query
+                  run and results table. Make sure to run the correct SQL before
+                  generating.
+                </AlertDialogDescription>
+                <AlertDialogDescription>
+                  Do you wish to continue?
+                </AlertDialogDescription>
+                <AlertDialogFooter>
+                  <AlertDialogCancel>Cancel</AlertDialogCancel>
+                  <AlertDialogAction onClick={handleGenerateMessage}>
+                    <Bot className="mr-2" size={16} strokeWidth={2.5} />
+                    Generate
+                  </AlertDialogAction>
+                </AlertDialogFooter>
+              </AlertDialogContent>
+            </AlertDialog>
+            <SendMessageDialog {...{ queryId }} />
+          </div>
+        </div>
+      </SectionHeader>
+      <div className="h-fit p-6 whitespace-pre-wrap">
+        {editingMessage || generatingMessage ? (
+          <LoadingBox className="h-24" />
+        ) : (
+          currentMessage
+        )}
+      </div>
+    </>
+  )
+}
+
+export default MessageSection
diff --git a/apps/ai/clients/admin-console/src/components/query/query-metadata.tsx b/apps/ai/clients/admin-console/src/components/query/query-metadata.tsx
new file mode 100644
index 00000000..4058bded
--- /dev/null
+++ b/apps/ai/clients/admin-console/src/components/query/query-metadata.tsx
@@ -0,0 +1,66 @@
+import {
+  formatQueryStatusWithScore,
+  getDomainStatus,
+  getDomainStatusColors,
+} from '@/lib/domain/query'
+import { cn } from '@/lib/utils'
+import { QueryStatus } from '@/models/api'
+import { EDomainQueryStatus } from '@/models/domain'
+import { Loader } from 'lucide-react'
+import { FC, HTMLAttributes } from 'react'
+
+export interface QueryMetadataProps extends HTMLAttributes<HTMLDivElement> {
+  queryId: string
+  status: QueryStatus
+  confidenceLevel: number | null
+  updatingQuery: boolean
+  // onResubmit: () => void
+}
+
+const QueryMetadata: FC<QueryMetadataProps> = ({
+  queryId,
+  status,
+  confidenceLevel,
+  updatingQuery,
+  // onResubmit,
+  className,
+}) => {
+  const textColor = getDomainStatusColors(status, confidenceLevel).text
+  const domainStatus = getDomainStatus(status, confidenceLevel)
+  const statusText = formatQueryStatusWithScore(domainStatus, confidenceLevel)
+  const isFromAI = [
+    EDomainQueryStatus.LOW_CONFIDENCE.valueOf(),
+    EDomainQueryStatus.MEDIUM_CONFIDENCE.valueOf(),
+    EDomainQueryStatus.HIGH_CONFIDENCE.valueOf(),
+  ].includes(domainStatus as EDomainQueryStatus)
+  return (
+    <div className={cn('flex flex-col gap-1 items-end', className)}>
+      <div className="flex items-center gap-2">
+        {/* <Button
+          variant="ghost"
+          className="flex items-center gap-2 h-9"
+          onClick={onResubmit}
+        >
+          <Boxes /> Resubmit
+        </Button> */}
+        <h1 className="text-xl font-bold">{queryId}</h1>
+      </div>
+      <div
+        className={cn(textColor, 'flex flex-row items-center font-semibold')}
+      >
+        {updatingQuery ? (
+          <div className="text-slate-500 flex items-center gap-2">
+            <Loader className="animate-spin" size={20} /> Updating query...
+          </div>
+        ) : (
+          <>
+            <div className="w-2 h-2 mr-2 rounded-full bg-current shrink-0" />
+            {isFromAI ? `Not Verified - ` : ''} {statusText}
+          </>
+        )}
+      </div>
+    </div>
+  )
+}
+
+export default QueryMetadata
diff --git a/apps/ai/clients/admin-console/src/components/query/question.tsx b/apps/ai/clients/admin-console/src/components/query/question.tsx
index 8245e27d..5d374d9d 100644
--- a/apps/ai/clients/admin-console/src/components/query/question.tsx
+++ b/apps/ai/clients/admin-console/src/components/query/question.tsx
@@ -1,8 +1,9 @@
+import { cn } from '@/lib/utils'
 import { format } from 'date-fns'
 import { Calendar, Clock, User2 } from 'lucide-react'
-import { FC } from 'react'
+import { FC, HTMLAttributes } from 'react'
 
-export interface QueryQuestionProps {
+export interface QueryQuestionProps extends HTMLAttributes<HTMLDivElement> {
   username: string
   question: string
   questionDate: Date
@@ -12,21 +13,22 @@ const QueryQuestion: FC<QueryQuestionProps> = ({
   username,
   question,
   questionDate,
+  className,
 }) => (
-  <div>
-    <h1 className="mb-1 font-bold">{question}</h1>
-    <h3 className="flex gap-5">
+  <div className={cn('flex flex-col gap-2', className)}>
+    <h1 className="text-xl font-bold first-letter:capitalize">{question}</h1>
+    <div className="flex gap-5">
       {[
         { icon: User2, text: username },
         { icon: Calendar, text: format(questionDate, 'MMMM dd, yyyy') },
         { icon: Clock, text: format(questionDate, 'hh:mm a') },
       ].map((item, index) => (
-        <div key={index} className="flex items-center gap-1">
+        <div key={index} className="flex items-center gap-2 text-sm">
           <item.icon size={16} />
           <span>{item.text}</span>
         </div>
       ))}
-    </h3>
+    </div>
   </div>
 )
 
diff --git a/apps/ai/clients/admin-console/src/components/query/section-header.tsx b/apps/ai/clients/admin-console/src/components/query/section-header.tsx
new file mode 100644
index 00000000..619679ea
--- /dev/null
+++ b/apps/ai/clients/admin-console/src/components/query/section-header.tsx
@@ -0,0 +1,13 @@
+import { FC, ReactNode } from 'react'
+
+export const SectionHeader: FC<{ children: ReactNode }> = ({ children }) => (
+  <div className="bg-slate-200 w-full px-6 py-3 flex items-center justify-between gap-2">
+    {children}
+  </div>
+)
+
+export const SectionHeaderTitle: FC<{ children: ReactNode }> = ({
+  children,
+}) => (
+  <div className="flex items-center gap-3 font-bold text-lg">{children}</div>
+)
diff --git a/apps/ai/clients/admin-console/src/components/query/send-message-dialog.tsx b/apps/ai/clients/admin-console/src/components/query/send-message-dialog.tsx
new file mode 100644
index 00000000..d173d8de
--- /dev/null
+++ b/apps/ai/clients/admin-console/src/components/query/send-message-dialog.tsx
@@ -0,0 +1,106 @@
+import { MAIN_ACTION_BTN_CLASSES } from '@/components/query/workspace'
+import {
+  AlertDialog,
+  AlertDialogAction,
+  AlertDialogCancel,
+  AlertDialogContent,
+  AlertDialogDescription,
+  AlertDialogFooter,
+  AlertDialogHeader,
+  AlertDialogTitle,
+  AlertDialogTrigger,
+} from '@/components/ui/alert-dialog'
+import { Button } from '@/components/ui/button'
+import { ToastAction } from '@/components/ui/toast'
+import { toast } from '@/components/ui/use-toast'
+import useQuerySendMessage from '@/hooks/api/query/useQuerySendMessage'
+import { cn } from '@/lib/utils'
+import { Loader, Send } from 'lucide-react'
+import { FC, useState } from 'react'
+
+interface SendMessageDialogProps {
+  queryId: string
+}
+
+const SendMessageDialog: FC<SendMessageDialogProps> = ({ queryId }) => {
+  const sendMessage = useQuerySendMessage()
+  const [sendingMessage, setSendingMessage] = useState(false)
+  const handleSendMessage = async () => {
+    try {
+      setSendingMessage(true)
+      await sendMessage(queryId)
+      toast({
+        variant: 'success',
+        title: 'Message sent',
+        description: 'The query message was sent to the Slack thread.',
+      })
+    } catch (error) {
+      console.error(error)
+      toast({
+        variant: 'destructive',
+        title: 'Ups! Something went wrong.',
+        description: 'There was a problem with sending the message.',
+        action: (
+          <ToastAction altText="Try again" onClick={handleSendMessage}>
+            Try again
+          </ToastAction>
+        ),
+      })
+    } finally {
+      setSendingMessage(false)
+    }
+  }
+  return (
+    <AlertDialog>
+      <AlertDialogTrigger asChild>
+        <Button
+          disabled={sendingMessage}
+          className={cn(
+            MAIN_ACTION_BTN_CLASSES,
+            'bg-green-600 hover:bg-green-500',
+          )}
+        >
+          {sendingMessage ? (
+            <>
+              <Loader
+                className="mr-2 animate-spin"
+                size={16}
+                strokeWidth={2.5}
+              />{' '}
+              Sending
+            </>
+          ) : (
+            <>
+              <Send className="mr-2" size={16} strokeWidth={2.5} />
+              Send
+            </>
+          )}
+        </Button>
+      </AlertDialogTrigger>
+      <AlertDialogContent>
+        <AlertDialogHeader>
+          <AlertDialogTitle>Send Slack message?</AlertDialogTitle>
+        </AlertDialogHeader>
+        <AlertDialogDescription>
+          This will send the current message to the original question’s slack
+          thread and cannot be undone.
+        </AlertDialogDescription>
+        <AlertDialogDescription>
+          Do you wish to continue?
+        </AlertDialogDescription>
+        <AlertDialogFooter>
+          <AlertDialogCancel>Cancel</AlertDialogCancel>
+          <AlertDialogAction
+            className="bg-green-600 hover:bg-green-500"
+            onClick={handleSendMessage}
+          >
+            <Send className="mr-2" size={16} strokeWidth={2.5} />
+            Send
+          </AlertDialogAction>
+        </AlertDialogFooter>
+      </AlertDialogContent>
+    </AlertDialog>
+  )
+}
+
+export default SendMessageDialog
diff --git a/apps/ai/clients/admin-console/src/components/query/sql-editor.tsx b/apps/ai/clients/admin-console/src/components/query/sql-editor.tsx
index 74bab007..8768e6b1 100644
--- a/apps/ai/clients/admin-console/src/components/query/sql-editor.tsx
+++ b/apps/ai/clients/admin-console/src/components/query/sql-editor.tsx
@@ -8,10 +8,15 @@ const Editor = dynamic(() => import('@monaco-editor/react'), {
 
 export interface SqlEditorProps {
   initialQuery: string
+  disabled?: boolean
   onValueChange: (value: string) => void
 }
 
-const SqlEditor: FC<SqlEditorProps> = ({ initialQuery, onValueChange }) => {
+const SqlEditor: FC<SqlEditorProps> = ({
+  initialQuery,
+  onValueChange,
+  disabled = false,
+}) => {
   const handleEditorChange = (value: string | undefined): void => {
     onValueChange(value || '')
   }
@@ -57,10 +62,11 @@ const SqlEditor: FC<SqlEditorProps> = ({ initialQuery, onValueChange }) => {
       defaultValue={initialQuery}
       language="sql"
       options={{
+        readOnly: disabled,
         lineHeight: 1.5,
         scrollBeyondLastLine: false,
         lineNumbersMinChars: 0,
-        renderLineHighlight: 'gutter',
+        renderLineHighlight: disabled ? 'none' : 'gutter',
         scrollbar: {
           useShadows: true,
           arrowSize: 0,
diff --git a/apps/ai/clients/admin-console/src/components/query/verify-select.tsx b/apps/ai/clients/admin-console/src/components/query/verify-select.tsx
deleted file mode 100644
index adc889a8..00000000
--- a/apps/ai/clients/admin-console/src/components/query/verify-select.tsx
+++ /dev/null
@@ -1,80 +0,0 @@
-import {
-  Select,
-  SelectContent,
-  SelectItem,
-  SelectTrigger,
-  SelectValue,
-} from '@/components/ui/select'
-import {
-  QUERY_STATUS_COLORS,
-  formatQueryStatus,
-  isNotVerified,
-  isRejected,
-  isVerified,
-} from '@/lib/domain/query'
-import { cn } from '@/lib/utils'
-import {
-  EDomainQueryWorkspaceStatus,
-  QueryWorkspaceStatus,
-} from '@/models/domain'
-import { Ban, CheckCircle, XCircle } from 'lucide-react'
-import { FC, useCallback } from 'react'
-
-export interface QueryVerifySelectProps {
-  verificationStatus: QueryWorkspaceStatus
-  onValueChange: (value: QueryWorkspaceStatus) => void
-}
-
-const QueryVerifySelect: FC<QueryVerifySelectProps> = ({
-  verificationStatus,
-  onValueChange,
-}) => {
-  const handleValueChange = (value: QueryWorkspaceStatus) => {
-    onValueChange(value)
-  }
-
-  const getStatusDisplay = useCallback(
-    (status: QueryWorkspaceStatus) => (
-      <div
-        className={cn(
-          'flex items-center gap-3 font-semibold text-base',
-          QUERY_STATUS_COLORS[status].text,
-        )}
-      >
-        {isVerified(status) && <CheckCircle size={20} strokeWidth={2.5} />}
-        {isNotVerified(status) && <XCircle size={20} strokeWidth={2.5} />}
-        {isRejected(status) && <Ban size={20} strokeWidth={3} />}
-        {formatQueryStatus(status)}
-      </div>
-    ),
-    [],
-  )
-
-  return (
-    <Select onValueChange={handleValueChange}>
-      <SelectTrigger
-        className={cn(
-          'w-[180px]',
-          QUERY_STATUS_COLORS[verificationStatus].border,
-        )}
-      >
-        <SelectValue placeholder={getStatusDisplay(verificationStatus)} />
-      </SelectTrigger>
-      <SelectContent>
-        {Object.values(EDomainQueryWorkspaceStatus).map(
-          (qs: QueryWorkspaceStatus, idx) => (
-            <SelectItem
-              key={qs + idx}
-              value={qs}
-              className={`focus:${QUERY_STATUS_COLORS[qs].background}`}
-            >
-              {getStatusDisplay(qs)}
-            </SelectItem>
-          ),
-        )}
-      </SelectContent>
-    </Select>
-  )
-}
-
-export default QueryVerifySelect
diff --git a/apps/ai/clients/admin-console/src/components/query/workspace.tsx b/apps/ai/clients/admin-console/src/components/query/workspace.tsx
index 295afb4d..5b23ba73 100644
--- a/apps/ai/clients/admin-console/src/components/query/workspace.tsx
+++ b/apps/ai/clients/admin-console/src/components/query/workspace.tsx
@@ -1,54 +1,46 @@
-import CustomResponseDialog from '@/components/query/custom-response-dialog'
 import QueryLastUpdated from '@/components/query/last-updated'
-import LoadingSqlQueryResults from '@/components/query/loading-sql-results'
-import QueryProcess from '@/components/query/process'
+import LoadingBox from '@/components/query/loading-box'
+import MessageSection from '@/components/query/message-section'
+import QueryMetadata from '@/components/query/query-metadata'
 import QueryQuestion from '@/components/query/question'
+import {
+  SectionHeader,
+  SectionHeaderTitle,
+} from '@/components/query/section-header'
 import SqlEditor from '@/components/query/sql-editor'
 import SqlResultsTable from '@/components/query/sql-results-table'
-import QueryVerifySelect from '@/components/query/verify-select'
-import { Alert, AlertDescription } from '@/components/ui/alert'
 import { Button } from '@/components/ui/button'
-import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
+import { Label } from '@/components/ui/label'
+import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
 import { ToastAction } from '@/components/ui/toast'
 import { Toaster } from '@/components/ui/toaster'
 import { useToast } from '@/components/ui/use-toast'
+import { QueryPatchRequest } from '@/hooks/api/query/useQueryPatch'
 import {
-  QUERY_STATUS_BUTTONS_CLASSES,
+  QUERY_STATUS_COLORS,
+  QUERY_STATUS_EXPLANATION,
+  formatQueryStatus,
   isNotVerified,
   isRejected,
-  isSqlError,
   isVerified,
 } from '@/lib/domain/query'
 import { cn } from '@/lib/utils'
-import { Query, QueryStatus } from '@/models/api'
+import { Query } from '@/models/api'
 import {
   EDomainQueryWorkspaceStatus,
   QueryWorkspaceStatus,
 } from '@/models/domain'
-import {
-  AlertCircle,
-  Ban,
-  Database,
-  Edit,
-  ListOrdered,
-  Loader,
-  Play,
-  Save,
-  Send,
-  XOctagon,
-} from 'lucide-react'
-import Image from 'next/image'
-import Link from 'next/link'
-import { FC, useEffect, useState } from 'react'
+import { Ban, Box, Code2, Loader, Play, Verified, XOctagon } from 'lucide-react'
+import { FC, useState } from 'react'
+
+export const MAIN_ACTION_BTN_CLASSES = 'h-8 py-0 px-4 w-28'
+export const SECONDARY_ACTION_BTN_CLASSES =
+  'w-fit px-4 text-sm hover:bg-slate-300 hover:text-black/80 flex items-center gap-1'
 
 export interface QueryWorkspaceProps {
   query: Query
-  onExecuteQuery: (sql_query: string) => void
-  onPatchQuery: (patches: {
-    sql_query: string
-    custom_response: string
-    query_status: QueryStatus
-  }) => void
+  onExecuteQuery: (sql_query: string) => Promise<void>
+  onPatchQuery: (patches: QueryPatchRequest) => Promise<void>
 }
 
 const QueryWorkspace: FC<QueryWorkspaceProps> = ({
@@ -57,48 +49,52 @@ const QueryWorkspace: FC<QueryWorkspaceProps> = ({
   onPatchQuery,
 }) => {
   const {
-    id,
+    id: queryId,
+    display_id,
     question,
     question_date,
-    response,
+    response, // TODO delete this
+    message,
     username,
     sql_query,
     sql_query_result,
     sql_error_message,
+    evaluation_score,
     status,
-    ai_process,
     last_updated,
     updated_by,
   } = query
 
   const questionDate: Date = new Date(question_date)
   const lastUpdatedDate: Date = new Date(last_updated)
+
   const [currentSqlQuery, setCurrentSqlQuery] = useState(sql_query)
-  const [verificationStatus, setVerifiedStatus] = useState<QueryStatus>(status)
-  const [customResponse, setCustomResponse] = useState<string>(response)
-  const [customResponseHasChanges, setcustomResponseHasChanges] =
-    useState(false)
-  const [openEditResponseDialog, setOpenEditResponseDialog] = useState(false)
-  const [savingQuery, setSavingQuery] = useState(false)
-  const [loadingSqlQueryResults, setLoadingQueryResults] = useState(false)
+  const [currentQueryStatus, setCurrentQueryStatus] =
+    useState<EDomainQueryWorkspaceStatus>(
+      Object.values(EDomainQueryWorkspaceStatus).find((qs) => qs === status) ||
+        EDomainQueryWorkspaceStatus.NOT_VERIFIED,
+    )
+
+  const [runningQuery, setRunningQuery] = useState(false)
+  const [updatingQueryStatus, setUpdatingQueryStatus] = useState(false)
 
   const { toast } = useToast()
 
   const handleRunQuery = async () => {
-    setLoadingQueryResults(true)
+    setRunningQuery(true)
     try {
       await onExecuteQuery(currentSqlQuery)
       toast({
-        title: 'Query executed',
+        title: 'Query updated',
         description:
-          'The query was executed successfully. Results and natural language response updated.',
+          'The query was executed successfully and the results were updated.',
       })
     } catch (e) {
       console.error(e)
       toast({
         variant: 'destructive',
         title: 'Ups! Something went wrong.',
-        description: 'There was a problem with running your query',
+        description: 'There was a problem with running the query',
         action: (
           <ToastAction altText="Try again" onClick={handleRunQuery}>
             Try again
@@ -106,52 +102,57 @@ const QueryWorkspace: FC<QueryWorkspaceProps> = ({
         ),
       })
     } finally {
-      setLoadingQueryResults(false)
+      setRunningQuery(false)
     }
   }
 
-  const handleSaveQuery = async () => {
+  const updateQueryStatus = async (newStatus: EDomainQueryWorkspaceStatus) => {
+    if (updatingQueryStatus) return
+    setUpdatingQueryStatus(true)
     try {
-      setSavingQuery(true)
       await onPatchQuery({
-        query_status: verificationStatus,
-        custom_response: customResponse,
-        sql_query: currentSqlQuery,
+        query_status: newStatus,
       })
-      if (isVerified(verificationStatus)) {
+      if (isVerified(newStatus)) {
         toast({
           variant: 'success',
           title: 'Query Verified',
           description:
-            'Response sent to the Slack thread and added to the Golden SQL training set.',
+            'Query added to the Golden SQL training set and used to further train the model for future queries.',
         })
-      } else if (isNotVerified(verificationStatus)) {
+      } else if (isNotVerified(newStatus)) {
         toast({
           title: 'Query Unverified',
-          description: 'The query is not part of the Golden SQL training set.',
+          description:
+            'The query is not part of the Golden SQL training set and not used to improve the platform accuracy.',
         })
-      } else if (isRejected(verificationStatus)) {
+      } else if (isRejected(newStatus)) {
         toast({
           variant: 'destructive-outline',
           title: 'Query Rejected',
           description:
-            'Response sent to the Slack thread informing that this query could not be answered.',
+            'The query is marked as rejected and will not be used to improve the platform accuracy.',
         })
       }
+      setCurrentQueryStatus(newStatus)
     } catch (e) {
       console.error(e)
+      setCurrentQueryStatus(status as EDomainQueryWorkspaceStatus)
       toast({
         variant: 'destructive',
         title: 'Ups! Something went wrong.',
-        description: 'There was a problem with saving your query',
+        description: 'There was a problem with updating the query status',
         action: (
-          <ToastAction altText="Try again" onClick={handleSaveQuery}>
+          <ToastAction
+            altText="Try again"
+            onClick={() => updateQueryStatus(newStatus)}
+          >
             Try again
           </ToastAction>
         ),
       })
     } finally {
-      setSavingQuery(false)
+      setUpdatingQueryStatus(false)
     }
   }
 
@@ -159,227 +160,118 @@ const QueryWorkspace: FC<QueryWorkspaceProps> = ({
     setCurrentSqlQuery(value)
   }
 
-  const handleVerifyChange = (verificationStatus: QueryWorkspaceStatus) => {
-    setVerifiedStatus(verificationStatus)
-    if (isRejected(verificationStatus) && !customResponseHasChanges) {
-      setOpenEditResponseDialog(true)
-    }
-  }
-
-  const handleCloseEditDialog = (newCustomResponse = customResponse) => {
-    setCustomResponse(newCustomResponse)
-    setOpenEditResponseDialog(false)
+  const handleQueryStatusChange = (value: EDomainQueryWorkspaceStatus) => {
+    setCurrentQueryStatus(value)
+    updateQueryStatus(value)
   }
 
-  useEffect(() => {
-    setcustomResponseHasChanges(customResponse !== query.response)
-  }, [query.response, customResponse])
-
-  useEffect(() => {
-    setCustomResponse(query.response)
-  }, [query])
-
-  const rejectedBanner = (
-    <div className="h-full flex items-center justify-center gap-2 text-muted-foreground">
-      <Ban size={18} strokeWidth={2} /> Rejected query
-    </div>
-  )
+  // TODO implement
+  // const handleResubmit = async () => {
+  //   console.log('resubmitting query')
+  // }
 
   return (
     <>
       <div
-        className="grow flex flex-col gap-5"
-        data-ph-capture-attribute-query_id={id}
+        className="grow flex flex-col gap-3 mt-4 overflow-auto"
+        data-ph-capture-attribute-query_id={queryId}
         data-ph-capture-attribute-asker={username}
       >
-        <div id="header" className="flex justify-between gap-3">
-          <QueryQuestion {...{ username, question, questionDate }} />
-          <div className="flex items-center self-start gap-5 min-w-fit">
-            <Link href="/queries">
-              <Button variant="link" className="font-normal">
-                Cancel
-              </Button>
-            </Link>
-            <Button
-              className={cn(QUERY_STATUS_BUTTONS_CLASSES[verificationStatus])}
-              onClick={handleSaveQuery}
-              disabled={savingQuery}
-            >
-              {savingQuery ? (
-                <>
-                  <Loader
-                    className="mr-2 animate-spin"
-                    size={20}
-                    strokeWidth={2.5}
-                  />{' '}
-                  Saving
-                </>
-              ) : (
-                <>
-                  {isVerified(verificationStatus) && (
-                    <>
-                      <Send className="mr-2" size={20} strokeWidth={2.5} />
-                      Save and Send
-                    </>
-                  )}
-                  {(isNotVerified(verificationStatus) ||
-                    isSqlError(verificationStatus)) && (
-                    <>
-                      <Save className="mr-2" size={20} strokeWidth={2.5} />
-                      Save
-                    </>
-                  )}
-                  {isRejected(verificationStatus) && (
-                    <>
-                      <Send className="mr-2" size={20} strokeWidth={2.5} />
-                      Save and Send
-                    </>
-                  )}
-                </>
-              )}
-            </Button>
-          </div>
+        <div id="header" className="flex items-end justify-between gap-3 px-6">
+          <QueryQuestion
+            className="max-w-2xl"
+            {...{ username, question, questionDate }}
+          />
+          <QueryMetadata
+            {...{
+              queryId: display_id,
+              status,
+              updatingQuery: runningQuery || updatingQueryStatus,
+              confidenceLevel: evaluation_score,
+              // onResubmit: handleResubmit,
+            }}
+          />
         </div>
-        {loadingSqlQueryResults ? (
-          <div className="shrink-0 h-24">
-            <LoadingSqlQueryResults />
-          </div>
-        ) : (
-          customResponse && (
-            <div className="bg-white flex flex-col px-5 pt-3 pb-5 rounded-xl border">
-              <div className="flex items-center justify-between gap-3">
-                <div className="flex items-center gap-2">
-                  <Image
-                    src="/images/slack-white.png"
-                    width={16}
-                    height={16}
-                    alt="Slack icon"
-                  />
-                  <div className="font-bold mr-1">Slack response</div>
-                </div>
-                <Button
-                  variant="link"
-                  className="font-normal text-black flex items-center gap-1"
-                  onClick={() => setOpenEditResponseDialog(true)}
-                >
-                  <Edit size={18} strokeWidth={2}></Edit>
-                  Edit
-                </Button>
+        <div className="grow flex flex-col overflow-auto">
+          <SectionHeader>
+            <SectionHeaderTitle>
+              <Code2 strokeWidth={2}></Code2>
+              {isNotVerified(currentQueryStatus) ? 'Verify SQL' : 'SQL'}
+            </SectionHeaderTitle>
+            {isNotVerified(currentQueryStatus) && (
+              <Button
+                onClick={handleRunQuery}
+                disabled={runningQuery || updatingQueryStatus}
+                className={cn(MAIN_ACTION_BTN_CLASSES)}
+              >
+                {runningQuery ? (
+                  <>
+                    <Loader
+                      className="mr-2 animate-spin"
+                      size={16}
+                      strokeWidth={2.5}
+                    />{' '}
+                    Running
+                  </>
+                ) : (
+                  <>
+                    <Play className="mr-2" size={16} strokeWidth={2.5} />
+                    Run
+                  </>
+                )}
+              </Button>
+            )}
+          </SectionHeader>
+          <div className="grow flex flex-col gap-2 px-6 py-4">
+            <div className="grow h-44">
+              <SqlEditor
+                disabled={isVerified(currentQueryStatus)}
+                initialQuery={currentSqlQuery}
+                onValueChange={handleSqlChange}
+              />
+            </div>
+            <QueryLastUpdated
+              responsible={updated_by?.name as string}
+              date={lastUpdatedDate}
+            />
+            {runningQuery || updatingQueryStatus ? (
+              <div id="loading_query_results" className="shrink-0 h-32">
+                <LoadingBox />
               </div>
-              <div className="break-words">{customResponse}</div>
-              {(isVerified(verificationStatus) ||
-                isRejected(verificationStatus)) && (
-                <Alert
-                  variant="info"
-                  className="flex items-center gap-2 mt-3 w-fit"
-                >
-                  <div>
-                    <AlertCircle size={18} />
+            ) : isVerified(currentQueryStatus) ? (
+              <div
+                id="verified_banner"
+                className="shrink-0 h-32 flex flex-col border bg-muted text-muted-foreground"
+              >
+                <div className="h-full flex flex-col items-center justify-center gap-2">
+                  <div className="flex items-center gap-2 text-green-700">
+                    <Verified size={18} strokeWidth={2} /> Verified query
+                  </div>
+                  <div className="px-20 text-center">
+                    {`The SQL query was verified and added to the Golden SQL training set. To modify the SQL query, please set the status to "Not Verified" first.`}
                   </div>
-                  <AlertDescription>
-                    {`This message will be sent as the question's response to
-                      the Slack thread each time you save.`}
-                  </AlertDescription>
-                </Alert>
-              )}
-            </div>
-          )
-        )}
-        <div
-          id="tabs"
-          className="shrink-0 h-80 grow flex-auto flex flex-col gap-5 bg-white border rounded-xl px-6 py-4"
-        >
-          <Tabs
-            defaultValue="sql"
-            className="w-full grow overflow-auto flex flex-col"
-          >
-            <TabsList className="w-full">
-              <div className="w-full flex gap-3 justify-between py-2">
-                <div id="tab-triggers" className="flex gap-5">
-                  <TabsTrigger value="sql">
-                    <Database className="mr-2" size={20} strokeWidth={2.5} />{' '}
-                    SQL
-                  </TabsTrigger>
-                  <TabsTrigger value="process">
-                    <ListOrdered className="mr-2" size={20} strokeWidth={2.5} />
-                    Process
-                  </TabsTrigger>
                 </div>
-                <div id="actions" className="flex items-center gap-5">
-                  <span className="text-lg">Mark as </span>
-                  <QueryVerifySelect
-                    verificationStatus={
-                      isSqlError(verificationStatus)
-                        ? EDomainQueryWorkspaceStatus.NOT_VERIFIED
-                        : (verificationStatus as EDomainQueryWorkspaceStatus)
-                    }
-                    onValueChange={handleVerifyChange}
-                  />
-                  <Button
-                    onClick={handleRunQuery}
-                    disabled={
-                      loadingSqlQueryResults || isRejected(verificationStatus)
-                    }
-                  >
-                    {loadingSqlQueryResults ? (
-                      <>
-                        <Loader
-                          className="mr-2 animate-spin"
-                          size={20}
-                          strokeWidth={2.5}
-                        />{' '}
-                        Running
-                      </>
-                    ) : (
-                      <>
-                        <Play className="mr-2" size={20} strokeWidth={2.5} />
-                        Run
-                      </>
-                    )}
-                  </Button>
+              </div>
+            ) : isRejected(currentQueryStatus) ? (
+              <div
+                id="rejected__banner"
+                className="shrink-0 h-32 flex flex-col border bg-muted text-red-500"
+              >
+                <div className="h-full flex items-center justify-center gap-2 ">
+                  <Ban size={18} strokeWidth={2} /> Rejected query
                 </div>
               </div>
-            </TabsList>
-            <TabsContent value="sql" className="pt-3 grow">
-              {isRejected(verificationStatus) ? (
-                rejectedBanner
-              ) : (
-                <SqlEditor
-                  initialQuery={currentSqlQuery}
-                  onValueChange={handleSqlChange}
-                />
-              )}
-            </TabsContent>
-            <TabsContent value="process" className="pt-3 grow overflow-auto">
-              {isRejected(verificationStatus) ? (
-                rejectedBanner
-              ) : (
-                <QueryProcess processSteps={ai_process} />
-              )}
-            </TabsContent>
-          </Tabs>
-          <QueryLastUpdated
-            responsible={updated_by?.name as string}
-            date={lastUpdatedDate}
-          />
-        </div>
-        {loadingSqlQueryResults ? (
-          <div className="shrink-0 h-32">
-            <LoadingSqlQueryResults />
-          </div>
-        ) : sql_error_message ? (
-          <div className="shrink-0 h-60 flex flex-col items-center bg-white border border-red-600 text-red-600">
-            <div className="flex items-center gap-3 py-5 font-bold">
-              <XOctagon size={28} />
-              <span>SQL Error</span>
-            </div>
-            <div className="w-full overflow-auto px-8 pb-3">
-              {sql_error_message}
-            </div>
-          </div>
-        ) : (
-          <>
-            {!isRejected(verificationStatus) && (
+            ) : sql_error_message ? (
+              <div className="shrink-0 h-32 flex flex-col items-center border bg-white border-red-600 text-red-600">
+                <div className="flex items-center gap-3 py-5 font-bold">
+                  <XOctagon size={28} />
+                  <span>SQL Error</span>
+                </div>
+                <div className="w-full overflow-auto px-8 pb-3">
+                  {sql_error_message}
+                </div>
+              </div>
+            ) : (
               <div
                 id="query_results"
                 className="min-h-[10rem] max-h-80 flex flex-col border bg-white"
@@ -402,26 +294,61 @@ const QueryWorkspace: FC<QueryWorkspaceProps> = ({
                 )}
               </div>
             )}
-          </>
-        )}
-      </div>
-      <CustomResponseDialog
-        title={
-          <div className="flex items-center gap-2">
-            <Image
-              src="/images/slack-white.png"
-              width={20}
-              height={20}
-              alt="Slack icon"
-            />{' '}
-            Slack response
           </div>
-        }
-        description="Compose the question's response message that will be sent to the Slack thread"
-        isOpen={openEditResponseDialog}
-        initialValue={customResponse}
-        onClose={handleCloseEditDialog}
-      ></CustomResponseDialog>
+          <MessageSection
+            {...{ queryId, initialMessage: message || response, onPatchQuery }}
+          />
+          <SectionHeader>
+            <SectionHeaderTitle>
+              <Box strokeWidth={2}></Box>Query Status
+            </SectionHeaderTitle>
+          </SectionHeader>
+          <div className="p-6 flex flex-col gap-5">
+            <RadioGroup
+              disabled={runningQuery || updatingQueryStatus}
+              className="space-y-1"
+              value={currentQueryStatus}
+              onValueChange={handleQueryStatusChange}
+            >
+              {Object.values(EDomainQueryWorkspaceStatus).map(
+                (qs: QueryWorkspaceStatus, idx) => (
+                  <div
+                    key={qs + idx}
+                    className={cn(
+                      'flex items-center space-x-2',
+                      QUERY_STATUS_COLORS[qs].text,
+                      qs === currentQueryStatus && 'font-bold',
+                    )}
+                  >
+                    <RadioGroupItem
+                      value={qs}
+                      id={qs}
+                      className={cn(
+                        QUERY_STATUS_COLORS[qs].text,
+                        QUERY_STATUS_COLORS[qs].border,
+                      )}
+                    />
+                    <Label
+                      htmlFor={qs}
+                      className={cn(
+                        'tracking-wide text-base',
+                        runningQuery || updatingQueryStatus
+                          ? ''
+                          : 'cursor-pointer',
+                      )}
+                    >
+                      {formatQueryStatus(qs)}{' '}
+                      <span className="ml-2 text-xs text-slate-400">
+                        {QUERY_STATUS_EXPLANATION[qs]}
+                      </span>
+                    </Label>
+                  </div>
+                ),
+              )}
+            </RadioGroup>
+          </div>
+        </div>
+      </div>
       <Toaster />
     </>
   )
diff --git a/apps/ai/clients/admin-console/src/components/ui/radio-group.tsx b/apps/ai/clients/admin-console/src/components/ui/radio-group.tsx
new file mode 100644
index 00000000..d2b3f09f
--- /dev/null
+++ b/apps/ai/clients/admin-console/src/components/ui/radio-group.tsx
@@ -0,0 +1,42 @@
+import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'
+import { Circle } from 'lucide-react'
+import * as React from 'react'
+
+import { cn } from '@/lib/utils'
+
+const RadioGroup = React.forwardRef<
+  React.ElementRef<typeof RadioGroupPrimitive.Root>,
+  React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
+>(({ className, ...props }, ref) => {
+  return (
+    <RadioGroupPrimitive.Root
+      className={cn('grid gap-2', className)}
+      {...props}
+      ref={ref}
+    />
+  )
+})
+RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
+
+const RadioGroupItem = React.forwardRef<
+  React.ElementRef<typeof RadioGroupPrimitive.Item>,
+  React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
+>(({ className, ...props }, ref) => {
+  return (
+    <RadioGroupPrimitive.Item
+      ref={ref}
+      className={cn(
+        'aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
+        className,
+      )}
+      {...props}
+    >
+      <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
+        <Circle className="h-2.5 w-2.5 fill-current text-current" />
+      </RadioGroupPrimitive.Indicator>
+    </RadioGroupPrimitive.Item>
+  )
+})
+RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
+
+export { RadioGroup, RadioGroupItem }
diff --git a/apps/ai/clients/admin-console/src/hooks/api/useQueries.ts b/apps/ai/clients/admin-console/src/hooks/api/query/useQueries.ts
similarity index 100%
rename from apps/ai/clients/admin-console/src/hooks/api/useQueries.ts
rename to apps/ai/clients/admin-console/src/hooks/api/query/useQueries.ts
diff --git a/apps/ai/clients/admin-console/src/hooks/api/useQuery.ts b/apps/ai/clients/admin-console/src/hooks/api/query/useQuery.ts
similarity index 100%
rename from apps/ai/clients/admin-console/src/hooks/api/useQuery.ts
rename to apps/ai/clients/admin-console/src/hooks/api/query/useQuery.ts
diff --git a/apps/ai/clients/admin-console/src/hooks/api/useQueryExecution.ts b/apps/ai/clients/admin-console/src/hooks/api/query/useQueryExecution.ts
similarity index 88%
rename from apps/ai/clients/admin-console/src/hooks/api/useQueryExecution.ts
rename to apps/ai/clients/admin-console/src/hooks/api/query/useQueryExecution.ts
index 27ff8904..9cb5e967 100644
--- a/apps/ai/clients/admin-console/src/hooks/api/useQueryExecution.ts
+++ b/apps/ai/clients/admin-console/src/hooks/api/query/useQueryExecution.ts
@@ -8,7 +8,7 @@ const useQueryExecution = () => {
 
   const executeQuery = useCallback(
     async (queryId: string, sql_query: string): Promise<Query> =>
-      apiFetcher<Query>(`${API_URL}/query/${queryId}/answer`, {
+      apiFetcher<Query>(`${API_URL}/query/${queryId}/sql-answer`, {
         method: 'POST',
         body: JSON.stringify({ sql_query }),
       }),
diff --git a/apps/ai/clients/admin-console/src/hooks/api/query/useQueryGenerateMessage.ts b/apps/ai/clients/admin-console/src/hooks/api/query/useQueryGenerateMessage.ts
new file mode 100644
index 00000000..59ca644e
--- /dev/null
+++ b/apps/ai/clients/admin-console/src/hooks/api/query/useQueryGenerateMessage.ts
@@ -0,0 +1,26 @@
+import { API_URL } from '@/config'
+import useApiFetcher from '@/hooks/api/generics/useApiFetcher'
+import { useCallback } from 'react'
+
+interface GenerateMessageResponse {
+  message: string
+}
+
+const useQueryGenerateMessage = () => {
+  const apiFetcher = useApiFetcher()
+
+  const generateMessage = useCallback(
+    async (queryId: string): Promise<GenerateMessageResponse> =>
+      apiFetcher<GenerateMessageResponse>(
+        `${API_URL}/query/${queryId}/message`,
+        {
+          method: 'PATCH',
+          body: JSON.stringify({}),
+        },
+      ),
+    [apiFetcher],
+  )
+  return generateMessage
+}
+
+export default useQueryGenerateMessage
diff --git a/apps/ai/clients/admin-console/src/hooks/api/useQueryPatch.ts b/apps/ai/clients/admin-console/src/hooks/api/query/useQueryPatch.ts
similarity index 64%
rename from apps/ai/clients/admin-console/src/hooks/api/useQueryPatch.ts
rename to apps/ai/clients/admin-console/src/hooks/api/query/useQueryPatch.ts
index b894a348..830e578e 100644
--- a/apps/ai/clients/admin-console/src/hooks/api/useQueryPatch.ts
+++ b/apps/ai/clients/admin-console/src/hooks/api/query/useQueryPatch.ts
@@ -3,18 +3,16 @@ import useApiFetcher from '@/hooks/api/generics/useApiFetcher'
 import { Query, QueryStatus } from '@/models/api'
 import { useCallback } from 'react'
 
-const usePatchQuery = () => {
+export interface QueryPatchRequest {
+  query_status?: QueryStatus
+  message?: string
+}
+
+const useQueryPatch = () => {
   const apiFetcher = useApiFetcher()
 
   const patchQuery = useCallback(
-    async (
-      queryId: string,
-      patches: {
-        sql_query: string
-        custom_response: string
-        query_status: QueryStatus
-      },
-    ): Promise<Query> =>
+    async (queryId: string, patches: QueryPatchRequest): Promise<Query> =>
       apiFetcher<Query>(`${API_URL}/query/${queryId}`, {
         method: 'PATCH',
         body: JSON.stringify(patches),
@@ -24,4 +22,4 @@ const usePatchQuery = () => {
   return patchQuery
 }
 
-export default usePatchQuery
+export default useQueryPatch
diff --git a/apps/ai/clients/admin-console/src/hooks/api/query/useQuerySendMessage.ts b/apps/ai/clients/admin-console/src/hooks/api/query/useQuerySendMessage.ts
new file mode 100644
index 00000000..d7e924cb
--- /dev/null
+++ b/apps/ai/clients/admin-console/src/hooks/api/query/useQuerySendMessage.ts
@@ -0,0 +1,18 @@
+import { API_URL } from '@/config'
+import useApiFetcher from '@/hooks/api/generics/useApiFetcher'
+import { useCallback } from 'react'
+
+const useQuerySendMessage = () => {
+  const apiFetcher = useApiFetcher()
+
+  const sendMessage = useCallback(
+    async (queryId: string): Promise<void> =>
+      apiFetcher<void>(`${API_URL}/query/${queryId}/message`, {
+        method: 'POST',
+      }),
+    [apiFetcher],
+  )
+  return sendMessage
+}
+
+export default useQuerySendMessage
diff --git a/apps/ai/clients/admin-console/src/lib/domain/query.ts b/apps/ai/clients/admin-console/src/lib/domain/query.ts
index 9b60a401..7c4f16e1 100644
--- a/apps/ai/clients/admin-console/src/lib/domain/query.ts
+++ b/apps/ai/clients/admin-console/src/lib/domain/query.ts
@@ -37,6 +37,14 @@ export const QUERY_STATUS_COLORS: ResourceColors<QueryWorkspaceStatus> = {
   },
 }
 
+export const QUERY_STATUS_EXPLANATION: Record<QueryWorkspaceStatus, string> = {
+  [EQueryStatus.REJECTED]: `The question is invalid, such as in the case of insufficient data or an unanswerable question`,
+  [EQueryStatus.NOT_VERIFIED]:
+    'The query is not used to improve the platform accuracy',
+  [EQueryStatus.VERIFIED]:
+    'The query is part of the Golden SQL training set to improve the platform accuracy',
+}
+
 export const DOMAIN_QUERY_STATUS_COLORS: ResourceColors<DomainQueryStatus> = {
   [EDomainQueryStatus.REJECTED]: {
     text: 'text-red-500',
@@ -44,6 +52,9 @@ export const DOMAIN_QUERY_STATUS_COLORS: ResourceColors<DomainQueryStatus> = {
   [EDomainQueryStatus.SQL_ERROR]: {
     text: 'text-red-500',
   },
+  [EDomainQueryStatus.NOT_VERIFIED]: {
+    text: 'text-gray-500',
+  },
   [EDomainQueryStatus.LOW_CONFIDENCE]: {
     text: 'text-orange-600',
   },
@@ -60,7 +71,7 @@ export const DOMAIN_QUERY_STATUS_COLORS: ResourceColors<DomainQueryStatus> = {
 
 export const getDomainStatus = (
   status: QueryStatus,
-  evaluation_score: number,
+  evaluation_score: number | null,
 ): DomainQueryStatus | undefined => {
   switch (status) {
     case EQueryStatus.REJECTED:
@@ -68,7 +79,9 @@ export const getDomainStatus = (
     case EQueryStatus.SQL_ERROR:
       return EDomainQueryStatus.SQL_ERROR
     case EQueryStatus.NOT_VERIFIED: {
-      if (evaluation_score < 70) {
+      if (evaluation_score === null) {
+        return status as DomainQueryStatus
+      } else if (evaluation_score < 70) {
         return EDomainQueryStatus.LOW_CONFIDENCE
       } else if (evaluation_score < 90) {
         return EDomainQueryStatus.MEDIUM_CONFIDENCE
@@ -83,7 +96,7 @@ export const getDomainStatus = (
 
 export const getDomainStatusColors = (
   status: QueryStatus,
-  evaluation_score: number,
+  evaluation_score: number | null,
 ): ColorClasses => {
   const domainStatus = getDomainStatus(
     status,
@@ -107,10 +120,13 @@ export const formatQueryStatus = (
 
 export const formatQueryStatusWithScore = (
   status: DomainQueryStatus | QueryStatus | undefined,
-  evaluation_score: number,
+  evaluation_score: number | null,
 ): string => {
   const formattedStatus = formatQueryStatus(status)
-  if (status === EQueryStatus.SQL_ERROR) {
+  if (
+    status === EQueryStatus.SQL_ERROR ||
+    (status === EQueryStatus.NOT_VERIFIED && evaluation_score === null)
+  ) {
     return formattedStatus
   } else if (status === EQueryStatus.REJECTED) {
     return formattedStatus + ' by Admin'
diff --git a/apps/ai/clients/admin-console/src/models/api.ts b/apps/ai/clients/admin-console/src/models/api.ts
index ffba2146..e206c9c4 100644
--- a/apps/ai/clients/admin-console/src/models/api.ts
+++ b/apps/ai/clients/admin-console/src/models/api.ts
@@ -82,15 +82,19 @@ export type QueryList = QueryListItem[]
 
 export interface Query {
   id: string
+  display_id: string
+  question_id: string
   question: string
   question_date: string
+  answer_id: string
   sql_query: string
   sql_query_result: QuerySqlResult | null
   sql_error_message?: string
+  evaluation_score: number
   ai_process: string[]
-  response: string
+  message: string
+  response: string // TODO remove this field once the backend migrated to `message`
   status: QueryStatus
-  evaluation_score: number
   username: string
   last_updated: string
   updated_by: User
diff --git a/apps/ai/clients/admin-console/src/models/domain.ts b/apps/ai/clients/admin-console/src/models/domain.ts
index 9f7d61e1..2474d4fb 100644
--- a/apps/ai/clients/admin-console/src/models/domain.ts
+++ b/apps/ai/clients/admin-console/src/models/domain.ts
@@ -4,6 +4,7 @@ import { LucideIcon } from 'lucide-react'
 export enum EDomainQueryStatus {
   REJECTED = 'REJECTED',
   SQL_ERROR = 'SQL_ERROR',
+  NOT_VERIFIED = 'NOT_VERIFIED',
   LOW_CONFIDENCE = 'LOW_CONFIDENCE',
   MEDIUM_CONFIDENCE = 'MEDIUM_CONFIDENCE',
   HIGH_CONFIDENCE = 'HIGH_CONFIDENCE',
@@ -13,9 +14,9 @@ export enum EDomainQueryStatus {
 export type DomainQueryStatus = keyof typeof EDomainQueryStatus
 
 export enum EDomainQueryWorkspaceStatus {
-  REJECTED = 'REJECTED',
-  NOT_VERIFIED = 'NOT_VERIFIED',
   VERIFIED = 'VERIFIED',
+  NOT_VERIFIED = 'NOT_VERIFIED',
+  REJECTED = 'REJECTED',
 }
 
 export type QueryWorkspaceStatus = keyof typeof EDomainQueryWorkspaceStatus
diff --git a/apps/ai/clients/admin-console/src/pages/databases/index.tsx b/apps/ai/clients/admin-console/src/pages/databases/index.tsx
index b0e0f7c6..d573f8fe 100644
--- a/apps/ai/clients/admin-console/src/pages/databases/index.tsx
+++ b/apps/ai/clients/admin-console/src/pages/databases/index.tsx
@@ -66,7 +66,7 @@ const DatabasesPage: FC = () => {
   }
   return (
     <PageLayout>
-      <ContentBox>{pageContent}</ContentBox>
+      <ContentBox className="m-6">{pageContent}</ContentBox>
     </PageLayout>
   )
 }
diff --git a/apps/ai/clients/admin-console/src/pages/golden-sql/index.tsx b/apps/ai/clients/admin-console/src/pages/golden-sql/index.tsx
index eccdbba5..b327848b 100644
--- a/apps/ai/clients/admin-console/src/pages/golden-sql/index.tsx
+++ b/apps/ai/clients/admin-console/src/pages/golden-sql/index.tsx
@@ -81,7 +81,7 @@ const GoldenSQLPage: FC = () => {
 
   return (
     <PageLayout>
-      <ContentBox className="overflow-auto">
+      <ContentBox className="overflow-auto m-6">
         <div className="flex flex-col gap-3 bg-gray-50 py-0">
           <h1 className="font-bold">Training Queries</h1>
           <p className="text-sm">
diff --git a/apps/ai/clients/admin-console/src/pages/my-account/index.tsx b/apps/ai/clients/admin-console/src/pages/my-account/index.tsx
index 66764475..576d1c40 100644
--- a/apps/ai/clients/admin-console/src/pages/my-account/index.tsx
+++ b/apps/ai/clients/admin-console/src/pages/my-account/index.tsx
@@ -13,7 +13,7 @@ const MyAccountPage: FC = () => {
   return (
     <PageLayout>
       {user && (
-        <div className="grid grid-cols-2 gap-4">
+        <div className="grid grid-cols-2 gap-4 m-6">
           <ContentBox>
             <div className="flex items-center gap-2">
               <User2 size={18} strokeWidth={2.5} />
diff --git a/apps/ai/clients/admin-console/src/pages/organization-settings/index.tsx b/apps/ai/clients/admin-console/src/pages/organization-settings/index.tsx
index 0ea7d35e..84b3ad47 100644
--- a/apps/ai/clients/admin-console/src/pages/organization-settings/index.tsx
+++ b/apps/ai/clients/admin-console/src/pages/organization-settings/index.tsx
@@ -19,7 +19,7 @@ const OrganizationSettingsPage: FC = () => {
 
   return (
     <PageLayout>
-      <div className="flex flex-col gap-5">
+      <div className="flex flex-col gap-5 m-6">
         <div className="flex items-center gap-5">
           <div className="flex items-center gap-2">
             <Building2 size={18} />
diff --git a/apps/ai/clients/admin-console/src/pages/queries/[queryId]/index.tsx b/apps/ai/clients/admin-console/src/pages/queries/[queryId]/index.tsx
index 2a11d01f..51637389 100644
--- a/apps/ai/clients/admin-console/src/pages/queries/[queryId]/index.tsx
+++ b/apps/ai/clients/admin-console/src/pages/queries/[queryId]/index.tsx
@@ -2,11 +2,12 @@ import PageLayout from '@/components/layout/page-layout'
 import QueryError from '@/components/query/error'
 import LoadingQuery from '@/components/query/loading'
 import QueryWorkspace from '@/components/query/workspace'
-import { ContentBox } from '@/components/ui/content-box'
-import { useQuery } from '@/hooks/api/useQuery'
-import useQueryExecution from '@/hooks/api/useQueryExecution'
-import usePatchQuery from '@/hooks/api/useQueryPatch'
-import { Query, QueryStatus } from '@/models/api'
+import { useQuery } from '@/hooks/api/query/useQuery'
+import useQueryExecution from '@/hooks/api/query/useQueryExecution'
+import useQueryPatch, {
+  QueryPatchRequest,
+} from '@/hooks/api/query/useQueryPatch'
+import { Query } from '@/models/api'
 import { withPageAuthRequired } from '@auth0/nextjs-auth0/client'
 import { useRouter } from 'next/router'
 import { FC, useEffect, useState } from 'react'
@@ -21,24 +22,32 @@ const QueryPage: FC = () => {
     mutate,
   } = useQuery(queryId as string)
   const [query, setQuery] = useState<Query | undefined>(initialQuery)
-  const patchQuery = usePatchQuery()
+  const patchQuery = useQueryPatch()
   const executeQuery = useQueryExecution()
 
   useEffect(() => setQuery(initialQuery), [initialQuery])
 
   const handleExecuteQuery = async (sql_query: string) => {
-    const executedQuery = await executeQuery(queryId as string, sql_query)
-    setQuery(executedQuery)
+    try {
+      const executedQuery = await executeQuery(queryId as string, sql_query)
+      setQuery(executedQuery)
+    } catch (e) {
+      console.error(e)
+      throw e
+    }
+    return void 0
   }
 
-  const handlePatchQuery = async (patches: {
-    sql_query: string
-    custom_response: string
-    query_status: QueryStatus
-  }) => {
-    const patchedQuery = await patchQuery(queryId as string, patches)
-    mutate(patchedQuery)
-    setQuery(patchedQuery)
+  const handlePatchQuery = async (patches: QueryPatchRequest) => {
+    try {
+      const patchedQuery = await patchQuery(queryId as string, patches)
+      mutate(patchedQuery)
+      setQuery(patchedQuery)
+    } catch (e) {
+      console.error(e)
+      throw e
+    }
+    return void 0
   }
 
   let pageContent: JSX.Element = <></>
@@ -46,7 +55,11 @@ const QueryPage: FC = () => {
   if (isLoadingInitialQuery && !query) {
     pageContent = <LoadingQuery />
   } else if (error) {
-    pageContent = <QueryError />
+    pageContent = (
+      <div className="m-6">
+        <QueryError />
+      </div>
+    )
   } else if (query)
     pageContent = (
       <QueryWorkspace
@@ -56,11 +69,7 @@ const QueryPage: FC = () => {
       />
     )
 
-  return (
-    <PageLayout>
-      <ContentBox>{pageContent}</ContentBox>
-    </PageLayout>
-  )
+  return <PageLayout disableBreadcrumb>{pageContent}</PageLayout>
 }
 
 export default withPageAuthRequired(QueryPage)
diff --git a/apps/ai/clients/admin-console/src/pages/queries/index.tsx b/apps/ai/clients/admin-console/src/pages/queries/index.tsx
index 90a2bf4b..92c47eff 100644
--- a/apps/ai/clients/admin-console/src/pages/queries/index.tsx
+++ b/apps/ai/clients/admin-console/src/pages/queries/index.tsx
@@ -5,7 +5,7 @@ import { columns as cols } from '@/components/queries/columns'
 import QueriesError from '@/components/queries/error'
 import { Button } from '@/components/ui/button'
 import { ContentBox } from '@/components/ui/content-box'
-import useQueries from '@/hooks/api/useQueries'
+import useQueries from '@/hooks/api/query/useQueries'
 import { buildIdHref, cn } from '@/lib/utils'
 import { QueryListItem } from '@/models/api'
 import { withPageAuthRequired } from '@auth0/nextjs-auth0/client'
@@ -63,7 +63,7 @@ const QueriesPage: FC = () => {
 
   return (
     <PageLayout>
-      <ContentBox className="overflow-auto">
+      <ContentBox className="overflow-auto m-6">
         <div className="flex items-center justify-between bg-gray-50 py-0">
           <h1 className="font-bold">Latest Queries</h1>
           <Button
diff --git a/apps/ai/server/app.py b/apps/ai/server/app.py
index 9cde0464..d3137dac 100644
--- a/apps/ai/server/app.py
+++ b/apps/ai/server/app.py
@@ -61,7 +61,7 @@ async def heartbeat():
 @app.get("/engine/heartbeat")
 async def engine_heartbeat():
     async with httpx.AsyncClient() as client:
-        response = await client.get(settings.k2_core_url + "/heartbeat")
+        response = await client.get(settings.engine_url + "/heartbeat")
         response.raise_for_status()  # Raise an exception for non-2xx status codes
         return response.json()
 
diff --git a/apps/ai/server/config.py b/apps/ai/server/config.py
index 03e1498f..93024bf2 100644
--- a/apps/ai/server/config.py
+++ b/apps/ai/server/config.py
@@ -22,8 +22,8 @@
 class Settings(BaseSettings):
     load_dotenv()
 
-    k2_core_url: str = os.environ.get("K2_CORE_URL")
-    default_k2_core_timeout: int = os.environ.get("DEFAULT_K2_TIMEOUT")
+    engine_url: str = os.environ.get("K2_CORE_URL")
+    default_engine_timeout: int = os.environ.get("DEFAULT_K2_TIMEOUT")
     encrypt_key: str = os.environ.get("ENCRYPT_KEY")
 
     def __getitem__(self, key: str) -> Any:
diff --git a/apps/ai/server/database/migrations/sprint_62/1_DH-4875_query_edit_refactor.py b/apps/ai/server/database/migrations/sprint_62/1_DH-4875_query_edit_refactor.py
new file mode 100644
index 00000000..5a1c5928
--- /dev/null
+++ b/apps/ai/server/database/migrations/sprint_62/1_DH-4875_query_edit_refactor.py
@@ -0,0 +1,21 @@
+import pymongo
+
+import config
+
+if __name__ == "__main__":
+    data_store = pymongo.MongoClient(config.db_settings.mongodb_uri)[
+        config.db_settings.mongodb_db_name
+    ]
+
+    try:
+        data_store["queries"].update_many(
+            {},
+            {
+                "$rename": {
+                    "custom_response": "message",
+                    "response_id": "answer_id",
+                }
+            },
+        )
+    except Exception as e:
+        print(e)
diff --git a/apps/ai/server/database/migrations/sprint_62/DH-4904_replace_llm_credentials.py b/apps/ai/server/database/migrations/sprint_62/2_DH-4904_replace_llm_credentials.py
similarity index 100%
rename from apps/ai/server/database/migrations/sprint_62/DH-4904_replace_llm_credentials.py
rename to apps/ai/server/database/migrations/sprint_62/2_DH-4904_replace_llm_credentials.py
diff --git a/apps/ai/server/dataherald b/apps/ai/server/dataherald
index 844491de..6d40e930 160000
--- a/apps/ai/server/dataherald
+++ b/apps/ai/server/dataherald
@@ -1 +1 @@
-Subproject commit 844491de1eade136de6c516bbf1c0c3bc0890e4d
+Subproject commit 6d40e930bc15dd9ac584caaba657f36b2ef7894e
diff --git a/apps/ai/server/modules/db_connection/service.py b/apps/ai/server/modules/db_connection/service.py
index 27209ab2..58f1b5bf 100644
--- a/apps/ai/server/modules/db_connection/service.py
+++ b/apps/ai/server/modules/db_connection/service.py
@@ -56,12 +56,12 @@ async def add_db_connection(
 
         async with httpx.AsyncClient() as client:
             response = await client.post(
-                settings.k2_core_url + "/database-connections",
+                settings.engine_url + "/database-connections",
                 json={
                     "llm_api_key": organization.llm_api_key,
                     **db_connection_request.dict(),
                 },
-                timeout=settings.default_k2_core_timeout,
+                timeout=settings.default_engine_timeout,
             )
 
             raise_for_status(response.status_code, response.text)
@@ -96,12 +96,12 @@ async def update_db_connection(
 
         async with httpx.AsyncClient() as client:
             response = await client.put(
-                settings.k2_core_url + f"/database-connections/{id}",
+                settings.engine_url + f"/database-connections/{id}",
                 json={
                     "llm_api_key": organization.llm_api_key,
                     **db_connection_request.dict(),
                 },
-                timeout=settings.default_k2_core_timeout,
+                timeout=settings.default_engine_timeout,
             )
             raise_for_status(response.status_code, response.text)
             return DBConnectionResponse(**response.json())
diff --git a/apps/ai/server/modules/golden_sql/controller.py b/apps/ai/server/modules/golden_sql/controller.py
index 6ce73181..4423cea2 100644
--- a/apps/ai/server/modules/golden_sql/controller.py
+++ b/apps/ai/server/modules/golden_sql/controller.py
@@ -6,6 +6,7 @@
 from modules.golden_sql.models.requests import GoldenSQLRequest
 from modules.golden_sql.models.responses import GoldenSQLResponse
 from modules.golden_sql.service import GoldenSQLService
+from modules.query.models.entities import QueryStatus
 from utils.auth import Authorize, VerifyToken
 
 router = APIRouter(
@@ -56,4 +57,4 @@ async def add_user_upload_golden_sql(
 async def delete_golden_sql(id: str, token: str = Depends(token_auth_scheme)):
     org_id = authorize.user(VerifyToken(token.credentials).verify()).organization_id
     authorize.golden_sql_in_organization(id, org_id)
-    return await golden_sql_service.delete_golden_sql(id)
+    return await golden_sql_service.delete_golden_sql(id, QueryStatus.NOT_VERIFIED)
diff --git a/apps/ai/server/modules/golden_sql/repository.py b/apps/ai/server/modules/golden_sql/repository.py
index 11ab59ca..96825192 100644
--- a/apps/ai/server/modules/golden_sql/repository.py
+++ b/apps/ai/server/modules/golden_sql/repository.py
@@ -55,12 +55,16 @@ def delete_golden_sql_ref(self, golden_id: str) -> int:
     # this violates the architecture, but it's a quick fix for now
     # TODO: need to avoid cross resource dependency and avoid circular dependency
     def delete_verified_golden_sql_ref(self, query_id: str):
-        MongoDB.update_one(
+        return MongoDB.delete_one(GOLDEN_SQL_REF_COL, {"query_id": ObjectId(query_id)})
+
+    def update_query_status(self, query_id: str, status: str):
+        # this violates the architecture, but it's a quick fix for now
+        # TODO: need to avoid cross resource dependency and avoid circular dependency
+        return MongoDB.update_one(
             QUERY_RESPONSE_REF_COL,
             {"_id": ObjectId(query_id)},
-            {"status": "NOT_VERIFIED"},
+            {"status": status},
         )
-        return MongoDB.delete_one(GOLDEN_SQL_REF_COL, {"query_id": ObjectId(query_id)})
 
     def get_next_display_id(self, org_id: str) -> str:
         return get_next_display_id(GOLDEN_SQL_REF_COL, ObjectId(org_id), "GS")
diff --git a/apps/ai/server/modules/golden_sql/service.py b/apps/ai/server/modules/golden_sql/service.py
index 78e68c6d..7507d262 100644
--- a/apps/ai/server/modules/golden_sql/service.py
+++ b/apps/ai/server/modules/golden_sql/service.py
@@ -10,6 +10,7 @@
 from modules.golden_sql.models.requests import GoldenSQLRequest
 from modules.golden_sql.models.responses import GoldenSQLResponse
 from modules.golden_sql.repository import GoldenSQLRepository
+from modules.query.models.entities import QueryStatus
 from utils.exception import raise_for_status
 
 
@@ -65,9 +66,9 @@ async def add_verified_query_golden_sql(
             await self.delete_golden_sql(golden_sql_ref.golden_sql_id)
         async with httpx.AsyncClient() as client:
             response = await client.post(
-                settings.k2_core_url + "/golden-records",
+                settings.engine_url + "/golden-records",
                 json=[golden_sql_request.dict()],
-                timeout=settings.default_k2_core_timeout,
+                timeout=settings.default_engine_timeout,
             )
             raise_for_status(response.status_code, response.text)
             response_json = response.json()[0]
@@ -94,12 +95,12 @@ async def add_user_upload_golden_sql(
     ) -> List[GoldenSQLResponse]:
         async with httpx.AsyncClient() as client:
             response = await client.post(
-                settings.k2_core_url + "/golden-records",
+                settings.engine_url + "/golden-records",
                 json=[
                     golden_sql_request.dict()
                     for golden_sql_request in golden_sql_requests
                 ],
-                timeout=settings.default_k2_core_timeout,
+                timeout=settings.default_engine_timeout,
             )
             raise_for_status(response.status_code, response.text)
 
@@ -117,7 +118,7 @@ async def add_user_upload_golden_sql(
                 golden_sql_ref_data = GoldenSQLRef(
                     golden_sql_id=golden_sql.id,
                     organization_id=ObjectId(org_id),
-                    source=GoldenSQLSource.USER_UPLOAD.value,
+                    source=GoldenSQLSource.USER_UPLOAD,
                     created_time=datetime.now(timezone.utc).strftime(
                         "%Y-%m-%d %H:%M:%S"
                     ),
@@ -133,14 +134,16 @@ async def add_user_upload_golden_sql(
 
             return golden_sql_responses
 
-    async def delete_golden_sql(self, golden_id: str) -> dict:
+    async def delete_golden_sql(
+        self, golden_id: str, query_status: QueryStatus = None
+    ) -> dict:
         golden_sql_ref = self.repo.get_golden_sql_ref(golden_id)
 
         if golden_sql_ref:
             async with httpx.AsyncClient() as client:
                 response = await client.delete(
-                    settings.k2_core_url + f"/golden-records/{golden_id}",
-                    timeout=settings.default_k2_core_timeout,
+                    settings.engine_url + f"/golden-records/{golden_id}",
+                    timeout=settings.default_engine_timeout,
                 )
                 raise_for_status(response.status_code, response.text)
                 if response.json()["status"]:
@@ -148,6 +151,10 @@ async def delete_golden_sql(self, golden_id: str) -> dict:
                         matched_count = self.repo.delete_verified_golden_sql_ref(
                             golden_sql_ref.query_id
                         )
+                        if query_status:
+                            self.repo.update_query_status(
+                                golden_sql_ref.query_id, query_status
+                            )
                     else:
                         matched_count = self.repo.delete_golden_sql_ref(golden_id)
                     if matched_count == 1:
diff --git a/apps/ai/server/modules/instruction/service.py b/apps/ai/server/modules/instruction/service.py
index de9304cc..62edc696 100644
--- a/apps/ai/server/modules/instruction/service.py
+++ b/apps/ai/server/modules/instruction/service.py
@@ -13,7 +13,7 @@ async def get_instructions(
     ) -> list[InstructionResponse]:
         async with httpx.AsyncClient() as client:
             response = await client.get(
-                settings.k2_core_url + "/instructions",
+                settings.engine_url + "/instructions",
                 params={"db_connection_id": db_connection_id},
             )
             raise_for_status(response.status_code, response.text)
@@ -22,7 +22,7 @@ async def get_instructions(
     async def get_instruction(self, db_connection_id: str) -> InstructionResponse:
         async with httpx.AsyncClient() as client:
             response = await client.get(
-                settings.k2_core_url + "/instructions",
+                settings.engine_url + "/instructions",
                 params={"db_connection_id": db_connection_id},
             )
             instructions = response.json()
@@ -36,7 +36,7 @@ async def add_instruction(
     ) -> InstructionResponse:
         async with httpx.AsyncClient() as client:
             response = await client.post(
-                settings.k2_core_url + "/instructions",
+                settings.engine_url + "/instructions",
                 json={
                     "db_connection_id": db_connection_id,
                     **instruction_request.dict(),
@@ -53,7 +53,7 @@ async def update_instruction(
     ) -> InstructionResponse:
         async with httpx.AsyncClient() as client:
             response = await client.put(
-                settings.k2_core_url + f"/instructions/{instruction_id}",
+                settings.engine_url + f"/instructions/{instruction_id}",
                 json={
                     "db_connection_id": db_connection_id,
                     **instruction_request.dict(exclude_unset=True),
@@ -65,7 +65,7 @@ async def update_instruction(
     async def delete_instruction(self, instruction_id):
         async with httpx.AsyncClient() as client:
             response = await client.delete(
-                settings.k2_core_url + f"/instructions/{instruction_id}",
+                settings.engine_url + f"/instructions/{instruction_id}",
             )
             raise_for_status(response.status_code, response.text)
             return {"id": instruction_id}
diff --git a/apps/ai/server/modules/query/controller.py b/apps/ai/server/modules/query/controller.py
index 658974af..509b4951 100644
--- a/apps/ai/server/modules/query/controller.py
+++ b/apps/ai/server/modules/query/controller.py
@@ -3,11 +3,12 @@
 
 from modules.organization.service import OrganizationService
 from modules.query.models.requests import (
-    QueryExecutionRequest,
     QueryUpdateRequest,
     QuestionRequest,
+    SQLAnswerRequest,
 )
 from modules.query.models.responses import (
+    MessageResponse,
     QueryListResponse,
     QueryResponse,
     QuerySlackResponse,
@@ -66,7 +67,7 @@ async def get_query(id: str, token: str = Depends(token_auth_scheme)) -> QueryRe
 
 
 @router.patch("/{id}")
-async def patch_response(
+async def update_query(
     id: str,
     query_request: QueryUpdateRequest,
     token: str = Depends(token_auth_scheme),
@@ -74,15 +75,36 @@ async def patch_response(
     user = authorize.user(VerifyToken(token.credentials).verify())
     organization = authorize.get_organization_by_user_response(user)
     authorize.query_in_organization(id, str(organization.id))
-    return await query_service.patch_response(id, query_request, organization, user)
+    return await query_service.update_query(id, query_request, user, organization)
 
 
-@router.post("/{id}/answer")
-async def run_response(
+@router.post("/{id}/sql-answer", status_code=status.HTTP_201_CREATED)
+async def generate_sql_answer(
     id: str,
-    sql_query: QueryExecutionRequest,
+    sql_answer_request: SQLAnswerRequest,
     token: str = Depends(token_auth_scheme),
 ) -> QueryResponse:
     user = authorize.user(VerifyToken(token.credentials).verify())
     authorize.query_in_organization(id, user.organization_id)
-    return await query_service.run_response(id, sql_query, user)
+    return await query_service.generate_sql_answer(id, sql_answer_request, user)
+
+
+@router.patch("/{id}/message", status_code=status.HTTP_200_OK)
+async def generate_message(
+    id: str,
+    token: str = Depends(token_auth_scheme),
+) -> MessageResponse:
+    user = authorize.user(VerifyToken(token.credentials).verify())
+    authorize.query_in_organization(id, user.organization_id)
+    return await query_service.generate_message(id)
+
+
+@router.post("/{id}/message", status_code=status.HTTP_200_OK)
+async def send_message(
+    id: str,
+    token: str = Depends(token_auth_scheme),
+):
+    user = authorize.user(VerifyToken(token.credentials).verify())
+    authorize.query_in_organization(id, user.organization_id)
+    organization = authorize.get_organization_by_user_response(user)
+    return await query_service.send_message(id, organization)
diff --git a/apps/ai/server/modules/query/models/entities.py b/apps/ai/server/modules/query/models/entities.py
index cb16cc98..d9879519 100644
--- a/apps/ai/server/modules/query/models/entities.py
+++ b/apps/ai/server/modules/query/models/entities.py
@@ -19,24 +19,24 @@ class QueryStatus(str, Enum):
     REJECTED = "REJECTED"
 
 
-class SQLGenerationStatus(Enum):
-    VALID = "VALID"
-    INVALID = "INVALID"
-    NONE = "NONE"
-
-
 class Query(BaseModel):
     id: Any = Field(alias="_id")
     status: QueryStatus
     question_id: Any
-    response_id: Any
+    answer_id: Any
     question_date: str
     last_updated: str
     updated_by: Any
     organization_id: Any
     display_id: str | None
     slack_info: SlackInfo
-    custom_response: str | None
+    message: str | None
+
+
+class SQLGenerationStatus(str, Enum):
+    VALID = "VALID"
+    INVALID = "INVALID"
+    NONE = "NONE"
 
 
 class SQLQueryResult(BaseModel):
@@ -44,8 +44,8 @@ class SQLQueryResult(BaseModel):
     rows: list[dict]
 
 
-class BaseEngineAnswer(BaseModel):
-    response: str | None
+class BaseAnswer(BaseModel):
+    response: str | None  # TODO: rename to message after engine refactor
     intermediate_steps: list[str] | None
     sql_query: str | None
     sql_query_result: SQLQueryResult | None
@@ -57,6 +57,6 @@ class BaseEngineAnswer(BaseModel):
     error_message: str | None
 
 
-class EngineAnswer(BaseEngineAnswer):
-    id: Any | None = Field(alias="_id")
+class Answer(BaseAnswer):
+    id: Any = Field(alias="_id")
     question_id: Any
diff --git a/apps/ai/server/modules/query/models/requests.py b/apps/ai/server/modules/query/models/requests.py
index 64ba2e12..7178b5c4 100644
--- a/apps/ai/server/modules/query/models/requests.py
+++ b/apps/ai/server/modules/query/models/requests.py
@@ -12,10 +12,9 @@ class QuestionRequest(BaseModel):
 
 
 class QueryUpdateRequest(BaseModel):
-    sql_query: str
     query_status: QueryStatus | None
-    custom_response: str | None
+    message: str | None
 
 
-class QueryExecutionRequest(BaseModel):
+class SQLAnswerRequest(BaseModel):
     sql_query: str
diff --git a/apps/ai/server/modules/query/models/responses.py b/apps/ai/server/modules/query/models/responses.py
index c8c14241..12603ee2 100644
--- a/apps/ai/server/modules/query/models/responses.py
+++ b/apps/ai/server/modules/query/models/responses.py
@@ -1,18 +1,9 @@
 from pydantic import BaseModel
 
-from modules.query.models.entities import (
-    BaseEngineAnswer,
-    QueryStatus,
-    SQLQueryResult,
-)
+from modules.query.models.entities import BaseAnswer, QueryStatus, SQLQueryResult
 from modules.user.models.responses import UserResponse
 
 
-class EngineAnswerResponse(BaseEngineAnswer):
-    id: str | None
-    question_id: str
-
-
 class QuerySlackResponse(BaseModel):
     id: str
     display_id: str
@@ -26,7 +17,7 @@ class QueryListResponse(BaseModel):
     id: str
     username: str
     question: str
-    question_date: str
+    question_date: str | None
     response: str | None
     status: QueryStatus | None
     evaluation_score: float | None
@@ -34,9 +25,20 @@ class QueryListResponse(BaseModel):
 
 
 class QueryResponse(QueryListResponse):
+    question_id: str
+    answer_id: str
     sql_query_result: SQLQueryResult | None
     sql_query: str
     ai_process: list[str] = []
     last_updated: str | None
     updated_by: UserResponse | None
     sql_error_message: str | None
+
+
+class AnswerResponse(BaseAnswer):
+    id: str
+    question_id: str
+
+
+class MessageResponse(BaseModel):
+    message: str
diff --git a/apps/ai/server/modules/query/repository.py b/apps/ai/server/modules/query/repository.py
index e25a476b..d9c11b8d 100644
--- a/apps/ai/server/modules/query/repository.py
+++ b/apps/ai/server/modules/query/repository.py
@@ -2,7 +2,7 @@
 
 from config import QUERY_RESPONSE_COL, QUERY_RESPONSE_REF_COL, QUESTION_COL
 from database.mongo import DESCENDING, MongoDB
-from modules.query.models.entities import EngineAnswer, Query, Question
+from modules.query.models.entities import Answer, Query, Question
 from utils.misc import get_next_display_id
 
 
@@ -16,20 +16,20 @@ def get_questions(self, question_ids: list[str]) -> list[Question]:
         questions = MongoDB.find_by_object_ids(QUESTION_COL, object_ids)
         return [Question(**question) for question in questions]
 
-    def get_answer(self, response_id: str) -> EngineAnswer:
-        answer = MongoDB.find_by_object_id(QUERY_RESPONSE_COL, ObjectId(response_id))
-        return EngineAnswer(**answer) if answer else None
+    def get_answer(self, answer_id: str) -> Answer:
+        answer = MongoDB.find_by_object_id(QUERY_RESPONSE_COL, ObjectId(answer_id))
+        return Answer(**answer) if answer else None
 
-    def get_answers(self, response_ids: list[str]) -> list[EngineAnswer]:
+    def get_answers(self, response_ids: list[str]) -> list[Answer]:
         object_ids = [ObjectId(id) for id in response_ids]
         answers = MongoDB.find(QUERY_RESPONSE_COL, {"_id": {"$in": object_ids}})
-        return [EngineAnswer(**qr) for qr in answers]
+        return [Answer(**qr) for qr in answers]
 
-    def get_answers_by_question_id(self, question_id: str) -> list[EngineAnswer]:
+    def get_answers_by_question_id(self, question_id: str) -> list[Answer]:
         answers = MongoDB.find(
             QUERY_RESPONSE_COL, {"question_id": ObjectId(question_id)}
         )
-        return [EngineAnswer(**qr) for qr in answers]
+        return [Answer(**qr) for qr in answers]
 
     def get_query(self, query_id: str) -> Query:
         query = MongoDB.find_one(QUERY_RESPONSE_REF_COL, {"_id": ObjectId(query_id)})
@@ -46,11 +46,11 @@ def get_queries(
         )
         return [Query(**query) for query in queries]
 
-    def get_question_answers(self, question_id: str) -> list[EngineAnswer]:
+    def get_question_answers(self, question_id: str) -> list[Answer]:
         answers = MongoDB.find(
             QUERY_RESPONSE_COL, {"question_id": ObjectId(question_id)}
         )
-        return [EngineAnswer(**answer) for answer in answers]
+        return [Answer(**answer) for answer in answers]
 
     def get_query_by_question_id(self, question_id: str) -> Query:
         query = MongoDB.find_one(
diff --git a/apps/ai/server/modules/query/service.py b/apps/ai/server/modules/query/service.py
index fbf8245a..d0c7052c 100644
--- a/apps/ai/server/modules/query/service.py
+++ b/apps/ai/server/modules/query/service.py
@@ -11,20 +11,20 @@
 from modules.golden_sql.service import GoldenSQLService
 from modules.organization.models.responses import OrganizationResponse
 from modules.query.models.entities import (
-    BaseEngineAnswer,
-    EngineAnswer,
+    Answer,
     Query,
     QueryStatus,
     Question,
     SQLGenerationStatus,
 )
 from modules.query.models.requests import (
-    QueryExecutionRequest,
     QueryUpdateRequest,
     QuestionRequest,
+    SQLAnswerRequest,
 )
 from modules.query.models.responses import (
-    EngineAnswerResponse,
+    AnswerResponse,
+    MessageResponse,
     QueryListResponse,
     QueryResponse,
     QuerySlackResponse,
@@ -62,22 +62,22 @@ async def answer_question(
         # ask question to k2 engine
         async with httpx.AsyncClient() as client:
             response = await client.post(
-                settings.k2_core_url + "/questions",
+                settings.engine_url + "/questions",
                 json={
                     "question": question_string,
                     "db_connection_id": organization.db_connection_id,
                 },
-                timeout=settings.default_k2_core_timeout,
+                timeout=settings.default_engine_timeout,
             )
             response_json = response.json()
             if not response_json["question_id"]:
                 raise_for_status(response.status_code, response.text)
 
-            answer = EngineAnswerResponse(**response_json)
+            answer = AnswerResponse(**response_json)
 
             query = Query(
                 question_id=ObjectId(answer.question_id),
-                response_id=ObjectId(answer.id) if answer.id else None,
+                answer_id=ObjectId(answer.id) if answer.id else None,
                 question_date=current_utc_time,
                 last_updated=current_utc_time,
                 organization_id=ObjectId(organization.id),
@@ -93,7 +93,7 @@ async def answer_question(
                 else QueryStatus.SQL_ERROR,
             )
 
-            query_id = self.repo.add_query(query.dict(exclude={"id"}))
+            query_id = self.repo.add_query(query.dict(exclude_unset=True))
 
             self.analytics.track(
                 question_request.slack_user_id,
@@ -102,7 +102,7 @@ async def answer_question(
                     "query_id": query_id,
                     "display_id": query.display_id,
                     "question_id": str(query.question_id),
-                    "response_id": str(query.response_id),
+                    "answer_id": str(query.answer_id),
                     "organization_id": organization.id,
                     "organization_name": organization.name,
                     "database_name": self.db_connection_service.get_db_connection(
@@ -144,7 +144,7 @@ async def answer_question(
                             organization.db_connection_id
                         ).alias,
                         "display_id": query.display_id,
-                        "status": query.status.value,
+                        "status": query.status,
                         "confidence_score": answer.confidence_score,
                         "asker": username,
                     },
@@ -171,9 +171,7 @@ async def answer_question(
     def get_query(self, query_id: str):
         query = self.repo.get_query(query_id)
         question = self.repo.get_question(str(query.question_id))
-        answer = (
-            self.repo.get_answer(str(query.response_id)) if query.response_id else None
-        )
+        answer = self.repo.get_answer(str(query.answer_id)) if query.answer_id else None
         if query:
             return self._get_mapped_query_response(query, question, answer)
 
@@ -197,8 +195,8 @@ def get_queries(
                     id=str(query.id),
                     username=query.slack_info.username or "unknown",
                     question=question.question,
-                    response=query.custom_response
-                    or (answer.response if query.response_id else ""),
+                    response=query.message
+                    or (answer.response if query.answer_id else ""),
                     status=query.status,
                     question_date=query.question_date,
                     evaluation_score=self._convert_confidence_score(
@@ -217,7 +215,7 @@ def get_queries(
             [
                 result
                 for query in queries
-                if (result := str(query.response_id) if query.response_id else None)
+                if (result := str(query.answer_id) if query.answer_id else None)
                 is not None
             ]
         )
@@ -231,7 +229,7 @@ def get_queries(
             if question.id not in question_dict:
                 question_dict[question.id] = question.question
 
-        query_response_dict: Dict[ObjectId, EngineAnswer | None] = {}
+        query_response_dict: Dict[ObjectId, Answer | None] = {}
         for answer in query_responses:
             query_response_dict[answer.id] = answer
 
@@ -241,18 +239,18 @@ def get_queries(
                     id=str(query.id),
                     username=query.slack_info.username or "unknown",
                     question=question_dict[query.question_id],
-                    response=query.custom_response
+                    response=query.message
                     or (
-                        query_response_dict[query.response_id].response
-                        if query.response_id
+                        query_response_dict[query.answer_id].response
+                        if query.answer_id
                         else ""
                     ),
                     question_date=query.question_date,
                     status=query.status,
                     evaluation_score=self._convert_confidence_score(
-                        query_response_dict[query.response_id].confidence_score
+                        query_response_dict[query.answer_id].confidence_score
                     )
-                    if query.response_id
+                    if query.answer_id
                     else 0,
                     display_id=query.display_id,
                 )
@@ -261,109 +259,77 @@ def get_queries(
 
         return []
 
-    async def patch_response(
+    async def update_query(
         self,
         query_id: str,
         query_request: QueryUpdateRequest,
-        organization: OrganizationResponse,
         user: UserResponse,
+        organization: OrganizationResponse,
     ) -> QueryResponse:
         query = self.repo.get_query(query_id)
-        prev_sql_query = (
-            self.repo.get_answer(str(query.response_id)).sql_query
-            if query.response_id
-            else None
-        )
-
-        if query_request.query_status != QueryStatus.REJECTED:
-            async with httpx.AsyncClient() as client:
-                response = await client.post(
-                    settings.k2_core_url + "/responses",
-                    json={
-                        "question_id": str(query.question_id),
-                        "sql_query": query_request.sql_query,
-                    },
-                    timeout=settings.default_k2_core_timeout,
-                )
-                raise_for_status(response.status_code, response.text)
-
-                new_query_response = EngineAnswerResponse(**response.json())
-        else:
-            new_query_response = None
-
         question = self.repo.get_question(query.question_id)
+        answer = self.repo.get_answer(str(query.answer_id)) if query.answer_id else None
         current_utc_time = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
-        updated_query = {
-            "response_id": ObjectId(new_query_response.id)
-            if new_query_response
-            else None,
+        updated_request = {
             "last_updated": current_utc_time,
             "updated_by": ObjectId(user.id),
-            "status": query_request.query_status.value,
-            "custom_response": query_request.custom_response,
+            "message": query_request.message,
         }
-        self.repo.update_query(str(query.id), updated_query)
+        if query_request.query_status:
+            updated_request["status"] = query_request.query_status
+
+        self.repo.update_query(str(query.id), updated_request)
         updated_query = self.repo.get_query(str(query.id))
 
         # verified
-        if query_request.query_status == QueryStatus.VERIFIED:
-            golden_sql = GoldenSQLRequest(
-                question=question.question,
-                sql_query=query_request.sql_query,
-                db_connection_id=organization.db_connection_id,
-            )
-            await self.golden_sql_service.add_verified_query_golden_sql(
-                golden_sql,
-                organization.id,
-                updated_query.id,
-            )
-
-            SlackWebClient(
-                organization.slack_installation.bot.token
-            ).send_verified_query_message(
-                updated_query,
-                new_query_response,
-                question.question,
-            )
+        if query_request.query_status:
+            if query_request.query_status == QueryStatus.VERIFIED:
+                golden_sql = GoldenSQLRequest(
+                    question=question.question,
+                    sql_query=answer.sql_query,
+                    db_connection_id=organization.db_connection_id,
+                )
+                await self.golden_sql_service.add_verified_query_golden_sql(
+                    golden_sql,
+                    organization.id,
+                    updated_query.id,
+                )
 
-            # logic to track 1st time correct response generated by engine
-            all_answers = self.repo.get_answers_by_question_id(
-                str(updated_query.question_id)
-            )
-            if all(answer.sql_query == prev_sql_query for answer in all_answers):
-                self.analytics.track(
-                    user.email,
-                    "verified_query_correct_on_first_try",
-                    {
-                        "query_id": query.id,
-                        "question_id": str(query.question_id),
-                        "response_id": str(query.response_id)
-                        if query.response_id
-                        else None,
-                        "database_name": self.db_connection_service.get_db_connection(
-                            organization.db_connection_id
-                        ).alias,
-                        "display_id": query.display_id,
-                        "status": query.status.value,
-                        "confidence_score": new_query_response.confidence_score
-                        if new_query_response
-                        else None,
-                    },
+                # logic to track 1st time correct response generated by engine
+                all_answers = self.repo.get_answers_by_question_id(
+                    str(updated_query.question_id)
                 )
+                if all(ans.sql_query == answer.sql_query for ans in all_answers):
+                    self.analytics.track(
+                        user.email,
+                        "verified_query_correct_on_first_try",
+                        {
+                            "query_id": query_id,
+                            "question_id": str(updated_query.question_id),
+                            "answer_id": str(updated_query.answer_id)
+                            if updated_query.answer_id
+                            else None,
+                            "organization_id": organization.id,
+                            "display_id": updated_query.display_id,
+                            "status": query_request.query_status,
+                            "confidence_score": answer.confidence_score
+                            if answer
+                            else None,
+                            "database_name": self.db_connection_service.get_db_connection(
+                                organization.db_connection_id
+                            ).alias,
+                        },
+                    )
 
-        # rejected or not verified
-        else:
-            golden_sql_ref = self.golden_sql_service.get_verified_golden_sql_ref(
-                updated_query.id
-            )
-            if golden_sql_ref:
-                await self.golden_sql_service.delete_golden_sql(
-                    str(golden_sql_ref.golden_sql_id)
+            # rejected or not verified
+            else:
+                golden_sql_ref = self.golden_sql_service.get_verified_golden_sql_ref(
+                    updated_query.id
                 )
-            if query_request.query_status == QueryStatus.REJECTED:
-                SlackWebClient(
-                    organization.slack_installation.bot.token,
-                ).send_rejected_query_message(updated_query)
+                if golden_sql_ref:
+                    await self.golden_sql_service.delete_golden_sql(
+                        str(golden_sql_ref.golden_sql_id), query_request.query_status
+                    )
 
         self.analytics.track(
             user.email,
@@ -371,80 +337,111 @@ async def patch_response(
             {
                 "query_id": query_id,
                 "question_id": str(updated_query.question_id),
-                "response_id": str(updated_query.response_id)
-                if updated_query.response_id
+                "answer_id": str(updated_query.answer_id)
+                if updated_query.answer_id
                 else None,
                 "database_name": self.db_connection_service.get_db_connection(
                     organization.db_connection_id
                 ).alias,
                 "display_id": updated_query.display_id,
-                "status": query_request.query_status.value,
-                "confidence_score": new_query_response.confidence_score
-                if new_query_response
-                else None,
-                "asker": query.slack_info.username,
+                "status": query_request.query_status,
+                "confidence_score": answer.confidence_score if answer else None,
             },
         )
 
-        return self._get_mapped_query_response(
-            updated_query, question, new_query_response
-        )
+        return self._get_mapped_query_response(updated_query, question, answer)
 
-    async def run_response(
-        self, query_id: str, query_request: QueryExecutionRequest, user: UserResponse
-    ):
+    async def generate_sql_answer(
+        self, query_id: str, sql_answer_request: SQLAnswerRequest, user: UserResponse
+    ) -> QueryResponse:
         query = self.repo.get_query(query_id)
+        question = self.repo.get_question(str(query.question_id))
         async with httpx.AsyncClient() as client:
             response = await client.post(
-                settings.k2_core_url + "/responses",
+                settings.engine_url + "/responses",
+                params={"sql_response_only": True, "run_evaluator": False},
                 json={
                     "question_id": str(query.question_id),
-                    "sql_query": query_request.sql_query,
+                    "sql_query": sql_answer_request.sql_query,
                 },
-                timeout=settings.default_k2_core_timeout,
+                timeout=settings.default_engine_timeout,
             )
             raise_for_status(response.status_code, response.text)
-            query.custom_response = None
-            question = self.repo.get_question(query.question_id)
-            new_query_response = EngineAnswerResponse(**response.json())
-
+            current_utc_time = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S")
+            answer = AnswerResponse(**response.json())
+            updated_request = {
+                "last_updated": current_utc_time,
+                "updated_by": ObjectId(user.id),
+                "answer_id": ObjectId(answer.id),
+            }
+            self.repo.update_query(str(query.id), updated_request)
             self.analytics.track(
                 user.email,
                 "query_executed",
                 {
                     "query_id": query_id,
-                    "question_id": new_query_response.id,
-                    "response_id": new_query_response.id,
+                    "question_id": question.id,
+                    "answer_id": answer.id,
+                    "sql_generation_status": answer.sql_generation_status,
+                    "confidence_score": answer.confidence_score,
                     "database_name": self.db_connection_service.get_db_connection(
                         str(question.db_connection_id)
                     ).alias,
-                    "sql_generation_status": new_query_response.sql_generation_status.value,
-                    "confidence_score": new_query_response.confidence_score,
                 },
             )
+            return self._get_mapped_query_response(query, question, answer)
+
+    async def generate_message(self, query_id: str) -> MessageResponse:
+        query = self.repo.get_query(query_id)
+        async with httpx.AsyncClient() as client:
+            response = await client.patch(
+                settings.engine_url + f"/responses/{str(query.answer_id)}",
+                timeout=settings.default_engine_timeout,
+            )
+            raise_for_status(response.status_code, response.text)
 
-            return self._get_mapped_query_response(query, question, new_query_response)
+            answer = AnswerResponse(**response.json())
+            self.repo.update_query(query_id, {"message": answer.response})
+            return MessageResponse(message=answer.response)
+
+    async def send_message(self, query_id: str, organization: OrganizationResponse):
+        query = self.repo.get_query(query_id)
+        question = self.repo.get_question(str(query.question_id))
+        answer = self.repo.get_answer(str(query.answer_id)) if query.answer_id else None
+
+        message = (
+            f":wave: Hello, <@{query.slack_info.user_id}>! An Admin has reviewed {query.display_id}.\n\n"
+            + f"Question: {question.question}\n\n"
+            + f"Response: {query.message or answer.response}\n\n"
+            + f":memo: *Generated SQL Query*: \n ```{answer.sql_query}```"
+        )
+
+        SlackWebClient(organization.slack_installation.bot.token).send_message(
+            query.slack_info.channel_id, query.slack_info.thread_ts, message
+        )
 
     def _get_mapped_query_response(
         self,
         query: Query,
         question: Question,
-        answer: BaseEngineAnswer = None,
+        answer: Answer = None,
     ) -> QueryResponse:
         if not answer:
-            answer = BaseEngineAnswer(
-                response_id=None,
-                question_id=query.question_id,
-                response=query.custom_response or "",
+            answer = Answer(
+                id=None,
+                question_id=question.id,
+                response=query.message or "",
                 sql_query="",
                 confidence_score=0,
             )
 
         return QueryResponse(
             id=str(query.id),
+            question_id=str(question.id),
+            answer_id=str(answer.id),
             username=query.slack_info.username or "unknown",
             question=question.question,
-            response=query.custom_response or answer.response,
+            response=query.message or answer.response,
             sql_query=answer.sql_query,
             sql_query_result=answer.sql_query_result,
             ai_process=answer.intermediate_steps or ["process unknown"],
@@ -463,7 +460,7 @@ def _get_mapped_query_response(
 
     def _convert_confidence_score(self, confidence_score: float) -> int:
         if not confidence_score:
-            return 0
+            return None
         if confidence_score > CONFIDENCE_CAP:
             return 95
         return int(confidence_score * 100)
diff --git a/apps/ai/server/modules/table_description/service.py b/apps/ai/server/modules/table_description/service.py
index a1facdeb..d4830941 100644
--- a/apps/ai/server/modules/table_description/service.py
+++ b/apps/ai/server/modules/table_description/service.py
@@ -23,9 +23,9 @@ async def get_table_descriptions(
     ) -> list[TableDescriptionResponse]:
         async with httpx.AsyncClient() as client:
             response = await client.get(
-                settings.k2_core_url + "/table-descriptions",
+                settings.engine_url + "/table-descriptions",
                 params={"db_connection_id": db_connection_id, "table_name": table_name},
-                timeout=settings.default_k2_core_timeout,
+                timeout=settings.default_engine_timeout,
             )
             raise_for_status(response.status_code, response.text)
 
@@ -46,8 +46,8 @@ async def get_table_description(
     ) -> TableDescriptionResponse:
         async with httpx.AsyncClient() as client:
             response = await client.get(
-                settings.k2_core_url + f"/table-descriptions/{table_description_id}",
-                timeout=settings.default_k2_core_timeout,
+                settings.engine_url + f"/table-descriptions/{table_description_id}",
+                timeout=settings.default_engine_timeout,
             )
             raise_for_status(response.status_code, response.text)
 
@@ -65,9 +65,9 @@ async def get_database_table_descriptions(self, db_connection_id: str):
 
         async with httpx.AsyncClient() as client:
             response = await client.get(
-                settings.k2_core_url + "/table-descriptions",
+                settings.engine_url + "/table-descriptions",
                 params={"db_connection_id": db_connection_id, "table_name": ""},
-                timeout=settings.default_k2_core_timeout,
+                timeout=settings.default_engine_timeout,
             )
             raise_for_status(response.status_code, response.text)
 
@@ -99,9 +99,9 @@ async def get_database_table_descriptions(self, db_connection_id: str):
     async def sync_table_descriptions_schemas(self, scan_request: ScanRequest) -> bool:
         async with httpx.AsyncClient() as client:
             response = await client.post(
-                settings.k2_core_url + "/table-descriptions/sync-schemas",
+                settings.engine_url + "/table-descriptions/sync-schemas",
                 json=scan_request.dict(),
-                timeout=settings.default_k2_core_timeout,
+                timeout=settings.default_engine_timeout,
             )
             raise_for_status(response.status_code, response.text)
             return response.json()
@@ -113,7 +113,7 @@ async def update_table_description(
     ) -> TableDescriptionResponse:
         async with httpx.AsyncClient() as client:
             response = await client.patch(
-                settings.k2_core_url + f"/table-descriptions/{table_description_id}",
+                settings.engine_url + f"/table-descriptions/{table_description_id}",
                 json=table_description_request.dict(exclude_unset=True),
             )
             raise_for_status(response.status_code, response.text)
@@ -122,7 +122,7 @@ async def update_table_description(
     async def delete_table_description(self, table_description_id: str):
         async with httpx.AsyncClient() as client:
             response = await client.delete(
-                settings.k2_core_url + f"/table-descriptions/{table_description_id}",
+                settings.engine_url + f"/table-descriptions/{table_description_id}",
             )
             raise_for_status(response.status_code, response.text)
             return True
diff --git a/apps/ai/server/tests/golden_sql/test_golden_sql_api.py b/apps/ai/server/tests/golden_sql/test_golden_sql_api.py
index 5d89783c..e6dc0061 100644
--- a/apps/ai/server/tests/golden_sql/test_golden_sql_api.py
+++ b/apps/ai/server/tests/golden_sql/test_golden_sql_api.py
@@ -171,6 +171,7 @@ def test_add_golden_sql(self):
         get_golden_sql_ref=Mock(return_value=GoldenSQLRef(**test_ref_1)),
         delete_verified_golden_sql_ref=Mock(return_value=1),
         delete_golden_sql_ref=Mock(return_value=1),
+        update_query_status=Mock(return_value=None),
     )
     def test_delete_golden_sql(self):
         response = client.delete(
diff --git a/apps/ai/server/tests/query/test_query_api.py b/apps/ai/server/tests/query/test_query_api.py
index f9421e06..850fba46 100644
--- a/apps/ai/server/tests/query/test_query_api.py
+++ b/apps/ai/server/tests/query/test_query_api.py
@@ -10,7 +10,7 @@
 from modules.db_connection.models.responses import DBConnectionResponse
 from modules.organization.models.entities import SlackBot, SlackInstallation
 from modules.organization.models.responses import OrganizationResponse
-from modules.query.models.entities import Query
+from modules.query.models.entities import Query, Question
 from modules.user.models.responses import UserResponse
 
 client = TestClient(app)
@@ -21,7 +21,7 @@
     "utils.auth.Authorize",
     user=Mock(
         return_value=UserResponse(
-            id="123",
+            id="0123456789ab0123456789ab",
             email="test@gmail.com",
             username="test_user",
             organization_id="0123456789ab0123456789ab",
@@ -84,11 +84,11 @@ class TestQueryAPI(TestCase):
 
     test_ref_1 = {
         "_id": ObjectId(b"doo-ree-miii"),
-        "response_id": test_0["_id"],
+        "answer_id": test_0["_id"],
         "question_id": test_question["_id"],
         "question_date": "2023-09-15 21:14:29",
         "status": "NOT_VERIFIED",
-        "custom_response": None,
+        "message": None,
         "last_updated": "2023-09-15 21:14:29",
         "updated_by": None,
         "organization_id": ObjectId(b"foo-bar-quux"),
@@ -123,6 +123,8 @@ class TestQueryAPI(TestCase):
         "last_updated": test_ref_1["last_updated"],
         "updated_by": None,
         "sql_error_message": "test_error",
+        "question_id": str(test_question["_id"]),
+        "answer_id": str(test_0["_id"]),
         **test_list_response_1,
     }
 
@@ -135,6 +137,10 @@ class TestQueryAPI(TestCase):
         "is_above_confidence_threshold": False,
     }
 
+    test_message_response_1 = {
+        "message": "test_response",
+    }
+
     @patch(
         "httpx.AsyncClient.post",
         AsyncMock(return_value=Response(status_code=201, json=test_response_0)),
@@ -218,29 +224,37 @@ def test_get_query(self):
         assert response.json() == self.test_response_1
 
     @patch(
-        "modules.organization.service.OrganizationService.get_organization",
-        Mock(return_value={"id": "666f6f2d6261722d71757578"}),
+        "httpx.AsyncClient.post",
+        AsyncMock(return_value=Response(201, json=test_response_0)),
     )
-    @patch(
-        "modules.query.service.QueryService.patch_response",
-        AsyncMock(return_value=test_response_1),
+    @patch.multiple(
+        "modules.query.repository.QueryRepository",
+        get_query=Mock(return_value=Query(**test_ref_1)),
+        get_question=Mock(return_value=Question(**test_question)),
+        update_query=Mock(return_value=None),
     )
-    def test_patch_response(self):
-        response = client.patch(
-            self.url + "/666f6f2d6261722d71757578",
+    def test_generate_sql_answer(self):
+        response = client.post(
+            self.url + "/666f6f2d6261722d71757578/sql-answer",
             headers=self.test_header,
-            json={"sql_query": "test_query", "query_status": "VERIFIED"},
+            json={"sql_query": "test_query"},
         )
-        assert response.status_code == status.HTTP_200_OK
+        assert response.status_code == status.HTTP_201_CREATED
+        assert response.json() == self.test_response_1
 
     @patch(
-        "modules.query.service.QueryService.run_response",
-        AsyncMock(return_value=test_response_1),
+        "httpx.AsyncClient.patch",
+        AsyncMock(return_value=Response(200, json=test_response_0)),
     )
-    def test_run_response(self):
-        response = client.post(
-            self.url + "/666f6f2d6261722d71757578/answer",
+    @patch.multiple(
+        "modules.query.repository.QueryRepository",
+        get_query=Mock(return_value=Query(**test_ref_1)),
+        update_query=Mock(return_value=None),
+    )
+    def test_generate_message(self):
+        response = client.patch(
+            self.url + "/666f6f2d6261722d71757578/message",
             headers=self.test_header,
-            json={"sql_query": "test_query"},
         )
         assert response.status_code == status.HTTP_200_OK
+        assert response.json() == self.test_message_response_1
diff --git a/apps/ai/server/utils/slack.py b/apps/ai/server/utils/slack.py
index 20d780fd..d95f142f 100644
--- a/apps/ai/server/utils/slack.py
+++ b/apps/ai/server/utils/slack.py
@@ -2,8 +2,7 @@
 
 from slack_sdk import WebClient
 
-from modules.query.models.entities import Query
-from modules.query.models.responses import EngineAnswerResponse
+from modules.query.models.entities import Answer, Query, Question
 
 
 class SlackWebClient:
@@ -24,69 +23,69 @@ def send_message(self, channel_id: str, thread_ts: str, message: str):
 
     def send_verified_query_message(
         self,
-        query_ref: Query,
-        query_response: EngineAnswerResponse,
-        question: str,
+        query: Query,
+        question: Question,
+        answer: Answer,
     ):
         message_blocks = [
             {
                 "type": "section",
                 "text": {
                     "type": "mrkdwn",
-                    "text": f":wave: Hello, <@{query_ref.slack_info.user_id}>! Your query {query_ref.display_id} has been verified.",
+                    "text": f":wave: Hello, <@{query.slack_info.user_id}>! Your query {query.display_id} has been verified.",
                 },
             },
             {
                 "type": "section",
                 "text": {
                     "type": "mrkdwn",
-                    "text": f"Question: {question}",
+                    "text": f"Question: {question.question}",
                 },
             },
             {
                 "type": "section",
                 "text": {
                     "type": "mrkdwn",
-                    "text": f"Response: {query_ref.custom_response or query_response.response}",
+                    "text": f"Response: {query.message or answer.response}",
                 },
             },
             {
                 "type": "section",
                 "text": {
                     "type": "mrkdwn",
-                    "text": f":memo: *Generated SQL Query*: \n ```{query_response.sql_query}```",
+                    "text": f":memo: *Generated SQL Query*: \n ```{answer.sql_query}```",
                 },
             },
         ]
         self.client.chat_postMessage(
-            channel=query_ref.slack_info.channel_id,
-            thread_ts=query_ref.slack_info.thread_ts,
+            channel=query.slack_info.channel_id,
+            thread_ts=query.slack_info.thread_ts,
             blocks=message_blocks,
         )
 
     def send_rejected_query_message(
         self,
-        query_ref: Query,
+        query: Query,
     ):
         message_blocks = [
             {
                 "type": "section",
                 "text": {
                     "type": "mrkdwn",
-                    "text": f":wave: Hello, <@{query_ref.slack_info.user_id}>. Your query {query_ref.display_id} could not be answered.",
+                    "text": f":wave: Hello, <@{query.slack_info.user_id}>. Your query {query.display_id} could not be answered.",
                 },
             },
             {
                 "type": "section",
                 "text": {
                     "type": "mrkdwn",
-                    "text": f"Reason: {query_ref.custom_response}",
+                    "text": f"Reason: {query.message}",
                 },
             },
         ]
         self.client.chat_postMessage(
-            channel=query_ref.slack_info.channel_id,
-            thread_ts=query_ref.slack_info.thread_ts,
+            channel=query.slack_info.channel_id,
+            thread_ts=query.slack_info.thread_ts,
             blocks=message_blocks,
         )