Skip to content

Repository files navigation

Reddit Agent

An async Python agent that finds relevant Reddit posts, scores them for relevance, analyses subreddit tone, generates playbook-compliant comments and original posts, and exports everything to Google Sheets.

Table of Contents


Features

  • Intelligent search — natural language prompts mapped to relevant subreddits via LLM
  • Relevance scoring — every post scored 0–1 with reasoning, boosted for organic engagement opportunities
  • Competitor tracking — finds posts and comments mentioning Synthesia, Camtasia, Guidde, etc.
  • Subreddit tone analysis — fetches hot posts/comments, extracts vocabulary and style, caches for 7 days
  • Playbook-compliant comments — stage-gated product mentions, randomised structure, subreddit-matched tone
  • Original post generation — question / insight / story formats, tone-aware, per-account assignment
  • Profile analysis — audit any public Reddit account against the playbook
  • Google Sheets export — deduplicated append with competitor flags, source prompt, and suggested comments
  • Multi-account support — named accounts in accounts.json with per-account karma stage
  • Rate limit handling — exponential backoff, automatic retries

Installation

Prerequisites

  • Python 3.9+
  • Reddit API credentials (client ID + secret)
  • OpenAI API key
  • Google service account JSON (for Sheets export)

Setup

# 1. Navigate to project directory
cd reddit-agent

# 2. Create and activate virtual environment
python3 -m venv .venv
source .venv/bin/activate

# 3. Install dependencies
pip install -r requirements.txt

# 4. Configure environment
cp .env.example .env   # or create .env manually — see Configuration

Configuration

.env File

# ── Reddit API ────────────────────────────────────────────────
REDDIT_CLIENT_ID=your_client_id
REDDIT_CLIENT_SECRET=your_client_secret
REDDIT_USERNAME=your_username          # required for posting
REDDIT_PASSWORD=your_password          # required for posting
REDDIT_USER_AGENT=reddit-agent/0.1 by your_username

# ── OpenAI ────────────────────────────────────────────────────
OPENAI_API_KEY=your_openai_api_key
OPENAI_MODEL=gpt-4o-mini               # or gpt-4o

# ── Subreddits ────────────────────────────────────────────────
DEFAULT_SUBREDDITS=r/ProductMarketing,r/elearning,r/instructionaldesign,r/Training,r/prodmgmt,r/SaaS

# ── Search limits ─────────────────────────────────────────────
MAX_POSTS=100
MAX_SUBREDDIT_MATCHES=5
CONCURRENCY_LIMIT=8

# ── Relevance ─────────────────────────────────────────────────
RELEVANCE_THRESHOLD=0.5

# ── Competitor tracking ───────────────────────────────────────
ENABLE_COMPETITOR_SEARCH=true
COMPETITORS=Synthesia,Camtasia,Guidde
CHECK_COMMENTS_FOR_COMPETITORS=true

# ── Smart subreddit matching ──────────────────────────────────
ENABLE_SMART_SUBREDDIT_MATCHING=true

# ── Engagement playbook ───────────────────────────────────────
KARMA_STAGE=1          # 1 = never mention product, 2 = build authority, 3 = light mention OK

# ── Google Sheets export ──────────────────────────────────────
GOOGLE_SHEET_ID=your_sheet_id
GOOGLE_SHEETS_CREDENTIALS_FILE=/path/to/service_account.json

# ── Multi-account ─────────────────────────────────────────────
ACCOUNTS_FILE=accounts.json            # optional, see Multi-Account section

# ── Misc ──────────────────────────────────────────────────────
ENABLE_POSTING=false
LOG_LEVEL=INFO

Getting Reddit API Credentials

  1. Go to reddit.com/prefs/apps
  2. Create app → type: script
  3. Copy the client ID (below app name) and secret

Getting Google Sheets Credentials

  1. Google Cloud Console → create/select a project
  2. Enable the Google Sheets API
  3. IAM & Admin → Service Accounts → Create → download JSON key
  4. Share your spreadsheet with the service account email (…@….iam.gserviceaccount.com) as Editor

Usage

Find relevant posts and generate comments

# Single prompt
.venv/bin/python -m src.agent.main --prompt "reduce time to create training content"

# Multiple prompts from file, export to Google Sheets
.venv/bin/python -m src.agent.main --prompt-file prompt.txt --export

# With custom subreddits and post limit
.venv/bin/python -m src.agent.main \
  --prompt "training video creation" \
  --subreddits r/elearning r/instructionaldesign \
  --limit 50 --top 10 --export

Generate original posts for subreddits

.venv/bin/python -m src.agent.main \
  --prompt "reduce time to create training content" \
  --subreddits r/elearning r/instructionaldesign \
  --generate-posts

Analyse a Reddit profile

.venv/bin/python -m src.agent.main --analyze-profile example_username

Use a specific account from accounts.json

.venv/bin/python -m src.agent.main \
  --prompt-file prompt.txt \
  --account account_1 \
  --generate-posts --export

Force-refresh subreddit tone cache

.venv/bin/python -m src.agent.main \
  --prompt-file prompt.txt \
  --refresh-tone

Command-Line Reference

Modes (mutually exclusive)

Flag Description
--prompt TEXT Single search prompt
--prompt-file PATH File with multiple prompts (see Prompt File Format)
--analyze-profile USERNAME Audit a Reddit profile against the playbook

Search & filtering

Flag Default Description
--subreddits from config Override subreddits for this run
--keywords Extra keywords appended to the search query
--limit N 100 Max posts fetched per prompt
--top N 10 Top N posts to generate comments for
--max-age-weeks N 12 Filter posts older than N weeks
--relevance-threshold F 0.5 Min relevance score to include a post

Output & export

Flag Default Description
--export false Export all above-threshold posts to Google Sheets
--format json|md md Terminal output format

Post & comment generation

Flag Default Description
--generate-posts false Generate original posts (title + body) per subreddit
--refresh-tone false Force-refresh subreddit tone profiles (ignores 7-day cache)
--post false Actually post generated comments to Reddit (requires ENABLE_POSTING=true)

Account management

Flag Default Description
--account NAME Use named account from accounts.json
--accounts-file PATH accounts.json Path to accounts config file

Prompt File Format

# Simple prompt — uses DEFAULT_SUBREDDITS or smart matching
reduce time to create training content

# Prompt with explicit subreddits (highest priority)
training video creation ||| r/instructionaldesign, r/elearning, r/Training

# Multiple prompts separated by blank lines
SOPs ||| r/instructionaldesign, r/elearning

product tour ||| r/ProductMarketing, r/productmanagement
  • ||| syntax pins specific subreddits for that prompt
  • Blank lines separate prompts
  • Subreddit names accept or omit the r/ prefix

Multi-Account Support

Copy accounts.example.json to accounts.json and fill in your credentials:

{
  "accounts": [
    {
      "name": "account_1",
      "username": "your_reddit_username",
      "password": "your_password",
      "karma_stage": 1,
      "preferred_subreddits": ["r/elearning", "r/instructionaldesign", "r/Training"]
    },
    {
      "name": "new_account_1",
      "username": "new_reddit_username",
      "password": "your_password",
      "karma_stage": 1,
      "preferred_subreddits": ["r/ProductMarketing", "r/SaaS"]
    }
  ]
}
  • accounts.json is gitignored — never commit it
  • --account NAME switches credentials and karma stage for that run
  • preferred_subreddits routes generated post suggestions to the right account
  • If no accounts.json exists, falls back to .env credentials

Karma Stage Playbook

Set KARMA_STAGE in .env (or per-account in accounts.json):

Stage Karma Behaviour
1 < 100 Pure value — no product, tool, or company names ever
2 100–299 Build authority — share experience, still no product mention
3 300+ Light [your product] mention allowed when it genuinely fits the thread

Stage 3 comments include a transparency framing: "frame it as a personal recommendation from someone who works on or uses the product" — so if someone asks about affiliation, the reply is honest.


Subreddit Tone Analysis

Before generating comments or posts, the agent fetches the top 20 hot posts and their top comments from each target subreddit and runs an LLM analysis to extract:

  • Tone — e.g. "casual, practitioner-focused, sceptical of vendors"
  • Vocabulary — insider jargon, acronyms, phrases that signal belonging
  • Upvoted formats — what kinds of posts/comments get positive engagement
  • Downvoted formats — what gets ignored or flagged
  • Comment length — short / medium / long
  • Self-promotion stance — how the community views promotional content

Tone profiles are cached in .tone_cache.json for 7 days. Force a refresh with --refresh-tone.


Profile Analysis

.venv/bin/python -m src.agent.main --analyze-profile example_username

Outputs:

  1. Stats panel — comment karma, post karma, account age, karma stage
  2. Compliance flags — promotional language hits, copy-paste pattern detection
  3. Top subreddits — where the last 100 comments landed
  4. Playbook analysis — LLM assessment of tone variety, value quality, promotional risk, top 3 improvements

Works on any public Reddit account — no password required.


Google Sheets Export

.venv/bin/python -m src.agent.main --prompt-file prompt.txt --export

The sheet receives one row per unique post (deduplicated by Post ID across runs):

Column Description
Title Post title
Subreddit e.g. r/elearning
Link Full Reddit URL
Relevance Score 0–1
Reasoning LLM explanation of score
Suggested Comment Generated comment text
Post ID Reddit post ID (dedup key)
Source Prompt Which prompt found this post
Mentions Competitor Yes / No
Competitor Names Comma-separated
Competitors in Comments Yes / No
Competitor Names in Comments Comma-separated

Re-running with --export appends only new posts — duplicates are skipped automatically.


Architecture

Modules

src/agent/
├── main.py                # CLI orchestrator
├── config.py              # Pydantic settings (loads .env)
├── types.py               # Post, AnalyzedPost dataclasses
├── reddit_client.py       # asyncpraw search, comments, posting
├── content_analyzer.py    # Relevance scoring via OpenAI
├── comment_generator.py   # Playbook-compliant comment generation
├── post_generator.py      # Original post generation (title + body)
├── subreddit_tone.py      # Tone profile fetching and caching
├── subreddit_matcher.py   # LLM-based prompt→subreddit matching
├── profile_analyzer.py    # Reddit profile audit
├── sheets_exporter.py     # Google Sheets append with dedup
└── logging_utils.py       # Structured logging

Pipeline (per prompt)

Prompt(s)
   │
   ▼
Subreddit selection
   Explicit (|||) → Smart LLM match → CLI --subreddits → DEFAULT_SUBREDDITS
   │
   ▼
Tone profile fetch (cached 7 days per subreddit)
   │
   ▼
Post search  ─────────────────────────────────────────────┐
   Main query (all subreddits)                             │
   + Competitor queries (if enabled)                       │
   → Date filter → Deduplicate                             │
   │                                                       │
   ▼                                                       ▼
Relevance scoring (OpenAI, concurrent)         Comment checking (comments for competitors)
   │
   ▼
Threshold filter → Sort → Top N
   │
   ▼
Comment generation (tone-aware, stage-gated)
   │
   ├─ Post generation (if --generate-posts)
   ├─ Google Sheets export (if --export)
   ├─ Terminal display
   └─ Reddit posting (if --post and ENABLE_POSTING=true)

OpenAI calls per run

Operation Calls
Smart subreddit matching 1 per prompt (if no explicit subreddits)
Tone profile fetch 1 per subreddit (cached 7 days)
Relevance scoring 1 per fetched post
Comment generation 1 per shortlisted post
Post generation 1 per subreddit (if --generate-posts)
Profile analysis 1 per --analyze-profile call

Troubleshooting

"No subreddits specified, skipping search"

Set DEFAULT_SUBREDDITS in .env, use --subreddits, or add ||| to your prompt file.

"Rate limit exceeded"

Wait a few minutes. The agent retries with exponential backoff (5s → 60s, up to 5 attempts). Reduce the number of subreddits if it persists.

"No posts found for this prompt"

Try a broader/more natural phrasing — Reddit search is literal. Check the prompt file examples for what works.

Google Sheets PermissionError

Share the spreadsheet with your service account email (…@….iam.gserviceaccount.com) as Editor.

Google Sheets credentials file not found

Set GOOGLE_SHEETS_CREDENTIALS_FILE in .env to the absolute path of your service account JSON.

ValidationError: Field required

REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, and OPENAI_API_KEY are required. Check your .env file.

Debug mode

LOG_LEVEL=DEBUG  # in .env

Version: 0.2
Last updated: April 2026

About

Async Python agent: finds relevant Reddit posts, scores with OpenAI, generates tone-aware playbook-compliant comments, exports to Google Sheets

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages