diff --git a/frontend/src/components/Modals/MangeWorkspace/Documents/Directory/index.jsx b/frontend/src/components/Modals/MangeWorkspace/Documents/Directory/index.jsx
index af8ae32ab3fa33e055462d96093fce21766d673b..557fe418145a10ea1c63f4fe18b4c9731d15c2f8 100644
--- a/frontend/src/components/Modals/MangeWorkspace/Documents/Directory/index.jsx
+++ b/frontend/src/components/Modals/MangeWorkspace/Documents/Directory/index.jsx
@@ -1,10 +1,10 @@
 import UploadFile from "../UploadFile";
 import PreLoader from "@/components/Preloader";
-import { useEffect, useState } from "react";
+import { memo, useEffect, useState } from "react";
 import FolderRow from "./FolderRow";
 import pluralize from "pluralize";
 
-export default function Directory({
+function Directory({
   files,
   loading,
   setLoading,
@@ -146,3 +146,5 @@ export default function Directory({
     </div>
   );
 }
+
+export default memo(Directory);
diff --git a/frontend/src/components/Modals/MangeWorkspace/Documents/WorkspaceDirectory/WorkspaceFileRow/index.jsx b/frontend/src/components/Modals/MangeWorkspace/Documents/WorkspaceDirectory/WorkspaceFileRow/index.jsx
index 91e165d4c0bc3c95587457c35ffc12d8c2be3a4e..93b62cefe48d263454a152eeaccb64409d4e29d0 100644
--- a/frontend/src/components/Modals/MangeWorkspace/Documents/WorkspaceDirectory/WorkspaceFileRow/index.jsx
+++ b/frontend/src/components/Modals/MangeWorkspace/Documents/WorkspaceDirectory/WorkspaceFileRow/index.jsx
@@ -1,12 +1,19 @@
-import { useState } from "react";
+import { memo, useState } from "react";
 import {
   formatDate,
   getFileExtension,
   middleTruncate,
 } from "@/utils/directories";
-import { ArrowUUpLeft, File } from "@phosphor-icons/react";
+import {
+  ArrowUUpLeft,
+  File,
+  PushPin,
+  PushPinSlash,
+} from "@phosphor-icons/react";
 import Workspace from "@/models/workspace";
 import debounce from "lodash.debounce";
+import { Tooltip } from "react-tooltip";
+import showToast from "@/utils/toast";
 
 export default function WorkspaceFileRow({
   item,
@@ -80,21 +87,105 @@ export default function WorkspaceFileRow({
       <p className="col-span-2 pl-2 uppercase overflow-x-hidden">
         {getFileExtension(item.url)}
       </p>
-      <div className="col-span-2 flex justify-end items-center">
-        {item?.cached && (
-          <div className="bg-white/10 rounded-3xl">
-            <p className="text-xs px-2 py-0.5">Cached</p>
-          </div>
-        )}
+      <div className="col-span-2 flex justify-center items-center">
         {hasChanges ? (
           <div className="w-4 h-4 ml-2 flex-shrink-0" />
         ) : (
-          <ArrowUUpLeft
-            onClick={onRemoveClick}
-            className="text-base font-bold w-4 h-4 ml-2 flex-shrink-0 cursor-pointer"
-          />
+          <div className="flex gap-x-2 items-center">
+            <PinItemToWorkspace
+              workspace={workspace}
+              docPath={`${folderName}/${item.name}`} // how to find documents during pin/unpin
+              item={item}
+            />
+            <RemoveItemFromWorkspace item={item} onClick={onRemoveClick} />
+          </div>
         )}
       </div>
     </div>
   );
 }
+
+const PinItemToWorkspace = memo(({ workspace, docPath, item }) => {
+  const [pinned, setPinned] = useState(
+    item?.pinnedWorkspaces?.includes(workspace.id) || false
+  );
+  const [hover, setHover] = useState(false);
+  const pinEvent = new CustomEvent("pinned_document");
+
+  const updatePinStatus = async () => {
+    try {
+      if (!pinned) window.dispatchEvent(pinEvent);
+      const success = await Workspace.setPinForDocument(
+        workspace.slug,
+        docPath,
+        !pinned
+      );
+
+      if (!success) {
+        showToast(`Failed to ${!pinned ? "pin" : "unpin"} document.`, "error", {
+          clear: true,
+        });
+        return;
+      }
+
+      showToast(
+        `Document ${!pinned ? "pinned to" : "unpinned from"} workspace`,
+        "success",
+        { clear: true }
+      );
+      setPinned(!pinned);
+    } catch (error) {
+      showToast(`Failed to pin document. ${error.message}`, "error", {
+        clear: true,
+      });
+      return;
+    }
+  };
+
+  if (!item) return <div />;
+
+  const PinIcon = pinned ? PushPinSlash : PushPin;
+  return (
+    <div
+      onMouseEnter={() => setHover(true)}
+      onMouseLeave={() => setHover(false)}
+    >
+      <PinIcon
+        data-tooltip-id={`pin-${item.id}`}
+        data-tooltip-content={
+          pinned ? "Unpin document from workspace" : "Pin document to workspace"
+        }
+        onClick={updatePinStatus}
+        weight={hover ? "fill" : "regular"}
+        className={`outline-none text-base font-bold w-4 h-4 ml-2 flex-shrink-0 cursor-pointer ${
+          pinned ? "hover:text-red-300" : ""
+        }`}
+      />
+      <Tooltip
+        id={`pin-${item.id}`}
+        place="bottom"
+        delayShow={300}
+        className="tooltip !text-xs"
+      />
+    </div>
+  );
+});
+
+const RemoveItemFromWorkspace = ({ item, onClick }) => {
+  return (
+    <div>
+      <ArrowUUpLeft
+        data-tooltip-id={`remove-${item.id}`}
+        data-tooltip-content="Remove document from workspace"
+        onClick={onClick}
+        className="text-base font-bold w-4 h-4 ml-2 flex-shrink-0 cursor-pointer"
+      />
+      <Tooltip
+        id={`remove-${item.id}`}
+        place="bottom"
+        delayShow={300}
+        className="tooltip !text-xs"
+      />
+    </div>
+  );
+};
diff --git a/frontend/src/components/Modals/MangeWorkspace/Documents/WorkspaceDirectory/index.jsx b/frontend/src/components/Modals/MangeWorkspace/Documents/WorkspaceDirectory/index.jsx
index 12080b9b217670ab8c3b57d448c466740c9b2b34..2232e746c6add8ec276bc36dd1dffcc94d2b848c 100644
--- a/frontend/src/components/Modals/MangeWorkspace/Documents/WorkspaceDirectory/index.jsx
+++ b/frontend/src/components/Modals/MangeWorkspace/Documents/WorkspaceDirectory/index.jsx
@@ -1,8 +1,12 @@
 import PreLoader from "@/components/Preloader";
 import { dollarFormat } from "@/utils/numbers";
 import WorkspaceFileRow from "./WorkspaceFileRow";
+import { memo, useEffect, useState } from "react";
+import ModalWrapper from "@/components/ModalWrapper";
+import { PushPin } from "@phosphor-icons/react";
+import { SEEN_DOC_PIN_ALERT } from "@/utils/constants";
 
-export default function WorkspaceDirectory({
+function WorkspaceDirectory({
   workspace,
   files,
   highlightWorkspace,
@@ -29,7 +33,7 @@ export default function WorkspaceDirectory({
             <p className="col-span-5">Name</p>
             <p className="col-span-3">Date</p>
             <p className="col-span-2">Kind</p>
-            <p className="col-span-2">Cached</p>
+            <p className="col-span-2" />
           </div>
           <div className="w-full h-full flex items-center justify-center flex-col gap-y-5">
             <PreLoader />
@@ -43,78 +47,145 @@ export default function WorkspaceDirectory({
   }
 
   return (
-    <div className="px-8">
-      <div className="flex items-center justify-start w-[560px]">
-        <h3 className="text-white text-base font-bold ml-5">
-          {workspace.name}
-        </h3>
-      </div>
-      <div
-        className={`relative w-[560px] h-[445px] bg-zinc-900 rounded-2xl mt-5 overflow-y-auto border-4 transition-all duration-300 ${
-          highlightWorkspace ? "border-cyan-300/80" : "border-transparent"
-        }`}
-      >
-        <div className="text-white/80 text-xs grid grid-cols-12 py-2 px-8 border-b border-white/20 bg-zinc-900 sticky top-0 z-10">
-          <p className="col-span-5">Name</p>
-          <p className="col-span-3">Date</p>
-          <p className="col-span-2">Kind</p>
-          <p className="col-span-2">Cached</p>
+    <>
+      <div className="px-8">
+        <div className="flex items-center justify-start w-[560px]">
+          <h3 className="text-white text-base font-bold ml-5">
+            {workspace.name}
+          </h3>
+        </div>
+        <div
+          className={`relative w-[560px] h-[445px] bg-zinc-900 rounded-2xl mt-5 overflow-y-auto border-4 transition-all duration-300 ${
+            highlightWorkspace ? "border-cyan-300/80" : "border-transparent"
+          }`}
+        >
+          <div className="text-white/80 text-xs grid grid-cols-12 py-2 px-8 border-b border-white/20 bg-zinc-900 sticky top-0 z-10">
+            <p className="col-span-5">Name</p>
+            <p className="col-span-3">Date</p>
+            <p className="col-span-2">Kind</p>
+            <p className="col-span-2" />
+          </div>
+          <div className="w-full h-full flex flex-col z-0">
+            {Object.values(files.items).some(
+              (folder) => folder.items.length > 0
+            ) || movedItems.length > 0 ? (
+              <>
+                {files.items.map((folder) =>
+                  folder.items.map((item, index) => (
+                    <WorkspaceFileRow
+                      key={index}
+                      item={item}
+                      folderName={folder.name}
+                      workspace={workspace}
+                      setLoading={setLoading}
+                      setLoadingMessage={setLoadingMessage}
+                      fetchKeys={fetchKeys}
+                      hasChanges={hasChanges}
+                      movedItems={movedItems}
+                    />
+                  ))
+                )}
+              </>
+            ) : (
+              <div className="w-full h-full flex items-center justify-center">
+                <p className="text-white text-opacity-40 text-sm font-medium">
+                  No Documents
+                </p>
+              </div>
+            )}
+          </div>
         </div>
-        <div className="w-full h-full flex flex-col z-0">
-          {Object.values(files.items).some(
-            (folder) => folder.items.length > 0
-          ) || movedItems.length > 0 ? (
-            <>
-              {files.items.map((folder) =>
-                folder.items.map((item, index) => (
-                  <WorkspaceFileRow
-                    key={index}
-                    item={item}
-                    folderName={folder.name}
-                    workspace={workspace}
-                    setLoading={setLoading}
-                    setLoadingMessage={setLoadingMessage}
-                    fetchKeys={fetchKeys}
-                    hasChanges={hasChanges}
-                    movedItems={movedItems}
-                  />
-                ))
-              )}
-            </>
-          ) : (
-            <div className="w-full h-full flex items-center justify-center">
-              <p className="text-white text-opacity-40 text-sm font-medium">
-                No Documents
+        {hasChanges && (
+          <div className="flex items-center justify-between py-6 transition-all duration-300">
+            <div className="text-white/80">
+              <p className="text-sm font-semibold">
+                {embeddingCosts === 0
+                  ? ""
+                  : `Estimated Cost: ${
+                      embeddingCosts < 0.01
+                        ? `< $0.01`
+                        : dollarFormat(embeddingCosts)
+                    }`}
+              </p>
+              <p className="mt-2 text-xs italic" hidden={embeddingCosts === 0}>
+                *One time cost for embeddings
               </p>
             </div>
-          )}
-        </div>
+
+            <button
+              onClick={saveChanges}
+              className="transition-all duration-300 border border-slate-200 px-5 py-2.5 rounded-lg text-white text-sm items-center flex gap-x-2 hover:bg-slate-200 hover:text-slate-800 focus:ring-gray-800"
+            >
+              Save and Embed
+            </button>
+          </div>
+        )}
       </div>
-      {hasChanges && (
-        <div className="flex items-center justify-between py-6 transition-all duration-300">
-          <div className="text-white/80">
-            <p className="text-sm font-semibold">
-              {embeddingCosts === 0
-                ? ""
-                : `Estimated Cost: ${
-                    embeddingCosts < 0.01
-                      ? `< $0.01`
-                      : dollarFormat(embeddingCosts)
-                  }`}
+      <PinAlert />
+    </>
+  );
+}
+
+const PinAlert = memo(() => {
+  const [showAlert, setShowAlert] = useState(false);
+  function dismissAlert() {
+    setShowAlert(false);
+    window.localStorage.setItem(SEEN_DOC_PIN_ALERT, "1");
+    window.removeEventListener(handlePinEvent);
+  }
+
+  function handlePinEvent() {
+    if (!!window?.localStorage?.getItem(SEEN_DOC_PIN_ALERT)) return;
+    setShowAlert(true);
+  }
+
+  useEffect(() => {
+    if (!window || !!window?.localStorage?.getItem(SEEN_DOC_PIN_ALERT)) return;
+    window?.addEventListener("pinned_document", handlePinEvent);
+  }, []);
+
+  return (
+    <ModalWrapper isOpen={showAlert}>
+      <div className="relative w-full max-w-2xl max-h-full">
+        <div className="relative bg-main-gradient rounded-lg shadow">
+          <div className="flex items-start justify-between p-4 border-b rounded-t border-gray-500/50">
+            <div className="flex items-center gap-2">
+              <PushPin className="text-red-600 text-lg w-6 h-6" weight="fill" />
+              <h3 className="text-xl font-semibold text-white">
+                What is document pinning?
+              </h3>
+            </div>
+          </div>
+          <div className="w-full p-6 text-white text-md flex flex-col gap-y-2">
+            <p>
+              When you <b>pin</b> a document in AnythingLLM we will inject the
+              entire content of the document into your prompt window for your
+              LLM to fully comprehend.
+            </p>
+            <p>
+              This works best with <b>large-context models</b> or small files
+              that are critical to its knowledge-base.
             </p>
-            <p className="mt-2 text-xs italic" hidden={embeddingCosts === 0}>
-              *One time cost for embeddings
+            <p>
+              If you are not getting the answers you desire from AnythingLLM by
+              default then pinning is a great way to get higher quality answers
+              in a click.
             </p>
           </div>
 
-          <button
-            onClick={saveChanges}
-            className="transition-all duration-300 border border-slate-200 px-5 py-2.5 rounded-lg text-white text-sm items-center flex gap-x-2 hover:bg-slate-200 hover:text-slate-800 focus:ring-gray-800"
-          >
-            Save and Embed
-          </button>
+          <div className="flex w-full justify-between items-center p-6 space-x-2 border-t rounded-b border-gray-500/50">
+            <button disabled={true} className="invisible" />
+            <button
+              onClick={dismissAlert}
+              className="transition-all duration-300 border border-slate-200 px-4 py-2 rounded-lg text-white text-sm items-center flex gap-x-2 hover:bg-slate-200 hover:text-slate-800 focus:ring-gray-800"
+            >
+              Okay, got it
+            </button>
+          </div>
         </div>
-      )}
-    </div>
+      </div>
+    </ModalWrapper>
   );
-}
+});
+
+export default memo(WorkspaceDirectory);
diff --git a/frontend/src/components/Modals/MangeWorkspace/Documents/index.jsx b/frontend/src/components/Modals/MangeWorkspace/Documents/index.jsx
index 705e78faae76f62c04ff341b7021fe2e3e5287d0..e8b63c903ca7c6981db6dbe4aa715fb1602acee0 100644
--- a/frontend/src/components/Modals/MangeWorkspace/Documents/index.jsx
+++ b/frontend/src/components/Modals/MangeWorkspace/Documents/index.jsx
@@ -2,8 +2,8 @@ import { ArrowsDownUp } from "@phosphor-icons/react";
 import { useEffect, useState } from "react";
 import Workspace from "../../../../models/workspace";
 import System from "../../../../models/system";
-import Directory from "./Directory";
 import showToast from "../../../../utils/toast";
+import Directory from "./Directory";
 import WorkspaceDirectory from "./WorkspaceDirectory";
 
 // OpenAI Cost per token
diff --git a/frontend/src/models/workspace.js b/frontend/src/models/workspace.js
index d77e2ad5592b248333db683f66855a0c84862fc3..d003887433d2521248a0a68345331db66d2ad87d 100644
--- a/frontend/src/models/workspace.js
+++ b/frontend/src/models/workspace.js
@@ -218,6 +218,25 @@ const Workspace = {
         return { success: false, error: e.message };
       });
   },
+  setPinForDocument: async function (slug, docPath, pinStatus) {
+    return fetch(`${API_BASE}/workspace/${slug}/update-pin`, {
+      method: "POST",
+      headers: baseHeaders(),
+      body: JSON.stringify({ docPath, pinStatus }),
+    })
+      .then((res) => {
+        if (!res.ok) {
+          throw new Error(
+            res.statusText || "Error setting pin status for document."
+          );
+        }
+        return true;
+      })
+      .catch((e) => {
+        console.error(e);
+        return false;
+      });
+  },
   threads: WorkspaceThread,
 };
 
diff --git a/frontend/src/utils/constants.js b/frontend/src/utils/constants.js
index 2fde1ee003663e4c0292df221443cca275d8bb6e..6fd29534c2f29cfc5cedd23a80555b34086267f7 100644
--- a/frontend/src/utils/constants.js
+++ b/frontend/src/utils/constants.js
@@ -4,6 +4,7 @@ export const AUTH_USER = "anythingllm_user";
 export const AUTH_TOKEN = "anythingllm_authToken";
 export const AUTH_TIMESTAMP = "anythingllm_authTimestamp";
 export const COMPLETE_QUESTIONNAIRE = "anythingllm_completed_questionnaire";
+export const SEEN_DOC_PIN_ALERT = "anythingllm_pinned_document_alert";
 
 export const USER_BACKGROUND_COLOR = "bg-historical-msg-user";
 export const AI_BACKGROUND_COLOR = "bg-historical-msg-system";
diff --git a/server/endpoints/workspaces.js b/server/endpoints/workspaces.js
index 82040272a88010d355056cf354a0dafbbc7429b9..54228bba0e59b7cd7ae29a85a7a5f6f72c6d2331 100644
--- a/server/endpoints/workspaces.js
+++ b/server/endpoints/workspaces.js
@@ -395,6 +395,33 @@ function workspaceEndpoints(app) {
       }
     }
   );
+
+  app.post(
+    "/workspace/:slug/update-pin",
+    [
+      validatedRequest,
+      flexUserRoleValid([ROLES.admin, ROLES.manager]),
+      validWorkspaceSlug,
+    ],
+    async (request, response) => {
+      try {
+        const { docPath, pinStatus = false } = reqBody(request);
+        const workspace = response.locals.workspace;
+
+        const document = await Document.get({
+          workspaceId: workspace.id,
+          docpath: docPath,
+        });
+        if (!document) return response.sendStatus(404).end();
+
+        await Document.update(document.id, { pinned: pinStatus });
+        return response.status(200).end();
+      } catch (error) {
+        console.error("Error processing the pin status update:", error);
+        return response.status(500).end();
+      }
+    }
+  );
 }
 
 module.exports = { workspaceEndpoints };
diff --git a/server/models/documents.js b/server/models/documents.js
index 9f50aa9159c2f9cbc3eec065affdfbb40c001bd8..aa62ccf668f68c2a196dbb4c3af450c5beeace00 100644
--- a/server/models/documents.js
+++ b/server/models/documents.js
@@ -1,4 +1,3 @@
-const { fileData } = require("../utils/files");
 const { v4: uuidv4 } = require("uuid");
 const { getVectorDbClass } = require("../utils/helpers");
 const prisma = require("../utils/prisma");
@@ -6,6 +5,8 @@ const { Telemetry } = require("./telemetry");
 const { EventLogs } = require("./eventLogs");
 
 const Document = {
+  writable: ["pinned"],
+
   forWorkspace: async function (workspaceId = null) {
     if (!workspaceId) return [];
     return await prisma.workspace_documents.findMany({
@@ -23,7 +24,7 @@ const Document = {
     }
   },
 
-  firstWhere: async function (clause = {}) {
+  get: async function (clause = {}) {
     try {
       const document = await prisma.workspace_documents.findFirst({
         where: clause,
@@ -35,9 +36,39 @@ const Document = {
     }
   },
 
+  getPins: async function (clause = {}) {
+    try {
+      const workspaceIds = await prisma.workspace_documents.findMany({
+        where: clause,
+        select: {
+          workspaceId: true,
+        },
+      });
+      return workspaceIds.map((pin) => pin.workspaceId) || [];
+    } catch (error) {
+      console.error(error.message);
+      return [];
+    }
+  },
+
+  where: async function (clause = {}, limit = null, orderBy = null) {
+    try {
+      const results = await prisma.workspace_documents.findMany({
+        where: clause,
+        ...(limit !== null ? { take: limit } : {}),
+        ...(orderBy !== null ? { orderBy } : {}),
+      });
+      return results;
+    } catch (error) {
+      console.error(error.message);
+      return [];
+    }
+  },
+
   addDocuments: async function (workspace, additions = [], userId = null) {
     const VectorDb = getVectorDbClass();
     if (additions.length === 0) return { failed: [], embedded: [] };
+    const { fileData } = require("../utils/files");
     const embedded = [];
     const failedToEmbed = [];
     const errors = new Set();
@@ -101,7 +132,7 @@ const Document = {
     if (removals.length === 0) return;
 
     for (const path of removals) {
-      const document = await this.firstWhere({
+      const document = await this.get({
         docpath: path,
         workspaceId: workspace.id,
       });
@@ -151,6 +182,26 @@ const Document = {
       return 0;
     }
   },
+  update: async function (id = null, data = {}) {
+    if (!id) throw new Error("No workspace document id provided for update");
+
+    const validKeys = Object.keys(data).filter((key) =>
+      this.writable.includes(key)
+    );
+    if (validKeys.length === 0)
+      return { document: { id }, message: "No valid fields to update!" };
+
+    try {
+      const document = await prisma.workspace_documents.update({
+        where: { id },
+        data,
+      });
+      return { document, message: null };
+    } catch (error) {
+      console.error(error.message);
+      return { document: null, message: error.message };
+    }
+  },
 };
 
 module.exports = { Document };
diff --git a/server/prisma/migrations/20240219211018_init/migration.sql b/server/prisma/migrations/20240219211018_init/migration.sql
new file mode 100644
index 0000000000000000000000000000000000000000..98e8b24ad55b2c4964ebef2f26e909e8793675c6
--- /dev/null
+++ b/server/prisma/migrations/20240219211018_init/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "workspace_documents" ADD COLUMN "pinned" BOOLEAN DEFAULT false;
diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma
index 77b25c8de741f61159958995c9197d00fce51484..8cd3a1d343d4799335d4aca9ceedc900ef94b6b3 100644
--- a/server/prisma/schema.prisma
+++ b/server/prisma/schema.prisma
@@ -30,6 +30,7 @@ model workspace_documents {
   docpath       String
   workspaceId   Int
   metadata      String?
+  pinned        Boolean?   @default(false)
   createdAt     DateTime   @default(now())
   lastUpdatedAt DateTime   @default(now())
   workspace     workspaces @relation(fields: [workspaceId], references: [id])
diff --git a/server/utils/AiProviders/openAi/index.js b/server/utils/AiProviders/openAi/index.js
index c3c983f8d25b97167ca8060ab3196421a3a686b3..d4dc14dc63bc119802ff751c1dc814f11459156a 100644
--- a/server/utils/AiProviders/openAi/index.js
+++ b/server/utils/AiProviders/openAi/index.js
@@ -195,11 +195,15 @@ class OpenAiLLM {
         `OpenAI chat: ${this.model} is not valid for chat completion!`
       );
 
-    const { data } = await this.openai.createChatCompletion({
-      model: this.model,
-      messages,
-      temperature,
-    });
+    const { data } = await this.openai
+      .createChatCompletion({
+        model: this.model,
+        messages,
+        temperature,
+      })
+      .catch((e) => {
+        throw new Error(e.response.data.error.message);
+      });
 
     if (!data.hasOwnProperty("choices")) return null;
     return data.choices[0].message.content;
diff --git a/server/utils/DocumentManager/index.js b/server/utils/DocumentManager/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..17fd9860ee2b2acd86b80c9cc07a969788fee8aa
--- /dev/null
+++ b/server/utils/DocumentManager/index.js
@@ -0,0 +1,72 @@
+const fs = require("fs");
+const path = require("path");
+
+const documentsPath =
+  process.env.NODE_ENV === "development"
+    ? path.resolve(__dirname, `../../storage/documents`)
+    : path.resolve(process.env.STORAGE_DIR, `documents`);
+
+class DocumentManager {
+  constructor({ workspace = null, maxTokens = null }) {
+    this.workspace = workspace;
+    this.maxTokens = maxTokens || Number.POSITIVE_INFINITY;
+    this.documentStoragePath = documentsPath;
+  }
+
+  log(text, ...args) {
+    console.log(`\x1b[36m[DocumentManager]\x1b[0m ${text}`, ...args);
+  }
+
+  async pinnedDocuments() {
+    if (!this.workspace) return [];
+    const { Document } = require("../../models/documents");
+    return await Document.where({
+      workspaceId: Number(this.workspace.id),
+      pinned: true,
+    });
+  }
+
+  async pinnedDocs() {
+    if (!this.workspace) return [];
+    const docPaths = (await this.pinnedDocuments()).map((doc) => doc.docpath);
+    if (docPaths.length === 0) return [];
+
+    let tokens = 0;
+    const pinnedDocs = [];
+    for await (const docPath of docPaths) {
+      try {
+        const filePath = path.resolve(this.documentStoragePath, docPath);
+        const data = JSON.parse(
+          fs.readFileSync(filePath, { encoding: "utf-8" })
+        );
+
+        if (
+          !data.hasOwnProperty("pageContent") ||
+          !data.hasOwnProperty("token_count_estimate")
+        ) {
+          this.log(
+            `Skipping document - Could not find page content or token_count_estimate in pinned source.`
+          );
+          continue;
+        }
+
+        if (tokens >= this.maxTokens) {
+          this.log(
+            `Skipping document - Token limit of ${this.maxTokens} has already been exceeded by pinned documents.`
+          );
+          continue;
+        }
+
+        pinnedDocs.push(data);
+        tokens += data.token_count_estimate || 0;
+      } catch {}
+    }
+
+    this.log(
+      `Found ${pinnedDocs.length} pinned sources - prepending to content with ~${tokens} tokens of content.`
+    );
+    return pinnedDocs;
+  }
+}
+
+module.exports.DocumentManager = DocumentManager;
diff --git a/server/utils/chats/embed.js b/server/utils/chats/embed.js
index 7a4c52d1770dc130d9a5db7c83e649f226d20781..f748a3a5d3038308cb218103ed46c4da5fe529a6 100644
--- a/server/utils/chats/embed.js
+++ b/server/utils/chats/embed.js
@@ -6,6 +6,7 @@ const {
   convertToPromptHistory,
   writeResponseChunk,
 } = require("../helpers/chat/responses");
+const { DocumentManager } = require("../DocumentManager");
 
 async function streamChatWithForEmbed(
   response,
@@ -64,6 +65,8 @@ async function streamChatWithForEmbed(
   }
 
   let completeText;
+  let contextTexts = [];
+  let sources = [];
   const { rawHistory, chatHistory } = await recentEmbedChatHistory(
     sessionId,
     embed,
@@ -71,26 +74,43 @@ async function streamChatWithForEmbed(
     chatMode
   );
 
-  const {
-    contextTexts = [],
-    sources = [],
-    message: error,
-  } = embeddingsCount !== 0 // if there no embeddings don't bother searching.
-    ? await VectorDb.performSimilaritySearch({
-        namespace: embed.workspace.slug,
-        input: message,
-        LLMConnector,
-        similarityThreshold: embed.workspace?.similarityThreshold,
-        topN: embed.workspace?.topN,
-      })
-    : {
-        contextTexts: [],
-        sources: [],
-        message: null,
-      };
-
-  // Failed similarity search.
-  if (!!error) {
+  // Look for pinned documents and see if the user decided to use this feature. We will also do a vector search
+  // as pinning is a supplemental tool but it should be used with caution since it can easily blow up a context window.
+  await new DocumentManager({
+    workspace: embed.workspace,
+    maxTokens: LLMConnector.limits.system,
+  })
+    .pinnedDocs()
+    .then((pinnedDocs) => {
+      pinnedDocs.forEach((doc) => {
+        const { pageContent, ...metadata } = doc;
+        contextTexts.push(doc.pageContent);
+        sources.push({
+          text:
+            pageContent.slice(0, 1_000) +
+            "...continued on in source document...",
+          ...metadata,
+        });
+      });
+    });
+
+  const vectorSearchResults =
+    embeddingsCount !== 0
+      ? await VectorDb.performSimilaritySearch({
+          namespace: embed.workspace.slug,
+          input: message,
+          LLMConnector,
+          similarityThreshold: embed.workspace?.similarityThreshold,
+          topN: embed.workspace?.topN,
+        })
+      : {
+          contextTexts: [],
+          sources: [],
+          message: null,
+        };
+
+  // Failed similarity search if it was run at all and failed.
+  if (!!vectorSearchResults.message) {
     writeResponseChunk(response, {
       id: uuid,
       type: "abort",
@@ -102,6 +122,9 @@ async function streamChatWithForEmbed(
     return;
   }
 
+  contextTexts = [...contextTexts, ...vectorSearchResults.contextTexts];
+  sources = [...sources, ...vectorSearchResults.sources];
+
   // If in query mode and no sources are found, do not
   // let the LLM try to hallucinate a response or use general knowledge
   if (chatMode === "query" && sources.length === 0) {
diff --git a/server/utils/chats/index.js b/server/utils/chats/index.js
index 6d8cccf9a11a3eed9c9b432bc9dbb6de7861ec2f..10df9983f071cd357f16a79723d6bc8ed3901355 100644
--- a/server/utils/chats/index.js
+++ b/server/utils/chats/index.js
@@ -3,6 +3,7 @@ const { WorkspaceChats } = require("../../models/workspaceChats");
 const { resetMemory } = require("./commands/reset");
 const { getVectorDbClass, getLLMProvider } = require("../helpers");
 const { convertToPromptHistory } = require("../helpers/chat/responses");
+const { DocumentManager } = require("../DocumentManager");
 
 const VALID_COMMANDS = {
   "/reset": resetMemory,
@@ -73,6 +74,8 @@ async function chatWithWorkspace(
   // If we are here we know that we are in a workspace that is:
   // 1. Chatting in "chat" mode and may or may _not_ have embeddings
   // 2. Chatting in "query" mode and has at least 1 embedding
+  let contextTexts = [];
+  let sources = [];
   const { rawHistory, chatHistory } = await recentChatHistory({
     user,
     workspace,
@@ -81,36 +84,56 @@ async function chatWithWorkspace(
     chatMode,
   });
 
-  const {
-    contextTexts = [],
-    sources = [],
-    message: error,
-  } = embeddingsCount !== 0 // if there no embeddings don't bother searching.
-    ? await VectorDb.performSimilaritySearch({
-        namespace: workspace.slug,
-        input: message,
-        LLMConnector,
-        similarityThreshold: workspace?.similarityThreshold,
-        topN: workspace?.topN,
-      })
-    : {
-        contextTexts: [],
-        sources: [],
-        message: null,
-      };
+  // Look for pinned documents and see if the user decided to use this feature. We will also do a vector search
+  // as pinning is a supplemental tool but it should be used with caution since it can easily blow up a context window.
+  await new DocumentManager({
+    workspace,
+    maxTokens: LLMConnector.limits.system,
+  })
+    .pinnedDocs()
+    .then((pinnedDocs) => {
+      pinnedDocs.forEach((doc) => {
+        const { pageContent, ...metadata } = doc;
+        contextTexts.push(doc.pageContent);
+        sources.push({
+          text:
+            pageContent.slice(0, 1_000) +
+            "...continued on in source document...",
+          ...metadata,
+        });
+      });
+    });
+
+  const vectorSearchResults =
+    embeddingsCount !== 0
+      ? await VectorDb.performSimilaritySearch({
+          namespace: workspace.slug,
+          input: message,
+          LLMConnector,
+          similarityThreshold: workspace?.similarityThreshold,
+          topN: workspace?.topN,
+        })
+      : {
+          contextTexts: [],
+          sources: [],
+          message: null,
+        };
 
   // Failed similarity search if it was run at all and failed.
-  if (!!error) {
+  if (!!vectorSearchResults.message) {
     return {
       id: uuid,
       type: "abort",
       textResponse: null,
       sources: [],
       close: true,
-      error,
+      error: vectorSearchResults.message,
     };
   }
 
+  contextTexts = [...contextTexts, ...vectorSearchResults.contextTexts];
+  sources = [...sources, ...vectorSearchResults.sources];
+
   // If in query mode and no sources are found, do not
   // let the LLM try to hallucinate a response or use general knowledge and exit early
   if (chatMode === "query" && sources.length === 0) {
diff --git a/server/utils/chats/stream.js b/server/utils/chats/stream.js
index 4f86c49d6d0f0b9efc45e29b436c0c1beb383e26..f1a335bc8ea2161ee91409cc39884def3d30c7eb 100644
--- a/server/utils/chats/stream.js
+++ b/server/utils/chats/stream.js
@@ -1,4 +1,5 @@
 const { v4: uuidv4 } = require("uuid");
+const { DocumentManager } = require("../DocumentManager");
 const { WorkspaceChats } = require("../../models/workspaceChats");
 const { getVectorDbClass, getLLMProvider } = require("../helpers");
 const { writeResponseChunk } = require("../helpers/chat/responses");
@@ -74,6 +75,8 @@ async function streamChatWithWorkspace(
   // 1. Chatting in "chat" mode and may or may _not_ have embeddings
   // 2. Chatting in "query" mode and has at least 1 embedding
   let completeText;
+  let contextTexts = [];
+  let sources = [];
   const { rawHistory, chatHistory } = await recentChatHistory({
     user,
     workspace,
@@ -82,37 +85,57 @@ async function streamChatWithWorkspace(
     chatMode,
   });
 
-  const {
-    contextTexts = [],
-    sources = [],
-    message: error,
-  } = embeddingsCount !== 0 // if there no embeddings don't bother searching.
-    ? await VectorDb.performSimilaritySearch({
-        namespace: workspace.slug,
-        input: message,
-        LLMConnector,
-        similarityThreshold: workspace?.similarityThreshold,
-        topN: workspace?.topN,
-      })
-    : {
-        contextTexts: [],
-        sources: [],
-        message: null,
-      };
+  // Look for pinned documents and see if the user decided to use this feature. We will also do a vector search
+  // as pinning is a supplemental tool but it should be used with caution since it can easily blow up a context window.
+  await new DocumentManager({
+    workspace,
+    maxTokens: LLMConnector.limits.system,
+  })
+    .pinnedDocs()
+    .then((pinnedDocs) => {
+      pinnedDocs.forEach((doc) => {
+        const { pageContent, ...metadata } = doc;
+        contextTexts.push(doc.pageContent);
+        sources.push({
+          text:
+            pageContent.slice(0, 1_000) +
+            "...continued on in source document...",
+          ...metadata,
+        });
+      });
+    });
+
+  const vectorSearchResults =
+    embeddingsCount !== 0
+      ? await VectorDb.performSimilaritySearch({
+          namespace: workspace.slug,
+          input: message,
+          LLMConnector,
+          similarityThreshold: workspace?.similarityThreshold,
+          topN: workspace?.topN,
+        })
+      : {
+          contextTexts: [],
+          sources: [],
+          message: null,
+        };
 
   // Failed similarity search if it was run at all and failed.
-  if (!!error) {
+  if (!!vectorSearchResults.message) {
     writeResponseChunk(response, {
       id: uuid,
       type: "abort",
       textResponse: null,
       sources: [],
       close: true,
-      error,
+      error: vectorSearchResults.message,
     });
     return;
   }
 
+  contextTexts = [...contextTexts, ...vectorSearchResults.contextTexts];
+  sources = [...sources, ...vectorSearchResults.sources];
+
   // If in query mode and no sources are found, do not
   // let the LLM try to hallucinate a response or use general knowledge and exit early
   if (chatMode === "query" && sources.length === 0) {
diff --git a/server/utils/files/index.js b/server/utils/files/index.js
index dff5bef9c2a0719810bb6c453078111ce055472d..1ba0179652bb67395a26abe13960efbb6e9202c4 100644
--- a/server/utils/files/index.js
+++ b/server/utils/files/index.js
@@ -1,6 +1,7 @@
 const fs = require("fs");
 const path = require("path");
 const { v5: uuidv5 } = require("uuid");
+const { Document } = require("../../models/documents");
 const documentsPath =
   process.env.NODE_ENV === "development"
     ? path.resolve(__dirname, `../../storage/documents`)
@@ -55,6 +56,10 @@ async function viewLocalFiles() {
           type: "file",
           ...metadata,
           cached: await cachedVectorInformation(cachefilename, true),
+          pinnedWorkspaces: await Document.getPins({
+            docpath: cachefilename,
+            pinned: true,
+          }),
         });
       }
       directory.items.push(subdocs);
diff --git a/server/utils/helpers/chat/index.js b/server/utils/helpers/chat/index.js
index 7292c422e5b989ac97467b7162c4500d4b41befe..84afd516cde5819c069722e1aa4380757637d52f 100644
--- a/server/utils/helpers/chat/index.js
+++ b/server/utils/helpers/chat/index.js
@@ -85,11 +85,35 @@ async function messageArrayCompressor(llm, messages = [], rawHistory = []) {
     // Split context from system prompt - cannonball since its over the window.
     // We assume the context + user prompt is enough tokens to fit.
     const [prompt, context = ""] = system.content.split("Context:");
-    system.content = `${cannonball({
-      input: prompt,
-      targetTokenSize: llm.limits.system,
-      tiktokenInstance: tokenManager,
-    })}${context ? `\nContext: ${context}` : ""}`;
+    let compressedPrompt;
+    let compressedContext;
+
+    // If the user system prompt contribution's to the system prompt is more than
+    // 25% of the system limit, we will cannonball it - this favors the context
+    // over the instruction from the user.
+    if (tokenManager.countFromString(prompt) >= llm.limits.system * 0.25) {
+      compressedPrompt = cannonball({
+        input: prompt,
+        targetTokenSize: llm.limits.system * 0.25,
+        tiktokenInstance: tokenManager,
+      });
+    } else {
+      compressedPrompt = prompt;
+    }
+
+    if (tokenManager.countFromString(context) >= llm.limits.system * 0.75) {
+      compressedContext = cannonball({
+        input: context,
+        targetTokenSize: llm.limits.system * 0.75,
+        tiktokenInstance: tokenManager,
+      });
+    } else {
+      compressedContext = context;
+    }
+
+    system.content = `${compressedPrompt}${
+      compressedContext ? `\nContext: ${compressedContext}` : ""
+    }`;
     resolve(system);
   });