reddit bot framework handoff rka1284
AT# Reddit assistant framework handoff Owner: Trevor McFedries Reference account/style source: `rka1284` Purpose: give an employee enough context to build their own Reddit monitoring + drafting + approval system using the old OpenClaw/Hermes Reddit framework as inspiration. This d
- Uploaded
- Uploaded May 15, 2026
- File type
- TXT
- Queried
- 22
Full document
Showing the full document.
# Reddit assistant framework handoff Owner: Trevor McFedries Reference account/style source: `rka1284` Purpose: give an employee enough context to build their own Reddit monitoring + drafting + approval system using the old OpenClaw/Hermes Reddit framework as inspiration. This document is intentionally sanitized. It does not include cookies, passwords, OAuth tokens, private browser profiles, or anything that should be copied between machines. ## What this should be Build a Reddit assistant, not a spam cannon. The useful product is a system that: 1. Finds relevant Reddit threads. 2. Scores whether the thread is worth responding to.
3. Drafts replies in a specific human style. 4. Runs quality and safety checks. 5. Queues drafts for human approval. 6. Posts only after approval, or leaves posting to the human. 7. Logs what happened so the account does not repeat itself. The bad version is fully automated posting, automated voting, fake activity, or anything that looks like manipulation. That will get accounts burned and it is also just a dumb way to build trust. ## Hard rules ### Do not automate these - Upvotes. - Downvotes. - Fake browsing activity. - Ban evasion. - Account farming.
- Posting the same reply template across many threads. - Commenting only to drop links. - Pretending a bot is a person if disclosure is required by policy, client rules, or subreddit norms. ### Require human approval before posting Every outbound comment should pass through an approval queue unless the operator explicitly chooses a different policy for their own account. For Trevor/rka1284-style workflows, approval was mandatory. Keep that default. ### Never store secrets in the repo Use environment variables or a local secrets manager. Required secrets should live outside the project: ```bash REDDIT_CLIENT_ID= REDDIT_CLIENT_SECRET= REDDIT_REFRESH_TOKEN= REDDIT_USER_AGENT= OPENAI_API_KEY= # or whatever model provider you use ```
Do not commit cookies. Do not email refresh tokens. Do not paste auth JSON into Slack. ## System shape A clean implementation has six modules. ```text reddit-assistant/ example config/ yaml yaml yaml yaml src/ py py py py py py py py py data/ jsonl jsonl jsonl jsonl prompts/ md md md tests/ py py ``` ## Recommended operating modes ### Mode 1: monitor only Use this first. - Fetch candidate threads. - Score them. - Save the best ones to a queue. - Do not draft and do not post. Good for validating subreddit selection and search queries.
### Mode 2: draft only - Fetch candidate threads. - Score them. - Generate a draft reply. - Run style and safety checks. - Save drafts to an approval queue. - Human posts manually or approves through the queue. This is the default mode I would ship. ### Mode 3: approved posting - Same as draft only. - Human clicks approve. - System posts via Reddit API. - System logs the permalink, timestamp, subreddit, thread id, and draft version. Do not enable this until monitor-only and draft-only have been stable for at least a week.
## Thread discovery Use two discovery paths. ### Reddit API discovery Pull fresh threads from target subreddits: - `/new` - `/hot` - keyword search within subreddit Useful fields: - subreddit - title - body/selftext - author - score - number of comments - created timestamp - permalink - url - flair Prefer fresh threads with low comment counts when the goal is helpful participation. Default scoring preference: ```yaml freshness: ideal_age_minutes: 15-360 reject_older_than_hours: 72 comments: ideal_max: 20 strong_preference: 0-8 subreddit_fit: required: true already_replied: reject: true locked_or_archived: reject: true ``` ### Google/search discovery The old OpenClaw notes had an important rule: do not only chase new Reddit posts.
Also find Reddit threads that rank on Google for target queries. This matters if the goal is durable search visibility. Example queries: ```text com/r/Soulseek port forwarding soulseek com/r/Soulseek soulseek alternatives com/r/musichoarder flac collection organize com/r/Piracy download music reddit ``` For Google-first discovery: 1. Search target query. 2. Keep Reddit results on page 1 or 2. 3. Check whether the thread is still open. 4. Check whether a reply would be genuinely useful. 5. Do not necro old threads unless the comment adds real value. ## Candidate scoring Score each thread from 0 to 100. Suggested factors:
```yaml relevance_to_topics: 0-30 ability_to_be_helpful: 0-25 low_spam_risk: 0-20 freshness_or_search_value: 0-15 account_voice_fit: 0-10 ``` Reject immediately if: - The thread is hostile to promotion. - The answer would require pretending to have personal experience you do not have. - The only useful reply is a link drop. - The subreddit rules prohibit the intended kind of comment. - The account has already replied to the same thread. - The same point has already been made by someone else. ## Topic map The original rka1284/OpenClaw material focused on music, downloading, collecting, and technical hobbyist communities. ### Strong-fit areas
- Soulseek usage and etiquette. - Music library organization. - FLAC, tagging, metadata, folders. - Music hoarding and storage. - Piracy-adjacent technical questions where a neutral, helpful answer is possible. - Torrents, trackers, usenet, seedboxes. - Self-hosting and homelab if the thread is relevant. - Mac apps and Linux if there is a real technical angle. - DJing, Beatmatch, production workflows. ### Target subreddit examples ```yaml primary: - Soulseek - musichoarder - DataHoarder - Piracy - torrents - trackers - opensignups - seedboxes - usenet music_and_dj: - Beatmatch - DJs - edmproduction - WeAreTheMusicMakers - ableton - FL_Studio technical: - homelab - selfhosted - linux - mac - macapps ```
Do not blindly use this list for a different brand/account. Treat it as a starting point. ## Approval queue Use JSONL. It is boring and reliable. jsonl`: ```json {"id":"2026-05-12T18:22:11Z_r_Soulseek_abc123","status":"pending","subreddit":"Soulseek","thread_id":"abc123","thread_title":"port forwarding ","risks":["mentions product, no link"],"created_at":"2026-05-12T18:22:11Z"} ``` Statuses: ```text pending approved rejected needs_rewrite posted skipped ``` Approval should show: - Thread title. - Thread URL. - Short summary of the thread. - Why this thread was selected. - Draft comment. - Safety/style notes. - Buttons or CLI actions: approve, reject, rewrite, skip. ## Logging Track everything. Repetition is what makes accounts look fake. jsonl`: ```json ","operator":"employee_name"} ```
jsonl`: ```json {"skipped_at":"2026-05-12T19:01:00Z","thread_id":"abc123","reason":"already answered by another commenter"} ``` jsonl`: ```json "} ``` ## Reddit auth Use Reddit OAuth. Prefer PRAW in Python unless there is a strong reason not to. Install: ```bash python -m venv venv/bin/activate pip install praw python-dotenv pydantic pyyaml rich ``` example`: ```bash REDDIT_CLIENT_ID= REDDIT_CLIENT_SECRET= REDDIT_REFRESH_TOKEN= REDDIT_USER_AGENT="reddit-assistant/0.1 by u/YOUR_USERNAME" ``` py`: ```python import os import praw from dotenv import load_dotenv load_dotenv() def get_reddit() -> Reddit: return environ["REDDIT_CLIENT_ID"], environ["REDDIT_CLIENT_SECRET"], environ["REDDIT_REFRESH_TOKEN"], get("REDDIT_USER_AGENT", "reddit-assistant/0.1"),) ``` Verify login without printing secrets: ```python reddit = get_reddit() me()) ``` Do not treat cookies as durable auth. The old imported OpenClaw cookies were not enough to prove login.
The reliable check is: authenticated API call returns the expected username. ## Posting implementation Only post approved items. ```python def post_approved_comment(reddit, item): if = "approved": raise ValueError("refusing to post unapproved item") submission = submission(id=item["thread_id"]) comment = reply(item["draft"]) return {"comment_id": id, "permalink": com" + permalink,} ``` Add guardrails before this function runs: - Check approval status. - Check thread is not locked. - Check account has not already replied. - Check draft hash has not already been posted. - Check minimum spacing since last post. - Check subreddit-specific posting limits. ## Rate limits and spacing Old rka1284 notes used 10-18 minutes between comments.
For a safer employee-built tool, use slower defaults. Suggested defaults: ```yaml posting: require_approval: true min_minutes_between_posts: 30 max_posts_per_day: 5 max_posts_per_subreddit_per_day: 2 no_duplicate_draft_hashes: true no_same_thread_twice: true ``` If a comment is promotional or mentions a product, use even lower volume. ## Drafting prompt Use this as md`. ```markdown You are drafting a Reddit comment for a human operator to review. Goal: - Be useful in the thread. - Sound like a real Reddit user typing quickly. - Do not sound like a brand, marketer, tutor, or AI assistant. - Do not force a product mention. Only mention the product if it is directly useful and natural.
Thread: Subreddit: {{subreddit}} Title: {{title}} Body: {{body}} Top comments: {{top_comments}} Account voice: - Casual lowercase is okay. - Short paragraphs, usually 1-2 sentences. - Specific, opinionated, not balanced for the sake of balance. - Personal experience is okay only if supplied in the context. Do not invent life experience. - No em dashes. - No polished conclusion. - No corporate words. - No "Here's the thing". - No "That said". - No "it's not X, it's Y" construction. - No list of three adjectives. Draft one comment. If the best answer is "do not reply", return only: NO_REPLY: <reason> ```
## Style rules The old rka1284 style was intentionally casual and anti-polished. Keep: - Short paragraphs. - Direct opinion. - Specific advice. - Lowercase casual when natural. - Occasional imperfect phrasing. - Endings that feel like a person trailing off, not a conclusion paragraph. Avoid: - Em dashes. - Corporate/tutorial phrasing. - "Here's the thing". - "It's worth noting". - "That said". - "comprehensive", "robust", "leverage", "utilize". - "exciting", "powerful", "revolutionary", "groundbreaking". - Perfectly structured three-part answers. - Generic positivity. - Link dropping. Good vibe: ```text port forwarding helps alot but you can still download without it, you just cant upload to people who also have closed ports.
so basically half the network becomes unavailable to grab from you if that makes sense? some users get annoyed and ban closed port people because they assume your leeching ``` Bad vibe: ```text Port forwarding helps a lot, but you can still download without it. Here's the thing: users with closed ports may be unable to connect to one another, which can reduce availability and create friction in the community. ``` The bad version is accurate but reads like an assistant. ## Style gate Run a deterministic check before any draft reaches approval. Reject or flag if the draft contains:
```text ā Here's the thing That said It's worth noting In today's world The answer lies in comprehensive robust leverage utilize revolutionary groundbreaking As an AI I hope this helps ``` Also flag if: - More than 180 words. - More than 3 paragraphs. - Contains a link and the thread did not ask for one. - Mentions a product more than once. - Sounds like customer support. - Uses a numbered list without a clear reason. Example Python gate: ```python BANNED = ["ā", "here's the thing", "that said", "it's worth noting", "in today's world", "the answer lies in", "comprehensive", "robust", "leverage", "utilize", "revolutionary", "groundbreaking", "as an ai", "i hope this helps",]
def style_gate(text: str) -> list[str]: issues = [] lower = lower() for phrase in BANNED: if lower() in lower: append(f"banned phrase: {phrase}") words = split() if len(words) > 180: append(f"too long: {len(words)} words") paragraphs = [p for p in split("\n\n") if strip()] if len(paragraphs) > 3: append(f"too many paragraphs: {len(paragraphs)}") if count("http://") + count("https://") > 0: append("contains link, requires extra review") return issues ``` ## Safety gate Run a second gate for behavior risk. Flag if: - The draft asks for upvotes. - The draft implies affiliation that is not true. - The draft hides a commercial relationship where one exists.
- The draft attacks a person. - The draft gives dangerous technical instructions. - The draft is mostly promotion. - The draft repeats a prior comment. - The thread is about legal, medical, financial, or crisis topics. For any flag, keep the item in queue but mark `needs_review`. ## Product mentions If the bot is meant to support a product, use strict rules. Allowed: - Mention the product only when it directly solves the user's problem. - Prefer describing the approach over dropping a link. - Say if you built it or are affiliated, if that is true and relevant.
- Make the comment useful even if the product mention is removed. Not allowed: - "You should check out X" pasted everywhere. - Fake user testimonials. - Pretending to discover your own product as a random user. - Hiding affiliation in subreddits where it matters. A good product-adjacent comment should pass this test: > If I delete the product name, is the comment still useful? If no, rewrite. ## Browser automation notes The old framework found that old Reddit was easier to automate than new Reddit because it uses normal HTML forms. Old Reddit comment form selectors:
```javascript const ta = querySelector('textarea[name="text"]'); value = 'your comment here'; const saveBtn = save'); click(); ``` But for a new implementation, prefer the official API through OAuth/PRAW. Browser automation is brittle and more likely to break. Use browser automation only for: - Human-in-the-loop review UI testing. - Manual session verification. - Edge cases the API does not expose. Do not use browser automation for voting or fake activity. ## CLI flow A minimal CLI is enough. ```bash # fetch and score candidates python -m main discover --limit 50 # generate drafts for good candidates python -m
main draft --min-score 70 # list pending drafts python -m main queue # approve one draft python -m main approve 2026-05-12T18:22:11Z_r_Soulseek_abc123 # post approved drafts python -m main post-approved --max 1 ``` ## Implementation checklist ### Phase 1: local monitor - [] Create repo structure. - [] Add example`. - [] Implement Reddit OAuth login. - [] Fetch new posts from configured subreddits. - [] Save jsonl`. - [] Add basic scoring. - [] Add duplicate detection. Acceptance: - Running `discover` produces a ranked candidate list. - No posting code runs. - No secrets appear in logs.
### Phase 2: draft queue - [] Add LLM provider wrapper. - [] Add drafting prompt. - [] Add style gate. - [] Add safety gate. - [] Save queue items as JSONL. - [] Add `queue`, `approve`, `reject`, and `rewrite` commands. Acceptance: - Drafts are useful and mostly short. - Banned phrases are caught. - Every draft has a source thread URL. - Every draft has a reason it was selected. ### Phase 3: approved posting - [] Implement posting only for `approved` items. - [] Check lock/archive status before posting. - [] Check account has not already replied.
- [] Enforce post spacing. - [] Log permalink after posting. - [] Mark queue item as `posted`. Acceptance: - Cannot post a pending item. - Cannot post the same item twice. - Failed posts stay visible with an error reason. ### Phase 4: search-value discovery - [] Add Google/search-based candidate ingestion. - [] Add target query config. - [] Track search query source for each candidate. - [] Score search-ranking threads differently from fresh threads. Acceptance: - Candidate records include discovery source. - Old threads are not replied to unless still useful and allowed.
## Config examples yaml`: ```yaml subreddits: Soulseek: enabled: true max_posts_per_day: 1 keywords: - port forwarding - shares - banned - download stuck - alternative musichoarder: enabled: true max_posts_per_day: 1 keywords: - flac - tagging - metadata - folder structure DataHoarder: enabled: true max_posts_per_day: 1 keywords: - music collection - backup - storage ``` yaml`: ```yaml voice: lowercase_ok: true max_words: 180 max_paragraphs: 3 no_em_dash: true avoid_polished_conclusion: true banned_phrases: - Here's the thing - That said - It's worth noting - comprehensive - robust - leverage - utilize - revolutionary - groundbreaking ``` yaml`: ```yaml posting: require_approval: true min_minutes_between_posts: 30 max_posts_per_day: 5 max_posts_per_subreddit_per_day: 2 reject_duplicate_drafts: true reject_if_already_replied: true promotion: allow_links: false max_product_mentions: 1 require_affiliation_disclosure_when_relevant: true ```
## Common failure modes ### It sounds like ChatGPT Fix: - Cut length by half. - Remove the intro sentence. - Remove the conclusion. - Replace formal words with normal ones. - Add one concrete detail from the thread. - Do not overdo typos. Forced typos look fake too. ### It keeps recommending the product Fix: - Add a no-product draft path. - Require the draft to be useful without the product name. - Reject if the thread did not ask for a tool/recommendation. ### It replies to stale threads Fix: - Add age filters.
- For search-discovered threads, require a reason to revive the thread. - Prefer unanswered questions or threads where the answer is still useful. ### It repeats itself Fix: - Hash every draft. - Store semantic summaries of previous replies. - Reject drafts that make the same point in the same subreddit too often. ### It gets auth wrong Fix: - Use OAuth refresh tokens. - Verify me()` returns the expected username. - Never rely on old cookies as proof of login. ## Employee deliverables Ask the employee to deliver: 1. Git repo with the structure above.
2. example`, no real secrets. 3. README with setup and commands. 4. Monitor-only mode. 5. Draft queue mode. 6. Style gate and safety gate. 7. Approved posting mode behind a config flag. 8. JSONL logs for seen, queued, skipped, posted. 9. A short Loom/video or terminal recording showing the workflow. 10. A sample run using a test subreddit or dry-run mode. ## Definition of done This project is done when: - A new operator can configure subreddits and topics without editing code. - The system can find candidate threads and explain why they were selected.
- Drafts are queued, not blindly posted. - The style gate catches obvious AI tells. - The safety gate catches promotional or risky drafts. - Posting requires approval. - Every post is logged with a permalink. - No secrets are committed. - The README is good enough that another employee can run it from scratch. ## Short instruction to give the employee Build a Reddit monitoring and drafting assistant inspired by this framework. Start with monitor-only and draft-only modes. Do not automate voting or fake activity. Do not auto-post without explicit approval. Use Reddit OAuth, JSONL logs, a human approval queue, a style gate, and a safety gate.
Optimize for useful comments that sound human and specific, not volume.
Want to learn more?
Ask about this document