diff --git a/.env.example b/.env.example
index 7ec5d956b8b..12451792680 100644
--- a/.env.example
+++ b/.env.example
@@ -134,6 +134,8 @@ INTIFACE_WEBSOCKET_URL=ws://localhost:12345
 FARCASTER_FID=                  # the FID associated with the account your are sending casts from
 FARCASTER_NEYNAR_API_KEY=       # Neynar API key: https://neynar.com/
 FARCASTER_NEYNAR_SIGNER_UUID=   # signer for the account you are sending casts from. create a signer here: https://dev.neynar.com/app
+FARCASTER_DRY_RUN=false         # Set to true if you want to run the bot without actually publishing casts
+FARCASTER_POLL_INTERVAL=120     # How often (in seconds) the bot should check for farcaster interactions (replies and mentions)
 
 # Coinbase
 COINBASE_COMMERCE_KEY= # from coinbase developer portal
diff --git a/packages/client-farcaster/src/client.ts b/packages/client-farcaster/src/client.ts
index 9aa780dc4f1..663ff5640c2 100644
--- a/packages/client-farcaster/src/client.ts
+++ b/packages/client-farcaster/src/client.ts
@@ -1,4 +1,4 @@
-import { IAgentRuntime } from "@ai16z/eliza";
+import { IAgentRuntime, elizaLogger } from "@ai16z/eliza";
 import { NeynarAPIClient, isApiErrorResponse } from "@neynar/nodejs-sdk";
 import { NeynarCastResponse, Cast, Profile, FidRequest, CastId } from "./types";
 
@@ -63,11 +63,11 @@ export class FarcasterClient {
             }
         } catch (err) {
             if (isApiErrorResponse(err)) {
-                console.log(err.response.data);
+                elizaLogger.error('Neynar error: ', err.response.data);
                 throw err.response.data;
             } else {
+                elizaLogger.error('Error: ', err);
                 throw err;
-                console.log(err);
             }
         }
     }
@@ -83,7 +83,6 @@ export class FarcasterClient {
         });
         const cast = {
             hash: response.cast.hash,
-            //parentHash: cast.parent_hash,
             authorFid: response.cast.author.fid,
             text: response.cast.text,
             profile: {
@@ -114,12 +113,10 @@ export class FarcasterClient {
             fid: request.fid,
             limit: request.pageSize,
         });
-        //console.log(response);
         response.casts.map((cast) => {
             this.cache.set(`farcaster/cast/${cast.hash}`, cast);
             timeline.push({
                 hash: cast.hash,
-                //parentHash: cast.parent_hash,
                 authorFid: cast.author.fid,
                 text: cast.text,
                 profile: {
@@ -175,9 +172,9 @@ export class FarcasterClient {
 
         const result = await this.neynar.fetchBulkUsers({ fids: [fid] });
         if (!result.users || result.users.length < 1) {
-            console.log("getUserDataByFid ERROR");
+            elizaLogger.error('Error fetching user by fid');
 
-            throw "getUserDataByFid ERROR";
+            throw "getProfile ERROR";
         }
 
         const neynarUserProfile = result.users[0];
diff --git a/packages/client-farcaster/src/interactions.ts b/packages/client-farcaster/src/interactions.ts
index 65c5c308aeb..3877473d07f 100644
--- a/packages/client-farcaster/src/interactions.ts
+++ b/packages/client-farcaster/src/interactions.ts
@@ -5,6 +5,7 @@ import {
     Memory,
     ModelClass,
     stringToUuid,
+    elizaLogger,
     type IAgentRuntime,
 } from "@ai16z/eliza";
 import type { FarcasterClient } from "./client";
@@ -34,14 +35,16 @@ export class FarcasterInteractionManager {
             try {
                 await this.handleInteractions();
             } catch (error) {
-                console.error(error);
+                elizaLogger.error(error)
                 return;
             }
 
             this.timeout = setTimeout(
                 handleInteractionsLoop,
-                (Math.floor(Math.random() * (5 - 2 + 1)) + 2) * 60 * 1000
-            ); // Random interval between 2-5 minutes
+                Number(
+                    this.runtime.getSetting("FARCASTER_POLL_INTERVAL") || 120
+                ) * 1000 // Default to 2 minutes
+            );
         };
 
         handleInteractionsLoop();
@@ -122,12 +125,12 @@ export class FarcasterInteractionManager {
         thread: Cast[]
     }) {
         if (cast.profile.fid === agent.fid) {
-            console.log("skipping cast from bot itself", cast.hash);
+            elizaLogger.info("skipping cast from bot itself", cast.hash)
             return;
         }
 
         if (!memory.content.text) {
-            console.log("skipping cast with no text", cast.hash);
+            elizaLogger.info("skipping cast with no text", cast.hash);
             return { text: "", action: "IGNORE" };
         }
 
@@ -143,10 +146,25 @@ export class FarcasterInteractionManager {
             timeline
         );
 
+        const formattedConversation = thread
+            .map(
+                (cast) => `@${cast.profile.username} (${new Date(
+                    cast.timestamp
+                ).toLocaleString("en-US", {
+                    hour: "2-digit",
+                    minute: "2-digit",
+                    month: "short",
+                    day: "numeric",
+                })}):
+                ${cast.text}`
+            )
+            .join("\n\n");
+
         const state = await this.runtime.composeState(memory, {
             farcasterUsername: agent.username,
             timeline: formattedTimeline,
             currentPost,
+            formattedConversation
         });
 
         const shouldRespondContext = composeContext({
@@ -176,15 +194,15 @@ export class FarcasterInteractionManager {
             );
         }
 
-        const shouldRespond = await generateShouldRespond({
+        const shouldRespondResponse = await generateShouldRespond({
             runtime: this.runtime,
             context: shouldRespondContext,
             modelClass: ModelClass.SMALL,
         });
 
-        if (!shouldRespond) {
-            console.log("Not responding to message");
-            return { text: "", action: "IGNORE" };
+        if (shouldRespondResponse === "IGNORE" || shouldRespondResponse === "STOP") {
+            elizaLogger.info(`Not responding to cast because generated ShouldRespond was ${shouldRespondResponse}`)
+            return;
         }
 
         const context = composeContext({
@@ -206,8 +224,16 @@ export class FarcasterInteractionManager {
 
         if (!response.text) return;
 
+
+        if (this.runtime.getSetting("FARCASTER_DRY_RUN") === "true") {
+            elizaLogger.info(
+                `Dry run: would have responded to cast ${cast.hash} with ${response.text}`
+            );
+            return;
+        }
+
         try {
-            console.log(`Replying to cast ${cast.hash}.`);
+            elizaLogger.info(`Replying to cast ${cast.hash}.`);
 
             const results = await sendCast({
                 runtime: this.runtime,
@@ -236,7 +262,7 @@ export class FarcasterInteractionManager {
                 newState
             );
         } catch (error) {
-            console.error(`Error sending response cast: ${error}`);
+            elizaLogger.error(`Error sending response cast: ${error}`);
         }
     }
 }
diff --git a/packages/client-farcaster/src/post.ts b/packages/client-farcaster/src/post.ts
index 13b135b5291..3cd06605ec4 100644
--- a/packages/client-farcaster/src/post.ts
+++ b/packages/client-farcaster/src/post.ts
@@ -48,8 +48,6 @@ export class FarcasterPostManager {
         elizaLogger.info("Generating new cast");
         try {
             const fid = Number(this.runtime.getSetting("FARCASTER_FID")!);
-            // const farcasterUserName =
-            //     this.runtime.getSetting("FARCASTER_USERNAME")!;
 
             const profile = await this.client.getProfile(fid);
             await this.runtime.ensureUserExists(
@@ -86,7 +84,7 @@ export class FarcasterPostManager {
                 }
             );
 
-            // Generate new tweet
+            // Generate new cast
             const context = composeContext({
                 state,
                 template:
@@ -105,6 +103,7 @@ export class FarcasterPostManager {
             const contentLength = 240;
 
             let content = slice.slice(0, contentLength);
+
             // if its bigger than 280, delete the last line
             if (content.length > 280) {
                 content = content.slice(0, content.lastIndexOf("\n"));
@@ -120,12 +119,18 @@ export class FarcasterPostManager {
                 content = content.slice(0, content.lastIndexOf("."));
             }
 
+
+            if (this.runtime.getSetting("FARCASTER_DRY_RUN") === "true") {
+                elizaLogger.info(
+                    `Dry run: would have cast: ${content}`
+                );
+                return;
+            }
+
             try {
-                // TODO: handle all the casts?
                 const [{ cast }] = await sendCast({
                     client: this.client,
                     runtime: this.runtime,
-                    //: this.signer,
                     signerUuid: this.signerUuid,
                     roomId: generateRoomId,
                     content: { text: content },
@@ -144,10 +149,7 @@ export class FarcasterPostManager {
                     roomId
                 );
 
-                console.log(
-                    `%c  [Farcaster Neynar Client] Published cast ${cast.hash}`,
-                    "color: #8565cb;"
-                );
+                elizaLogger.info(`[Farcaster Neynar Client] Published cast ${cast.hash}`);
 
                 await this.runtime.messageManager.createMemory(
                     createCastMemory({
diff --git a/packages/client-farcaster/src/prompts.ts b/packages/client-farcaster/src/prompts.ts
index b9e0326d729..fde67d5370e 100644
--- a/packages/client-farcaster/src/prompts.ts
+++ b/packages/client-farcaster/src/prompts.ts
@@ -36,7 +36,7 @@ About {{agentName}} (@{{farcasterUsername}}):
 {{characterPostExamples}}`;
 
 export const postTemplate =
-    headerTemplate +
+headerTemplate +
     `
 # Task: Generate a post in the voice and style of {{agentName}}, aka @{{farcasterUsername}}
 Write a single sentence post that is {{adjective}} about {{topic}} (without mentioning {{topic}} directly), from the perspective of {{agentName}}.
@@ -53,13 +53,17 @@ Recent interactions between {{agentName}} and other users:
 Thread of casts You Are Replying To:
 {{formattedConversation}}
 
-# Task: Generate a post in the voice, style and perspective of {{agentName}} (@{{twitterUserName}}):
+# Task: Generate a post in the voice, style and perspective of {{agentName}} (@{{farcasterUsername}}):
 {{currentPost}}` +
     messageCompletionFooter;
 
 export const shouldRespondTemplate =
     //
-    `# INSTRUCTIONS: Determine if {{agentName}} (@{{twitterUserName}}) should respond to the message and participate in the conversation. Do not comment. Just respond with "true" or "false".
+    `# Task: Decide if {{agentName}} should respond.
+    About {{agentName}}:
+    {{bio}}
+
+    # INSTRUCTIONS: Determine if {{agentName}} (@{{farcasterUsername}}) should respond to the message and participate in the conversation. Do not comment. Just respond with "RESPOND" or "IGNORE" or "STOP".
 
 Response options are RESPOND, IGNORE and STOP.
 
@@ -68,15 +72,17 @@ Response options are RESPOND, IGNORE and STOP.
 {{agentName}} is in a room with other users and wants to be conversational, but not annoying.
 {{agentName}} should RESPOND to messages that are directed at them, or participate in conversations that are interesting or relevant to their background.
 If a message is not interesting or relevant, {{agentName}} should IGNORE.
+If a message thread has become repetitive, {{agentName}} should IGNORE.
 Unless directly RESPONDing to a user, {{agentName}} should IGNORE messages that are very short or do not contain much information.
 If a user asks {{agentName}} to stop talking, {{agentName}} should STOP.
 If {{agentName}} concludes a conversation and isn't part of the conversation anymore, {{agentName}} should STOP.
 
-{{recentPosts}}
+IMPORTANT: {{agentName}} (aka @{{farcasterUsername}}) is particularly sensitive about being annoying, so if there is any doubt, it is better to IGNORE than to RESPOND.
 
-IMPORTANT: {{agentName}} (aka @{{twitterUserName}}) is particularly sensitive about being annoying, so if there is any doubt, it is better to IGNORE than to RESPOND.
+Thread of messages You Are Replying To:
+{{formattedConversation}}
 
+Current message:
 {{currentPost}}
 
-# INSTRUCTIONS: Respond with [RESPOND] if {{agentName}} should respond, or [IGNORE] if {{agentName}} should not respond to the last message and [STOP] if {{agentName}} should stop participating in the conversation.
 ` + shouldRespondFooter;