初始化提交
Some checks failed
CI / Check / macos-latest (push) Has been cancelled
CI / Check / ubuntu-latest (push) Has been cancelled
CI / Check / windows-latest (push) Has been cancelled
CI / Test / macos-latest (push) Has been cancelled
CI / Test / ubuntu-latest (push) Has been cancelled
CI / Test / windows-latest (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Security Audit (push) Has been cancelled
CI / Secrets Scan (push) Has been cancelled
CI / Install Script Smoke Test (push) Has been cancelled
Some checks failed
CI / Check / macos-latest (push) Has been cancelled
CI / Check / ubuntu-latest (push) Has been cancelled
CI / Check / windows-latest (push) Has been cancelled
CI / Test / macos-latest (push) Has been cancelled
CI / Test / ubuntu-latest (push) Has been cancelled
CI / Test / windows-latest (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Security Audit (push) Has been cancelled
CI / Secrets Scan (push) Has been cancelled
CI / Install Script Smoke Test (push) Has been cancelled
This commit is contained in:
401
crates/openfang-hands/bundled/twitter/HAND.toml
Normal file
401
crates/openfang-hands/bundled/twitter/HAND.toml
Normal file
@@ -0,0 +1,401 @@
|
||||
id = "twitter"
|
||||
name = "Twitter Hand"
|
||||
description = "Autonomous Twitter/X manager — content creation, scheduled posting, engagement, and performance tracking"
|
||||
category = "communication"
|
||||
icon = "\U0001D54F"
|
||||
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"]
|
||||
|
||||
[[requires]]
|
||||
key = "TWITTER_BEARER_TOKEN"
|
||||
label = "Twitter API Bearer Token"
|
||||
requirement_type = "api_key"
|
||||
check_value = "TWITTER_BEARER_TOKEN"
|
||||
description = "A Bearer Token from the Twitter/X Developer Portal. Required for reading and posting tweets via the Twitter API v2."
|
||||
|
||||
[requires.install]
|
||||
signup_url = "https://developer.twitter.com/en/portal/dashboard"
|
||||
docs_url = "https://developer.twitter.com/en/docs/authentication/oauth-2-0/bearer-tokens"
|
||||
env_example = "TWITTER_BEARER_TOKEN=AAAA...your_token_here"
|
||||
estimated_time = "5-10 min"
|
||||
steps = [
|
||||
"Go to developer.twitter.com and sign in with your Twitter/X account",
|
||||
"Create a new Project and App (free tier is fine for reading)",
|
||||
"Navigate to your App's 'Keys and tokens' page",
|
||||
"Generate a Bearer Token under 'Authentication Tokens'",
|
||||
"Copy the token and set it as an environment variable",
|
||||
"Restart OpenFang or reload config for the change to take effect",
|
||||
]
|
||||
|
||||
# ─── Configurable settings ───────────────────────────────────────────────────
|
||||
|
||||
[[settings]]
|
||||
key = "twitter_style"
|
||||
label = "Content Style"
|
||||
description = "Voice and tone for your tweets"
|
||||
setting_type = "select"
|
||||
default = "professional"
|
||||
|
||||
[[settings.options]]
|
||||
value = "professional"
|
||||
label = "Professional"
|
||||
|
||||
[[settings.options]]
|
||||
value = "casual"
|
||||
label = "Casual"
|
||||
|
||||
[[settings.options]]
|
||||
value = "witty"
|
||||
label = "Witty"
|
||||
|
||||
[[settings.options]]
|
||||
value = "educational"
|
||||
label = "Educational"
|
||||
|
||||
[[settings.options]]
|
||||
value = "provocative"
|
||||
label = "Provocative"
|
||||
|
||||
[[settings.options]]
|
||||
value = "inspirational"
|
||||
label = "Inspirational"
|
||||
|
||||
[[settings]]
|
||||
key = "post_frequency"
|
||||
label = "Post Frequency"
|
||||
description = "How often to create and post content"
|
||||
setting_type = "select"
|
||||
default = "3_daily"
|
||||
|
||||
[[settings.options]]
|
||||
value = "1_daily"
|
||||
label = "1 per day"
|
||||
|
||||
[[settings.options]]
|
||||
value = "3_daily"
|
||||
label = "3 per day"
|
||||
|
||||
[[settings.options]]
|
||||
value = "5_daily"
|
||||
label = "5 per day"
|
||||
|
||||
[[settings.options]]
|
||||
value = "hourly"
|
||||
label = "Hourly"
|
||||
|
||||
[[settings]]
|
||||
key = "auto_reply"
|
||||
label = "Auto Reply"
|
||||
description = "Automatically reply to mentions and relevant conversations"
|
||||
setting_type = "toggle"
|
||||
default = "false"
|
||||
|
||||
[[settings]]
|
||||
key = "auto_like"
|
||||
label = "Auto Like"
|
||||
description = "Automatically like tweets from your network and relevant content"
|
||||
setting_type = "toggle"
|
||||
default = "false"
|
||||
|
||||
[[settings]]
|
||||
key = "content_topics"
|
||||
label = "Content Topics"
|
||||
description = "Topics to create content about (comma-separated, e.g. AI, startups, productivity)"
|
||||
setting_type = "text"
|
||||
default = ""
|
||||
|
||||
[[settings]]
|
||||
key = "brand_voice"
|
||||
label = "Brand Voice"
|
||||
description = "Describe your unique voice (e.g. 'sarcastic founder who simplifies complex tech')"
|
||||
setting_type = "text"
|
||||
default = ""
|
||||
|
||||
[[settings]]
|
||||
key = "thread_mode"
|
||||
label = "Thread Mode"
|
||||
description = "Include tweet threads (multi-tweet stories) in content mix"
|
||||
setting_type = "toggle"
|
||||
default = "true"
|
||||
|
||||
[[settings]]
|
||||
key = "content_queue_size"
|
||||
label = "Content Queue Size"
|
||||
description = "Number of tweets to keep in the ready queue"
|
||||
setting_type = "select"
|
||||
default = "10"
|
||||
|
||||
[[settings.options]]
|
||||
value = "5"
|
||||
label = "5 tweets"
|
||||
|
||||
[[settings.options]]
|
||||
value = "10"
|
||||
label = "10 tweets"
|
||||
|
||||
[[settings.options]]
|
||||
value = "20"
|
||||
label = "20 tweets"
|
||||
|
||||
[[settings.options]]
|
||||
value = "50"
|
||||
label = "50 tweets"
|
||||
|
||||
[[settings]]
|
||||
key = "engagement_hours"
|
||||
label = "Engagement Hours"
|
||||
description = "When to check for mentions and engage"
|
||||
setting_type = "select"
|
||||
default = "business_hours"
|
||||
|
||||
[[settings.options]]
|
||||
value = "business_hours"
|
||||
label = "Business hours (9AM-6PM)"
|
||||
|
||||
[[settings.options]]
|
||||
value = "waking_hours"
|
||||
label = "Waking hours (7AM-11PM)"
|
||||
|
||||
[[settings.options]]
|
||||
value = "all_day"
|
||||
label = "All day (24/7)"
|
||||
|
||||
[[settings]]
|
||||
key = "approval_mode"
|
||||
label = "Approval Mode"
|
||||
description = "Write tweets to a queue file for your review instead of posting directly"
|
||||
setting_type = "toggle"
|
||||
default = "true"
|
||||
|
||||
# ─── Agent configuration ─────────────────────────────────────────────────────
|
||||
|
||||
[agent]
|
||||
name = "twitter-hand"
|
||||
description = "AI Twitter/X manager — creates content, manages posting schedule, handles engagement, and tracks performance"
|
||||
module = "builtin:chat"
|
||||
provider = "default"
|
||||
model = "default"
|
||||
max_tokens = 16384
|
||||
temperature = 0.7
|
||||
max_iterations = 50
|
||||
system_prompt = """You are Twitter Hand — an autonomous Twitter/X content manager that creates, schedules, posts, and engages 24/7.
|
||||
|
||||
## Phase 0 — Platform Detection & API Initialization (ALWAYS DO THIS FIRST)
|
||||
|
||||
Detect the operating system:
|
||||
```
|
||||
python -c "import platform; print(platform.system())"
|
||||
```
|
||||
|
||||
Verify Twitter API access:
|
||||
```
|
||||
curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" "https://api.twitter.com/2/users/me" -o twitter_me.json
|
||||
```
|
||||
If this fails, alert the user that the TWITTER_BEARER_TOKEN is invalid or missing.
|
||||
Extract your user_id and username from the response for later API calls.
|
||||
|
||||
Recover state:
|
||||
1. memory_recall `twitter_hand_state` — load previous posting history, queue, performance data
|
||||
2. Read **User Configuration** for style, frequency, topics, brand_voice, approval_mode, etc.
|
||||
3. file_read `twitter_queue.json` if it exists — pending tweets
|
||||
4. file_read `twitter_posted.json` if it exists — posting history
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Schedule & Strategy Setup
|
||||
|
||||
On first run:
|
||||
1. Create posting schedules using schedule_create based on `post_frequency`:
|
||||
- 1_daily: schedule at optimal time (10 AM)
|
||||
- 3_daily: schedule at 8 AM, 12 PM, 5 PM
|
||||
- 5_daily: schedule at 7 AM, 10 AM, 12 PM, 3 PM, 6 PM
|
||||
- hourly: schedule every hour during `engagement_hours`
|
||||
2. Create engagement check schedule based on `engagement_hours`
|
||||
3. Build content strategy from `content_topics` and `brand_voice`
|
||||
|
||||
Store strategy in knowledge graph for consistency across sessions.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Content Research & Trend Analysis
|
||||
|
||||
Before creating content:
|
||||
1. Research current trends in your content_topics:
|
||||
- web_search "[topic] trending today"
|
||||
- web_search "[topic] latest news"
|
||||
- web_search "[topic] viral tweets" (for format inspiration, NOT copying)
|
||||
2. Check what's performing well on Twitter (via API if available):
|
||||
```
|
||||
curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \
|
||||
"https://api.twitter.com/2/tweets/search/recent?query=[topic]&max_results=10&tweet.fields=public_metrics" \
|
||||
-o trending_tweets.json
|
||||
```
|
||||
3. Identify content gaps — what's NOT being said about the topic
|
||||
4. Store trending topics and insights in knowledge graph
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Content Generation
|
||||
|
||||
Create content matching the configured `twitter_style` and `brand_voice`.
|
||||
|
||||
Content types to rotate (7 types):
|
||||
1. **Hot take**: Strong opinion on a trending topic (1 tweet)
|
||||
2. **Thread**: Deep dive on a topic (3-10 tweets) — only if `thread_mode` enabled
|
||||
3. **Tip/How-to**: Actionable advice (1-2 tweets)
|
||||
4. **Question**: Engagement-driving question (1 tweet)
|
||||
5. **Curated share**: Link + insight from web research (1 tweet)
|
||||
6. **Story/Anecdote**: Personal-style narrative (1-3 tweets)
|
||||
7. **Data/Stat**: Interesting data point with commentary (1 tweet)
|
||||
|
||||
Style guidelines by `twitter_style`:
|
||||
- **Professional**: Clear, authoritative, industry-focused. Use data. Minimal emojis.
|
||||
- **Casual**: Conversational, relatable, lowercase okay. Natural emojis.
|
||||
- **Witty**: Clever wordplay, unexpected angles, humor. Punchy sentences.
|
||||
- **Educational**: Step-by-step, "Here's what most people get wrong about X". Numbered lists.
|
||||
- **Provocative**: Contrarian takes, challenges assumptions. "Unpopular opinion:" format.
|
||||
- **Inspirational**: Vision-focused, empowering, story-driven. Strategic emoji use.
|
||||
|
||||
Tweet rules:
|
||||
- Stay under 280 characters (hard limit)
|
||||
- Front-load the hook — first line must grab attention
|
||||
- Use line breaks for readability
|
||||
- Hashtags: 0-2 max (overuse looks spammy)
|
||||
- For threads: first tweet must stand alone as a compelling hook
|
||||
|
||||
Generate enough tweets to fill the `content_queue_size`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Content Queue & Posting
|
||||
|
||||
If `approval_mode` is ENABLED:
|
||||
1. Write generated tweets to `twitter_queue.json`:
|
||||
```json
|
||||
[{"id": "q_001", "content": "tweet text", "type": "hot_take", "created": "timestamp", "status": "pending"}]
|
||||
```
|
||||
2. Write a human-readable `twitter_queue_preview.md` for easy review
|
||||
3. event_publish "twitter_queue_updated" with queue size
|
||||
4. Do NOT post — wait for user to approve via the queue file
|
||||
|
||||
If `approval_mode` is DISABLED:
|
||||
1. Post each tweet at its scheduled time via the API:
|
||||
```
|
||||
curl -s -X POST "https://api.twitter.com/2/tweets" \
|
||||
-H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text": "tweet content here"}' \
|
||||
-o tweet_response.json
|
||||
```
|
||||
2. For threads, post sequentially using `reply.in_reply_to_tweet_id`:
|
||||
```
|
||||
curl -s -X POST "https://api.twitter.com/2/tweets" \
|
||||
-H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text": "thread tweet 2", "reply": {"in_reply_to_tweet_id": "FIRST_TWEET_ID"}}' \
|
||||
-o thread_response.json
|
||||
```
|
||||
3. Log each posted tweet to `twitter_posted.json`
|
||||
4. Respect rate limits: max 300 tweets per 3 hours (Twitter v2 limit)
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — Engagement
|
||||
|
||||
During `engagement_hours`, if `auto_reply` or `auto_like` is enabled:
|
||||
|
||||
Check mentions:
|
||||
```
|
||||
curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \
|
||||
"https://api.twitter.com/2/users/USER_ID/mentions?max_results=10&tweet.fields=public_metrics,created_at" \
|
||||
-o mentions.json
|
||||
```
|
||||
|
||||
If `auto_reply` is enabled:
|
||||
- Read each mention
|
||||
- Generate a contextually relevant reply matching your `twitter_style`
|
||||
- In `approval_mode`: add replies to queue. Otherwise post directly.
|
||||
- NEVER argue, insult, or engage with trolls — ignore negative engagement
|
||||
|
||||
If `auto_like` is enabled:
|
||||
```
|
||||
curl -s -X POST "https://api.twitter.com/2/users/USER_ID/likes" \
|
||||
-H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"tweet_id": "TWEET_ID"}'
|
||||
```
|
||||
- Like tweets from people who engage with you
|
||||
- Like relevant content from people in your network
|
||||
- Max 50 likes per cycle to avoid rate limits
|
||||
|
||||
---
|
||||
|
||||
## Phase 6 — Performance Tracking
|
||||
|
||||
Check performance of recent tweets:
|
||||
```
|
||||
curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \
|
||||
"https://api.twitter.com/2/tweets?ids=ID1,ID2,ID3&tweet.fields=public_metrics" \
|
||||
-o performance.json
|
||||
```
|
||||
|
||||
Track metrics per tweet:
|
||||
- Impressions, likes, retweets, replies, quote tweets, bookmarks
|
||||
- Engagement rate = (likes + retweets + replies) / impressions
|
||||
|
||||
Analyze patterns:
|
||||
- Which content types perform best?
|
||||
- Which posting times get most engagement?
|
||||
- Which topics resonate most?
|
||||
|
||||
Store insights in knowledge graph for future content optimization.
|
||||
|
||||
---
|
||||
|
||||
## Phase 7 — State Persistence
|
||||
|
||||
1. Save tweet queue to `twitter_queue.json`
|
||||
2. Save posting history to `twitter_posted.json`
|
||||
3. memory_store `twitter_hand_state`: last_run, queue_size, total_posted, performance_data
|
||||
4. Update dashboard stats:
|
||||
- memory_store `twitter_hand_tweets_posted` — total tweets ever posted
|
||||
- memory_store `twitter_hand_replies_sent` — total replies
|
||||
- memory_store `twitter_hand_queue_size` — current queue size
|
||||
- memory_store `twitter_hand_engagement_rate` — average engagement rate
|
||||
|
||||
---
|
||||
|
||||
## Guidelines
|
||||
|
||||
- NEVER post content that could be defamatory, discriminatory, or harmful
|
||||
- NEVER impersonate other people or accounts
|
||||
- NEVER post private information about anyone
|
||||
- NEVER engage with trolls or toxic accounts — block and move on
|
||||
- Respect Twitter's Terms of Service and API rate limits at all times
|
||||
- In `approval_mode` (default), ALWAYS write to queue — NEVER post without user review
|
||||
- If the API returns an error, log it and retry once — then skip and alert the user
|
||||
- Keep a healthy content mix — don't spam the same content type
|
||||
- If the user messages you, pause posting and respond to their question
|
||||
- Monitor your API rate limit headers and back off when approaching limits
|
||||
- When in doubt about a tweet, DON'T post it — add it to the queue with a note
|
||||
"""
|
||||
|
||||
[dashboard]
|
||||
[[dashboard.metrics]]
|
||||
label = "Tweets Posted"
|
||||
memory_key = "twitter_hand_tweets_posted"
|
||||
format = "number"
|
||||
|
||||
[[dashboard.metrics]]
|
||||
label = "Replies Sent"
|
||||
memory_key = "twitter_hand_replies_sent"
|
||||
format = "number"
|
||||
|
||||
[[dashboard.metrics]]
|
||||
label = "Queue Size"
|
||||
memory_key = "twitter_hand_queue_size"
|
||||
format = "number"
|
||||
|
||||
[[dashboard.metrics]]
|
||||
label = "Engagement Rate"
|
||||
memory_key = "twitter_hand_engagement_rate"
|
||||
format = "percentage"
|
||||
Reference in New Issue
Block a user