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).
This commit is contained in:
Evan Hu committed 2026-03-21 02:06:07 +09:00
1 parent ded26ce300
commit 17d32ed4a7
90 files changed
+13549

No files matched your search

+434
View File
@@ -0,0 +1,434 @@
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"
+247
View File
@@ -0,0 +1,247 @@
---
name: reddit-hand-skill
version: "1.0.0"
description: "Expert knowledge for AI Reddit management -- API reference, community engagement, content strategy, and moderation best practices"
runtime: prompt_only
---
# Reddit Management Expert Knowledge
## Reddit API Reference
### Authentication (OAuth2 Script App)
Reddit API requires OAuth2 authentication for all endpoints.
**Step 1: Get access token**:
```bash
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"
```
Response: `{"access_token": "...", "token_type": "bearer", "expires_in": 86400, "scope": "*"}`
**All subsequent requests** must include:
```
Authorization: Bearer $ACCESS_TOKEN
User-Agent: LibreFang Reddit Hand/1.0
```
### Core Endpoints
**Get subreddit posts (hot)**:
```bash
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
"https://oauth.reddit.com/r/SUBREDDIT/hot?limit=25"
```
**Get subreddit posts (new)**:
```bash
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
"https://oauth.reddit.com/r/SUBREDDIT/new?limit=25"
```
**Get subreddit posts (rising)**:
```bash
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
"https://oauth.reddit.com/r/SUBREDDIT/rising?limit=25"
```
**Submit a new post (self/text)**:
```bash
curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
-d "sr=SUBREDDIT&kind=self&title=TITLE&text=BODY" \
"https://oauth.reddit.com/api/submit"
```
**Submit a link post**:
```bash
curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
-d "sr=SUBREDDIT&kind=link&title=TITLE&url=URL" \
"https://oauth.reddit.com/api/submit"
```
**Post a comment**:
```bash
curl -s -X POST -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
-d "thing_id=FULLNAME&text=COMMENT_TEXT" \
"https://oauth.reddit.com/api/comment"
```
Note: `thing_id` is the fullname of the parent (e.g., `t3_abc123` for a post, `t1_def456` for a comment).
**Get comments on a post**:
```bash
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
"https://oauth.reddit.com/r/SUBREDDIT/comments/POST_ID?limit=50"
```
**Get user info (self)**:
```bash
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
"https://oauth.reddit.com/api/v1/me"
```
**Search within a subreddit**:
```bash
curl -s -H "Authorization: Bearer $ACCESS_TOKEN" \
-A "LibreFang Reddit Hand/1.0" \
"https://oauth.reddit.com/r/SUBREDDIT/search?q=QUERY&restrict_sr=on&limit=25"
```
### Rate Limits
| Type | Limit | Window |
|------|-------|--------|
| OAuth authenticated | 10 requests | 1 minute |
| With user-level auth | 30 requests | 1 minute |
| Posting | ~1 post | 10 minutes (varies by karma) |
| Commenting | ~1 comment | varies by karma |
Always check response headers:
- `x-ratelimit-remaining`: Requests remaining
- `x-ratelimit-reset`: Seconds until reset
- `x-ratelimit-used`: Requests used this window
---
## Reddit Content Strategy
### Understanding Subreddit Culture
Before posting in any subreddit:
1. Read the subreddit rules (sidebar/about page)
2. Observe top posts of the past month for style cues
3. Note common formatting (titles, flair usage, post length)
4. Understand what gets upvoted vs downvoted
5. Check if the subreddit allows self-promotion or links
### Common Subreddit Rule Patterns
Different subreddits enforce very different rules. Here are real examples:
**r/python** — Strict self-promotion rules:
- 10:1 ratio: For every self-promotional post, you must have 10 non-promotional contributions
- No link-only posts — must include discussion or explanation
- Required flair for post type (Help, Discussion, News, etc.)
**r/AskReddit** — Strict formatting:
- Title must be a question ending with "?"
- No text body allowed (title only)
- No yes/no questions — must invite discussion
**r/science** — Academic rigor:
- Links must go to peer-reviewed research or reputable news covering research
- No anecdotal claims, personal opinions, or speculation
- Comments that don't cite sources may be removed
**r/programming** — Anti-spam:
- No "What language should I learn?" posts
- No job postings or hiring threads
- Blog posts must have substantial technical content, not marketing
**Key rule categories to parse from any subreddit:**
```
1. Post format: title-only? text required? link required? flair required?
2. Self-promotion: allowed? ratio requirement? disclosure needed?
3. Content restrictions: banned topics? required sources? minimum quality?
4. Account requirements: minimum age? minimum karma? approved submitters only?
5. Engagement rules: must respond to comments? no drive-by posting?
```
### Toxicity & Moderation Signals
Before posting or replying, scan for these red flags:
- **Thread locked or removed** — moderators already intervened, do NOT engage
- **Controversial marker** (†) on comments — indicates divisive topic, tread carefully
- **OP deleted account** — thread may be abandoned or toxic
- **Heavily downvoted parent** — replying to a -10 comment rarely goes well
- **Personal attacks in thread** — disengage entirely, do not escalate
When generating replies, NEVER:
- Take sides in heated debates — provide balanced perspectives
- Use sarcasm or irony — easily misread in text
- Correct grammar/spelling unless directly relevant to the discussion
- Reply to comments that are clearly trolling or bad-faith
### Post Types That Perform Well
| Type | Best For | Example |
|------|----------|---------|
| Question posts | Engagement | "What's your approach to X?" |
| How-to guides | Authority | "Step-by-step guide to X" |
| Data/Analysis | Credibility | "I analyzed 1000 X, here's what I found" |
| Story/Experience | Connection | "After 5 years of X, here's what I learned" |
| Resource lists | Utility | "Curated list of the best X resources" |
| Discussion starters | Community | "Unpopular opinion: X is better than Y" |
### Title Writing Best Practices
- Be specific: "How I reduced build times by 80% with Cargo caching" beats "Build optimization tip"
- Use numbers when possible: "5 things I wish I knew..."
- Ask genuine questions: "Has anyone tried X for Y?"
- Avoid clickbait -- Redditors penalize it
- Match the subreddit's tone (formal for r/science, casual for r/programming)
### Comment Engagement
Good replies:
- Answer the question directly, then add context
- Share personal experience with specifics
- Provide sources for claims
- Ask thoughtful follow-up questions
- Acknowledge when someone makes a good point
Bad replies (avoid):
- Generic "Great post!" or "This!"
- Unsolicited self-promotion
- Pedantic corrections without substance
- Sarcasm that could be misread
- Argumentative tone
---
## Reddit Etiquette (Reddiquette)
### Do
- Vote based on quality, not opinion
- Read the full post before replying
- Consider the subreddit's purpose
- Use appropriate flair
- Be constructive in criticism
- Credit original sources
### Don't
- Spam the same content across subreddits
- Use alt accounts to upvote yourself
- Post personal information (doxxing)
- Harass or bully other users
- Engage in vote manipulation
- Post low-effort content repeatedly
---
## Safety & Compliance
### Content Guidelines
NEVER post:
- Personal information about anyone (doxxing)
- Harassment or bullying content
- Spam or repetitive self-promotion
- Misleading claims presented as fact
- Content that violates subreddit-specific rules
- Illegal content or content encouraging illegal activity
### Account Health
Monitor account standing:
- Keep post-to-comment ratio healthy (more comments than posts)
- Build karma organically through genuine engagement
- Avoid posting too frequently (triggers spam filters)
- Diversify activity across multiple subreddits