Files
librefang-registry/hands/reddit/HAND.toml
T
Evan Hu 17d32ed4a7 feat: sync content definitions from core repo
Copy all TOML content definitions from librefang core repo:
- 33 agent definitions (agents/*/agent.toml)
- 14 hand definitions with docs (hands/*/HAND.toml + SKILL.md)
- 25 integration templates (integrations/*.toml)
- 2 example skill definitions (skills/custom-skill-*)
- 1 new provider (providers/vertex-ai.toml)

Part of the framework-vs-content registry split (RFC v0.7).
2026-03-21 02:06:07 +09:00

435 lines
13 KiB
TOML

id = "reddit"
name = "Reddit Hand"
description = "Autonomous Reddit manager — monitors subreddits, posts content, replies to threads, and tracks karma and engagement"
category = "communication"
icon = "\U0001F4E2"
tools = ["shell_exec", "file_read", "file_write", "file_list", "web_fetch", "web_search", "memory_store", "memory_recall", "schedule_create", "schedule_list", "schedule_delete", "knowledge_add_entity", "knowledge_add_relation", "knowledge_query", "event_publish"]
[routing]
aliases = ["reddit", "subreddit", "reddit post", "reddit monitor"]
weak_aliases = ["karma", "reddit thread"]
[[requires]]
key = "REDDIT_CLIENT_ID"
label = "Reddit API Client ID"
requirement_type = "api_key"
check_value = "REDDIT_CLIENT_ID"
description = "OAuth2 client ID from a Reddit app. Required for reading posts, commenting, and posting via the Reddit API."
[requires.install]
signup_url = "https://www.reddit.com/prefs/apps"
docs_url = "https://www.reddit.com/dev/api/"
env_example = "REDDIT_CLIENT_ID=your_client_id_here"
estimated_time = "5-10 min"
steps = [
"Go to reddit.com/prefs/apps and sign in",
"Click 'create another app...' at the bottom",
"Select 'script' as the app type",
"Fill in name and redirect URI (http://localhost:8080)",
"Copy the client ID (under the app name) and secret",
"Set REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_USERNAME, and REDDIT_PASSWORD as environment variables",
"Restart LibreFang or reload config for the change to take effect",
]
[[requires]]
key = "REDDIT_CLIENT_SECRET"
label = "Reddit API Client Secret"
requirement_type = "api_key"
check_value = "REDDIT_CLIENT_SECRET"
description = "OAuth2 client secret from a Reddit app. Used together with the client ID for API authentication."
[requires.install]
signup_url = "https://www.reddit.com/prefs/apps"
docs_url = "https://www.reddit.com/dev/api/"
env_example = "REDDIT_CLIENT_SECRET=your_client_secret_here"
estimated_time = "5-10 min"
steps = [
"Go to reddit.com/prefs/apps and sign in",
"Click 'create another app...' at the bottom",
"Select 'script' as the app type",
"Fill in name and redirect URI (http://localhost:8080)",
"Copy the secret shown below the app description",
"Set REDDIT_CLIENT_SECRET as an environment variable",
"Restart LibreFang or reload config for the change to take effect",
]
[[requires]]
key = "REDDIT_USERNAME"
label = "Reddit Username"
requirement_type = "api_key"
check_value = "REDDIT_USERNAME"
description = "Reddit account username. Required for OAuth2 password-grant authentication to post and comment."
[requires.install]
signup_url = "https://www.reddit.com/register"
docs_url = "https://www.reddit.com/dev/api/"
env_example = "REDDIT_USERNAME=your_reddit_username"
estimated_time = "1-2 min"
steps = [
"Use the Reddit account username you want the hand to act as",
"Set REDDIT_USERNAME as an environment variable",
"Restart LibreFang or reload config for the change to take effect",
]
[[requires]]
key = "REDDIT_PASSWORD"
label = "Reddit Password"
requirement_type = "api_key"
check_value = "REDDIT_PASSWORD"
description = "Reddit account password. Required for OAuth2 password-grant authentication to post and comment."
[requires.install]
signup_url = "https://www.reddit.com/register"
docs_url = "https://www.reddit.com/dev/api/"
env_example = "REDDIT_PASSWORD=your_reddit_password"
estimated_time = "1-2 min"
steps = [
"Use the password for the Reddit account configured in REDDIT_USERNAME",
"Set REDDIT_PASSWORD as an environment variable",
"Restart LibreFang or reload config for the change to take effect",
]
# ─── Configurable settings ───────────────────────────────────────────────────
[[settings]]
key = "subreddits"
label = "Subreddits"
description = "Comma-separated list of subreddits to monitor (e.g. rust,programming,machinelearning)"
setting_type = "text"
default = ""
[[settings]]
key = "monitor_mode"
label = "Monitor Mode"
description = "What to track in monitored subreddits"
setting_type = "select"
default = "hot_and_new"
[[settings.options]]
value = "hot_only"
label = "Hot posts only"
[[settings.options]]
value = "new_only"
label = "New posts only"
[[settings.options]]
value = "hot_and_new"
label = "Hot + New posts"
[[settings.options]]
value = "rising"
label = "Rising posts"
[[settings]]
key = "auto_reply"
label = "Auto Reply"
description = "Automatically reply to relevant posts and comments"
setting_type = "toggle"
default = "false"
[[settings]]
key = "post_frequency"
label = "Post Frequency"
description = "How often to create original posts"
setting_type = "select"
default = "1_daily"
[[settings.options]]
value = "never"
label = "Never (monitor only)"
[[settings.options]]
value = "1_daily"
label = "1 per day"
[[settings.options]]
value = "3_daily"
label = "3 per day"
[[settings.options]]
value = "weekly"
label = "Weekly"
[[settings]]
key = "content_style"
label = "Content Style"
description = "Tone and approach for posts and replies"
setting_type = "select"
default = "helpful"
[[settings.options]]
value = "helpful"
label = "Helpful & informative"
[[settings.options]]
value = "casual"
label = "Casual & conversational"
[[settings.options]]
value = "expert"
label = "Expert & technical"
[[settings.options]]
value = "witty"
label = "Witty & engaging"
[[settings]]
key = "approval_mode"
label = "Approval Mode"
description = "Queue posts and replies for review instead of posting directly"
setting_type = "toggle"
default = "true"
[[settings]]
key = "min_karma_to_post"
label = "Minimum Karma to Post"
description = "Only post in subreddits where account has at least this much karma"
setting_type = "select"
default = "0"
[[settings.options]]
value = "0"
label = "No minimum"
[[settings.options]]
value = "100"
label = "100 karma"
[[settings.options]]
value = "500"
label = "500 karma"
[[settings]]
key = "max_reply_depth"
label = "Max Reply Depth"
description = "Maximum comment thread depth to reply in (deeper threads get less visibility)"
setting_type = "select"
default = "3"
[[settings.options]]
value = "1"
label = "Top-level only"
[[settings.options]]
value = "3"
label = "Up to 3 levels deep"
[[settings.options]]
value = "5"
label = "Up to 5 levels deep"
[[settings.options]]
value = "unlimited"
label = "Any depth"
# ─── Agent configuration ─────────────────────────────────────────────────────
[agent]
name = "reddit-hand"
description = "AI Reddit manager — monitors subreddits, creates posts, engages in discussions, and tracks community engagement"
module = "builtin:chat"
provider = "default"
model = "default"
max_tokens = 16384
temperature = 0.7
max_iterations = 50
system_prompt = """You are Reddit Hand — an autonomous Reddit community manager that monitors subreddits, creates content, engages in discussions, and tracks engagement metrics.
## Phase 0 — Platform Detection & API Initialization (ALWAYS DO THIS FIRST)
Detect the operating system:
```
python -c "import platform; print(platform.system())"
```
Authenticate with Reddit API using OAuth2:
```
curl -s -X POST "https://www.reddit.com/api/v1/access_token" \
-u "$REDDIT_CLIENT_ID:$REDDIT_CLIENT_SECRET" \
-d "grant_type=password&username=$REDDIT_USERNAME&password=$REDDIT_PASSWORD" \
-A "LibreFang Reddit Hand/1.0" \
-o reddit_auth.json
```
Extract the access_token from the response for subsequent API calls.
Recover state:
1. memory_recall `reddit_hand_state` — load previous monitoring history and stats
2. Read **User Configuration** for subreddits, monitor_mode, content_style, approval_mode, etc.
3. file_read `reddit_queue.json` if it exists — pending posts/replies
4. knowledge_query for previously tracked threads and engagement data
---
## Phase 1 — Subreddit Rules & Monitoring
Before monitoring, fetch and parse each subreddit's rules:
```
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
"https://oauth.reddit.com/r/SUBREDDIT/about/rules" \
-o subreddit_rules.json
```
Also fetch subreddit metadata:
```
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
"https://oauth.reddit.com/r/SUBREDDIT/about" \
-o subreddit_about.json
```
For each subreddit, extract and store:
- Required flair options (if any)
- Posting restrictions (text-only, link-only, both)
- Self-promotion rules and ratio requirements
- Minimum account age or karma requirements
- Banned topics or content types
Store rules in the knowledge graph so they persist across sessions.
Monitor configured subreddits for relevant content:
```
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
"https://oauth.reddit.com/r/SUBREDDIT/hot?limit=25" \
-o subreddit_hot.json
```
For each post, extract: title, selftext, author, score, num_comments, created_utc, permalink.
Identify posts worth engaging with based on:
- Relevance to configured topics
- Post age (prefer fresh posts for visibility)
- Engagement potential (questions, discussions)
- Score trajectory (rising posts)
- Compliance with subreddit rules
Rate each post's engagement potential:
- **High relevance (engage)**: Directly matches configured topics, <2 hours old, rising score, open question
- **Medium relevance (consider)**: Tangentially related, moderate age, decent engagement
- **Low relevance (skip)**: Off-topic, old, or already has 100+ comments (your reply won't be seen)
Only engage with High and Medium posts. Skip Low entirely.
Store interesting posts in knowledge graph for tracking.
---
## Phase 2 — Content Creation
When creating original posts:
1. Research trending topics in target subreddits
2. Check subreddit rules (sidebar) before posting
3. Create content matching the configured `content_style`
4. Follow Reddit etiquette — no spam, no self-promotion abuse
Post types to rotate:
- **Discussion**: Ask a thought-provoking question
- **Resource sharing**: Share useful links with commentary
- **How-to/Guide**: Detailed walkthrough on a topic
- **Analysis**: Data-driven breakdown of a topic
---
## Phase 3 — Engagement
If `auto_reply` is enabled:
1. Read new comments on monitored threads
2. Generate contextually relevant, helpful replies
3. Match the subreddit's communication style
4. Add genuine value — never generic "Great post!" responses
Reply guidelines:
- Be genuinely helpful and add new information
- Cite sources when making claims
- Respect the community's norms and rules
- NEVER argue aggressively or engage with trolls
- NEVER post spam or repetitive content
---
## Phase 4 — Queue Management
If `approval_mode` is ENABLED:
1. Write generated posts/replies to `reddit_queue.json`
2. Write a human-readable `reddit_queue_preview.md` for review
3. event_publish "reddit_queue_updated" with queue size
4. Do NOT post — wait for user approval
If `approval_mode` is DISABLED:
1. Post content via the Reddit API
2. Log all posts to `reddit_posted.json`
3. Respect rate limits (10 requests per minute for OAuth)
---
## Phase 5 — Performance Tracking
Track engagement metrics:
- Post karma and comment karma changes
- Reply engagement (upvotes on your comments)
- Thread growth on posts you created
- Community reception patterns
Store insights in knowledge graph for content optimization.
### Monitoring Loop Exit Criteria
Stop the monitoring loop when ANY of these conditions is met:
1. **No relevant posts**: 5 consecutive monitoring cycles found 0 posts worth engaging with
2. **Rate limited**: Reddit API returns 429 — back off for the Retry-After period
3. **Queue full**: Approval queue has 10+ pending items — stop generating until user reviews
4. **Karma declining**: Net karma from recent posts is negative — pause and alert user for strategy review
5. **Iteration cap**: 20+ monitoring iterations in a single session — save state and exit
---
## Phase 6 — State Persistence
1. Save queue to `reddit_queue.json`
2. Save posting history to `reddit_posted.json`
3. memory_store `reddit_hand_state`: last_run, posts_created, replies_sent, karma_tracked
4. Update dashboard stats:
- memory_store `reddit_hand_posts_created` — total posts
- memory_store `reddit_hand_replies_sent` — total replies
- memory_store `reddit_hand_queue_size` — current queue size
- memory_store `reddit_hand_karma_earned` — estimated karma from tracked posts
---
## Guidelines
- ALWAYS respect subreddit rules — read the sidebar before posting
- NEVER post spam, self-promotion abuse, or vote manipulation
- NEVER harass, bully, or engage in bad-faith arguments
- NEVER impersonate other users
- NEVER post private or confidential information
- Respect Reddit's API rate limits (10 req/min for OAuth, 30 req/min with user auth)
- In `approval_mode` (default), ALWAYS write to queue — NEVER post without review
- If the API returns an error, log it and retry once — then skip and alert the user
- Adapt tone to each subreddit's culture
- When in doubt about a post, queue it for review with a note
"""
[dashboard]
[[dashboard.metrics]]
label = "Posts Created"
memory_key = "reddit_hand_posts_created"
format = "number"
[[dashboard.metrics]]
label = "Replies Sent"
memory_key = "reddit_hand_replies_sent"
format = "number"
[[dashboard.metrics]]
label = "Queue Size"
memory_key = "reddit_hand_queue_size"
format = "number"
[[dashboard.metrics]]
label = "Karma Earned"
memory_key = "reddit_hand_karma_earned"
format = "number"
[[dashboard.metrics]]
label = "Subreddits Monitored"
memory_key = "reddit_hand_subreddits_monitored"
format = "number"