Files
miku-discord/AUTONOMOUS_V2_SPAM_FIX.md

8.0 KiB

Critical Fixes for Autonomous V2 - Spam Prevention

Date: November 23, 2025
Issue: Miku sending multiple rapid-fire messages on startup and reacting to messages in wrong channels


🐛 Issues Identified

Issue #1: No Channel Filtering

Problem: on_message_event() was processing ALL messages from ALL channels in the server.

Impact:

  • Miku reacted to messages in channels she shouldn't monitor
  • Wasted processing on irrelevant messages
  • Privacy concern: tracking messages from non-autonomous channels

Logs showed:

bot-1 | 🎯 [V2] Real-time reaction triggered for message from aryan slavic eren yigger
bot-1 | ❌ [j's reviews patreon server (real)] Missing permissions to add reactions

This means she tried to react to a message in a channel where she doesn't have permissions (not the autonomous channel).


Issue #2: No Startup Cooldown

Problem: On bot startup, the autonomous system immediately started making decisions, causing 3 messages to be sent back-to-back.

Impact:

  • Spam: 3 general messages in ~6 seconds
  • Bad user experience
  • Looks like a bug, not natural conversation

Logs showed:

bot-1 | 🎯 [V2] Message triggered autonomous action: general
bot-1 | 🤖 [V2] Autonomous engine decided to: general for server 1140377616667377725
bot-1 | 💬 Miku said something general in #general
bot-1 | 🎯 [V2] Message triggered autonomous action: general
bot-1 | 🤖 [V2] Autonomous engine decided to: general for server 1140377616667377725
bot-1 | 💬 Miku said something general in #general
bot-1 | 🎯 [V2] Message triggered autonomous action: general
bot-1 | 🤖 [V2] Autonomous engine decided to: general for server 1140377616667377725
bot-1 | 💬 Miku said something general in #general

Issue #3: No Rate Limiting

Problem: Even with the decision engine, multiple messages could trigger actions in quick succession if conditions were met.

Impact:

  • Potential for spam if multiple users send messages simultaneously
  • No protection against edge cases

Fixes Applied

Fix #1: Channel Filtering 🔒

File: bot/utils/autonomous.py

Added: Server config check to only process messages from the autonomous channel

def on_message_event(message):
    """
    ONLY processes messages from the configured autonomous channel.
    """
    if not message.guild:
        return  # DMs don't use this system
    
    guild_id = message.guild.id
    
    # Get server config to check if this is the autonomous channel
    server_config = server_manager.get_server_config(guild_id)
    if not server_config:
        return  # No config for this server
    
    # CRITICAL: Only process messages from the autonomous channel
    if message.channel.id != server_config.autonomous_channel_id:
        return  # Ignore messages from other channels

Impact:

  • Only tracks messages from the configured autonomous channel
  • Won't react to messages in other channels
  • Privacy: doesn't process messages from non-autonomous channels
  • Performance: less unnecessary processing

Fix #2: Startup Cooldown

File: bot/utils/autonomous_engine.py

Added: 2-minute cooldown after bot startup

class AutonomousEngine:
    def __init__(self):
        # ... existing code ...
        self.bot_startup_time: float = time.time()  # Track when bot started
def should_take_action(self, guild_id: int, debug: bool = False) -> Optional[str]:
    # STARTUP COOLDOWN: Don't act for first 2 minutes after bot startup
    # This prevents rapid-fire messages when bot restarts
    time_since_startup = time.time() - self.bot_startup_time
    if time_since_startup < 120:  # 2 minutes
        if debug:
            print(f"⏳ [V2 Debug] Startup cooldown active ({time_since_startup:.0f}s / 120s)")
        return None

Impact:

  • Bot waits 2 minutes after startup before taking any autonomous actions
  • Gives time for context to build naturally
  • Prevents immediate spam on restart
  • Users won't see weird behavior when bot comes online

Fix #3: Rate Limiting 🛡️

File: bot/utils/autonomous.py

Added: Minimum 30-second interval between autonomous actions

# Rate limiting: Track last action time per server to prevent rapid-fire
_last_action_execution = {}  # guild_id -> timestamp
_MIN_ACTION_INTERVAL = 30  # Minimum 30 seconds between autonomous actions

async def autonomous_tick_v2(guild_id: int):
    # Rate limiting check
    now = time.time()
    if guild_id in _last_action_execution:
        time_since_last = now - _last_action_execution[guild_id]
        if time_since_last < _MIN_ACTION_INTERVAL:
            print(f"⏱️ [V2] Rate limit: Only {time_since_last:.0f}s since last action")
            return
    
    # ... execute action ...
    
    # Update rate limiter
    _last_action_execution[guild_id] = time.time()

Impact:

  • Even if multiple messages trigger decisions, only 1 action per 30 seconds
  • Extra safety net beyond the engine's cooldowns
  • Prevents edge cases where rapid messages could cause spam

🔄 Multi-Layer Protection

The system now has 3 layers of spam prevention:

  1. Engine Cooldowns (in autonomous_engine.py)

    • Each decision type has its own cooldown (5 min, 15 min, 30 min, etc.)
    • Mood-based thresholds
  2. Startup Cooldown (NEW)

    • 2-minute grace period after bot restart
    • Prevents immediate actions on startup
  3. Rate Limiter (NEW)

    • Hard limit: 30 seconds minimum between ANY autonomous actions
    • Final safety net
Message arrives → Channel check → Startup check → Engine decision → Rate limiter → Action
     ↓                 ↓                ↓              ↓                ↓           ↓
   All msgs      Autonomous only   <2min? Skip   Apply logic    <30s? Skip    Execute

🧪 Testing Checklist

After deploying these fixes:

  • Restart bot - Should see no autonomous actions for 2 minutes
  • Send messages in autonomous channel - Should be tracked and eventually trigger actions
  • Send messages in other channels - Should be ignored completely
  • Rapid messages - Should trigger at most 1 action per 30 seconds
  • Debug mode - Should show "Startup cooldown active" for first 2 minutes

📊 Expected Behavior

On Bot Startup

[Bot starts]
User: "hello"
[V2 tracks message but doesn't act - startup cooldown]
User: "how are you?"
[V2 tracks message but doesn't act - startup cooldown]
... 2 minutes pass ...
User: "anyone here?"
[V2 can now act if conditions are met]
Miku: "Hi everyone! ✨"

Message in Wrong Channel

[User sends message in #random-chat]
[V2 ignores - not the autonomous channel]

[User sends message in #general (autonomous channel)]
[V2 tracks and may act]

Rate Limiting

18:00:00 - User message → Miku acts
18:00:15 - User message → V2 rate limited (only 15s)
18:00:25 - User message → V2 rate limited (only 25s)
18:00:35 - User message → V2 can act (30s+ passed)

🔧 Configuration

Adjust Startup Cooldown

In bot/utils/autonomous_engine.py, line ~238:

if time_since_startup < 120:  # Change 120 to desired seconds

Recommended: 120 seconds (2 minutes)

Adjust Rate Limit

In bot/utils/autonomous.py, line ~15:

_MIN_ACTION_INTERVAL = 30  # Change to desired seconds

Recommended: 30 seconds minimum


Validation

All syntax checks passed:

  • autonomous.py - Syntax OK
  • autonomous_engine.py - Syntax OK

🎯 Summary

Before:

  • Processed all messages from all channels
  • Immediately acted on bot startup (3 messages in seconds)
  • No rate limiting

After:

  • Only processes messages from configured autonomous channel
  • 2-minute startup cooldown prevents immediate spam
  • 30-second rate limit prevents rapid-fire actions
  • Multi-layer protection ensures natural behavior

The bot will now behave naturally and won't spam on startup! 🎉