Crafted RC | Maker Gear & Tools Curated by Code
CraftedRC - Maker Tools & Hobby Gear
← Back

How I Built an Engagement Bot That Comments Like a Human

By Joe Stasio on May 21, 2025

The Vision: Local LLM + Automated Engagement

I've built plenty of bots before, but this one was different. I didn’t just want a vote-bot. I wanted a bot that would comment. One that reads articles, forms opinions, and throws out spicy takes like a half-baked Redditor on too much coffee. And I wanted it to run locally — no OpenAI keys, no cloud calls.

Tools I Used

  • Raspberry Pi 5 with NVMe
  • FastAPI for the local LLM server
  • My own LLM backend: a trimmed-down Mistral-style model
  • BeautifulSoup + requests + Tor for scraping and anonymity
  • My existing CoreAPI (posts, comments, voting)

How It Works (In English)

Every 15 seconds, this thing wakes up. It:

  1. Pulls the top 100 posts from my site
  2. Prioritizes new content 65% of the time
  3. Filters out anything already at 10k+ score
  4. Pulls the article URL and scrapes the content
  5. Votes on it (random mix of up/super/boost/down/burn)
  6. Sends the article + title to the LLM
  7. Posts 1–3 top-level comments
  8. Reads comments already there and maybe replies or boosts them
  9. Waits, rotates IPs using Tor, and repeats

What Broke (Often)

  • LLM timeout hell — long inputs + low-end GPU = dead API
  • Scraping fails — site format changed or Tor timed out
  • LLM comments too nice — it sounded like a damn guidance counselor
  • Infinite loops — without score caps it just hounded top posts forever

Fixes That Helped

1. Score Cap:

if score >= TARGET_SCORE:
    print(f"⏭️ Skipping post {pid} (score={score} >= target)")
    continue

2. Tor Refresh:

if now - _last_tor_refresh > TOR_REFRESH_INTERVAL:
    renew_tor_ip()

3. LLM Prompt That Doesn’t Suck:

"React to this post. Be opinionated. Swear if needed. Sound human."

4. Logging Everything:

print(f"💬 Commenting on post {post_id} with: {content[:60]}")

The Comment System Itself

The magic is in get_llm_comment():

def get_llm_comment(post_title, article_content):
    tone = random.choice(TONES)
    perspective = random.choice(PERSPECTIVES)
    payload = {
        "content": article_content,
        "tone": tone,
        "perspective": perspective,
        "max_length": 120,
        "context": f"Context: {post_title}"
    }
    res = requests.post(LLM_COMMENT_API, json=payload)
    return res.json().get("generated_text", "").strip()

Sample Output

"Of course the government wants to regulate AI. They can't even regulate trains."
"Oh cool, another billionaire launches a rocket while we can't afford eggs."

What’s Next?

  • Add memory so it doesn’t comment on the same post twice
  • Auto-feature hot comments
  • Detect controversial posts and swarm them

Final Thoughts

This bot doesn’t just upvote. It engages. It replies. It shitposts. It learns. And best of all, it runs from my own gear. No subscriptions. No limits. No guardrails. Just raw, programmable influence.

Built with sweat, swear words, and caffeine.