diff --git a/server/endpoints/workspaces.js b/server/endpoints/workspaces.js
index 6a6df19347be50ff53ee8d85fa96900b9a42ed47..95fe61b49a889de1287f73852946238c70d2572c 100644
--- a/server/endpoints/workspaces.js
+++ b/server/endpoints/workspaces.js
@@ -825,7 +825,6 @@ function workspaceEndpoints(app) {
             : "Forked Thread",
         });
 
-        await Telemetry.sendTelemetry("thread_forked");
         await EventLogs.logEvent(
           "thread_forked",
           {
diff --git a/server/models/telemetry.js b/server/models/telemetry.js
index 011da05e97f444229d926a14d5a675aabc5c1a41..101fb58e0f026234fdf1117232ab70a27be90a7c 100644
--- a/server/models/telemetry.js
+++ b/server/models/telemetry.js
@@ -1,11 +1,28 @@
 const { v4 } = require("uuid");
 const { SystemSettings } = require("./systemSettings");
 
+// Map of events and last sent time to check if the event is on cooldown
+// This will be cleared on server restart - but that is fine since it is mostly to just
+// prevent spamming the logs.
+const TelemetryCooldown = new Map();
+
 const Telemetry = {
   // Write-only key. It can't read events or any of your other data, so it's safe to use in public apps.
   pubkey: "phc_9qu7QLpV8L84P3vFmEiZxL020t2EqIubP7HHHxrSsqS",
   stubDevelopmentEvents: true, // [DO NOT TOUCH] Core team only.
   label: "telemetry_id",
+  /* 
+  Key value pairs of events that should be debounced to prevent spamming the logs.
+  This should be used for events that could be triggered in rapid succession that are not useful to atomically log.
+  The value is the number of seconds to debounce the event
+  */
+  debounced: {
+    agent_chat_started: 1800,
+    sent_chat: 1800,
+    agent_chat_sent: 1800,
+    agent_chat_started: 1800,
+    agent_tool_call: 1800,
+  },
 
   id: async function () {
     const result = await SystemSettings.get({ label: this.label });
@@ -34,6 +51,34 @@ const Telemetry = {
     return "other";
   },
 
+  /**
+   * Checks if the event is on cooldown
+   * @param {string} event - The event to check
+   * @returns {boolean} - True if the event is on cooldown, false otherwise
+   */
+  isOnCooldown: function (event) {
+    // If the event is not debounced, return false
+    if (!this.debounced[event]) return false;
+
+    // If the event is not in the cooldown map, return false
+    const lastSent = TelemetryCooldown.get(event);
+    if (!lastSent) return false;
+
+    // If the event is in the cooldown map, check if it has expired
+    const now = Date.now();
+    const cooldown = this.debounced[event] * 1000;
+    return now - lastSent < cooldown;
+  },
+
+  /**
+   * Marks the event as on cooldown - will check if the event is debounced first
+   * @param {string} event - The event to mark
+   */
+  markOnCooldown: function (event) {
+    if (!this.debounced[event]) return;
+    TelemetryCooldown.set(event, Date.now());
+  },
+
   sendTelemetry: async function (
     event,
     eventProperties = {},
@@ -46,6 +91,9 @@ const Telemetry = {
       const distinctId = !!subUserId ? `${systemId}::${subUserId}` : systemId;
       const properties = { ...eventProperties, runtime: this.runtime() };
 
+      // If the event is on cooldown, return
+      if (this.isOnCooldown(event)) return;
+
       // Silence some events to keep logs from being too messy in production
       // eg: Tool calls from agents spamming the logs.
       if (!silent) {
@@ -63,6 +111,9 @@ const Telemetry = {
       });
     } catch {
       return;
+    } finally {
+      // Mark the event as on cooldown if needed
+      this.markOnCooldown(event);
     }
   },