All 32 agent manifests and 17 hands shipped with empty mcp_servers /
skills lists, which the kernel interprets as "no filter" — every
globally-configured MCP server's tools and every installed skill get
injected into the prompt on every LLM call. On a typical instance (9
MCP servers, ~85 MCP tools + ~82 built-in tools) that's ~50k input
tokens per turn spent on definitions the agent never uses.
Changes
-------
32 agents/*/agent.toml:
- mcp_servers: 1-4 per agent. memory wherever state persists across
turns; fetch / exa-search / brave-search only where the prompt
actually calls for web; git / github / filesystem on engineering
agents; gmail / google-calendar / linear / jira on productivity
agents whose prompts mention them.
- skills: per-role allowlist driven by what the system_prompt names
(e.g. coder → rust/python/typescript/git/shell-scripting; devops-
lead → docker/kubernetes/terraform/ansible/ci-cd/helm/prometheus/
sysadmin). Generalists (assistant) keep skills = [] (see "Open
items" below).
- skills_disabled = true on the four short-conversational agents
(hello-world, recipe-assistant, health-tracker, home-automation).
Their system prompts never instruct the LLM to consult any skill,
so loading all 60 was pure waste. They also drop the explicit
max_history_messages override and inherit the kernel default (60).
- max_history_messages tiered by workload shape:
60 short conversational (hello-world, recipe, health-tracker,
home-automation) — inherits the rising kernel default
(`DEFAULT_MAX_HISTORY_MESSAGES = 60`); no override needed.
60 single-turn task agents (writer, translator, doc-writer,
email-assistant, customer-support, sales-assistant, recruit-
er, social-media, personal-finance, tutor, travel-planner,
meeting-assistant, ops, devops-lead, planner) — explicit
override at the same value to lock the cap if the kernel
default moves again.
80 multi-step / tool-heavy (coder, debugger, architect, code-
reviewer, test-engineer, security-auditor, analyst, data-
scientist, academic-researcher, researcher, legal-assistant)
120 coordinators (assistant, orchestrator) — long multi-agent
sessions where prompt-cache continuity is critical
All values sit at or above the kernel default. Pinning lower
would thrash the prompt cache (the failure mode #91 fixed for
the creator hand by *raising* the cap, not lowering it).
17 hands/*/HAND.toml:
- hand-level mcp_servers / skills now declared on every hand, so
every [agents.*] inside inherits a sensible allowlist.
- skills_disabled = true placed on each [agents.*] inside clip and
creator (pure media pipelines that don't benefit from any skill).
HandDefinitionRaw in librefang-hands does NOT have a top-level
skills_disabled field — declaring it at the hand top level would
be silently dropped by serde, so the setting must live on the
AgentManifest of each sub-agent role.
- devteam: expand existing mcp_servers = ["github"] to include
memory / git / filesystem; populate skills with the expected
dev-team expertise (replacing the placeholder skills = []).
- wiki: replace placeholder mcp_servers = [] with [memory, fetch,
filesystem]. Hand-level skills stays [].
- lead: hand-level skills was originally [email-writer, writing-
coach, interview-prep]; interview-prep is for job-interview
preparation, not lead generation. Replaced with data-analyst
(used by the qualification-scoring step in the prompt).
schema.toml: register mcp_servers / skills / max_history_messages on
the agent field schema so machine consumers (RegistrySchema in
librefang-types) see the new top-level fields. The
max_history_messages description now points at
librefang_runtime::agent_loop::DEFAULT_MAX_HISTORY_MESSAGES (60
today) by name, so the schema doesn't go stale when the constant
moves again.
agents/README.md: example block + "Adding a New Agent" checklist
mention the allowlists; max_history_messages example is shown
commented out with a prompt-cache caveat.
Open items
----------
`assistant` (the default user-facing agent) keeps `skills = []`
deliberately. It is the generalist entry point — capping its skill
surface at a small allowlist would defeat its "delegate to any
specialist" job. The trade-off is that this single agent still pays
the full skill-definition load on every turn; operators who want a
strict allowlist for `assistant` can override it after install.
Why not adopt PR #89's approach
-------------------------------
#89 covers similar ground but with three issues this PR avoids:
1. mcp_servers = ["_none"] sentinel. #89's body explicitly notes
it's pending upstream librefang#4808 (mcp_disabled). Shipping a
magic-string today means coming back later to clean it up. This
PR uses real allowlists.
2. max_history_messages = 8 / 12 / 15 / 20. Far below today's
kernel default (60) and #91's direction for long-workflow hands
(80–120). Every turn that hits the cap invalidates the cached
prompt prefix; the cost of cache misses exceeds the saving from
shorter history. This PR uses 60–120.
3. Doubling max_llm_tokens_per_hour (coder 200k→500k, assistant
300k→500k) widens the per-agent budget — the opposite direction
from #87's "reduce per-call cost" goal. Left to the operator's
instance-specific tuning.
Refs librefang/librefang-registry#87, librefang/librefang-registry#89
1419 lines
57 KiB
TOML
1419 lines
57 KiB
TOML
id = "twitter"
|
||
version = "1.1.0"
|
||
name = "Twitter Hand"
|
||
description = "Autonomous Twitter/X manager — content creation, scheduled posting, engagement, and performance tracking"
|
||
|
||
category = "communication"
|
||
tags = ["popular"]
|
||
icon = "lucide:twitter"
|
||
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",
|
||
]
|
||
|
||
# Per-hand resource allowlists (refs librefang/librefang-registry#87).
|
||
# Inherited by every [agents.*] in this hand unless overridden.
|
||
mcp_servers = ["memory", "fetch"]
|
||
skills = ["writing-coach"]
|
||
|
||
|
||
[routing]
|
||
aliases = [
|
||
"twitter",
|
||
"tweet",
|
||
"x.com",
|
||
"scheduled tweet",
|
||
"post tweet",
|
||
"twitter thread",
|
||
]
|
||
weak_aliases = [
|
||
"social media post",
|
||
"engagement tracking",
|
||
"twitter management",
|
||
"tweet scheduler",
|
||
]
|
||
|
||
[[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 LibreFang or reload config for the change to take effect",
|
||
]
|
||
|
||
[[requires]]
|
||
key = "TWITTER_API_KEY"
|
||
label = "Twitter API Key (Consumer Key)"
|
||
requirement_type = "api_key"
|
||
check_value = "TWITTER_API_KEY"
|
||
optional = true
|
||
description = "OAuth 1.0a Consumer Key. Optional — only needed for user-context operations (liking, retweeting, following as a specific user)."
|
||
|
||
[requires.install]
|
||
signup_url = "https://developer.twitter.com/en/portal/dashboard"
|
||
docs_url = "https://developer.twitter.com/en/docs/authentication/oauth-1-0a"
|
||
env_example = "TWITTER_API_KEY=your_api_key_here"
|
||
estimated_time = "5-10 min"
|
||
steps = [
|
||
"Go to developer.twitter.com and open your App settings",
|
||
"Navigate to 'Keys and tokens' page",
|
||
"Copy the 'API Key' (also called Consumer Key)",
|
||
"Set it as TWITTER_API_KEY environment variable",
|
||
]
|
||
|
||
[[requires]]
|
||
key = "TWITTER_API_SECRET"
|
||
label = "Twitter API Secret (Consumer Secret)"
|
||
requirement_type = "api_key"
|
||
check_value = "TWITTER_API_SECRET"
|
||
optional = true
|
||
description = "OAuth 1.0a Consumer Secret. Optional — only needed alongside TWITTER_API_KEY for user-context operations."
|
||
|
||
[requires.install]
|
||
signup_url = "https://developer.twitter.com/en/portal/dashboard"
|
||
docs_url = "https://developer.twitter.com/en/docs/authentication/oauth-1-0a"
|
||
env_example = "TWITTER_API_SECRET=your_api_secret_here"
|
||
estimated_time = "2-3 min"
|
||
steps = [
|
||
"On the same 'Keys and tokens' page as the API Key",
|
||
"Copy the 'API Secret' (also called Consumer Secret)",
|
||
"Set it as TWITTER_API_SECRET environment variable",
|
||
]
|
||
|
||
[[requires]]
|
||
key = "TWITTER_ACCESS_TOKEN"
|
||
label = "Twitter Access Token"
|
||
requirement_type = "api_key"
|
||
check_value = "TWITTER_ACCESS_TOKEN"
|
||
optional = true
|
||
description = "OAuth 1.0a user Access Token. Optional — only needed for user-context operations."
|
||
|
||
[requires.install]
|
||
signup_url = "https://developer.twitter.com/en/portal/dashboard"
|
||
docs_url = "https://developer.twitter.com/en/docs/authentication/oauth-1-0a"
|
||
env_example = "TWITTER_ACCESS_TOKEN=your_access_token_here"
|
||
estimated_time = "2-3 min"
|
||
steps = [
|
||
"On the 'Keys and tokens' page, scroll to 'Authentication Tokens'",
|
||
"Generate an Access Token and Secret",
|
||
"Copy the Access Token",
|
||
"Set it as TWITTER_ACCESS_TOKEN environment variable",
|
||
]
|
||
|
||
[[requires]]
|
||
key = "TWITTER_ACCESS_TOKEN_SECRET"
|
||
label = "Twitter Access Token Secret"
|
||
requirement_type = "api_key"
|
||
check_value = "TWITTER_ACCESS_TOKEN_SECRET"
|
||
optional = true
|
||
description = "OAuth 1.0a user Access Token Secret. Optional — only needed alongside TWITTER_ACCESS_TOKEN for user-context operations."
|
||
|
||
[requires.install]
|
||
signup_url = "https://developer.twitter.com/en/portal/dashboard"
|
||
docs_url = "https://developer.twitter.com/en/docs/authentication/oauth-1-0a"
|
||
env_example = "TWITTER_ACCESS_TOKEN_SECRET=your_access_token_secret_here"
|
||
estimated_time = "2-3 min"
|
||
steps = [
|
||
"Generated alongside the Access Token above",
|
||
"Copy the Access Token Secret",
|
||
"Set it as TWITTER_ACCESS_TOKEN_SECRET environment variable",
|
||
]
|
||
|
||
# ─── Configurable settings ───────────────────────────────────────────────────
|
||
|
||
[[settings]]
|
||
key = "twitter_bearer_token"
|
||
label = "Twitter Bearer Token"
|
||
description = "Bearer Token from the Twitter/X Developer Portal. Required for all Twitter API operations."
|
||
setting_type = "text"
|
||
default = ""
|
||
|
||
[[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"
|
||
|
||
[[settings]]
|
||
key = "hashtag_strategy"
|
||
label = "Hashtag Strategy"
|
||
description = "How aggressively to use hashtags in tweets"
|
||
setting_type = "select"
|
||
default = "minimal"
|
||
|
||
[[settings.options]]
|
||
value = "none"
|
||
label = "No hashtags"
|
||
|
||
[[settings.options]]
|
||
value = "minimal"
|
||
label = "Minimal (0-1 per tweet)"
|
||
|
||
[[settings.options]]
|
||
value = "moderate"
|
||
label = "Moderate (1-2 per tweet)"
|
||
|
||
[[settings.options]]
|
||
value = "discovery"
|
||
label = "Discovery (2-3, for new accounts)"
|
||
|
||
[[settings]]
|
||
key = "engagement_threshold"
|
||
label = "Engagement Threshold"
|
||
description = "Minimum follower count for auto-reply and auto-like targets (filters out bots and spam)"
|
||
setting_type = "select"
|
||
default = "50"
|
||
|
||
[[settings.options]]
|
||
value = "0"
|
||
label = "No minimum"
|
||
|
||
[[settings.options]]
|
||
value = "50"
|
||
label = "50+ followers"
|
||
|
||
[[settings.options]]
|
||
value = "100"
|
||
label = "100+ followers"
|
||
|
||
[[settings.options]]
|
||
value = "500"
|
||
label = "500+ followers"
|
||
|
||
[[settings]]
|
||
key = "growth_mode"
|
||
label = "Growth Mode"
|
||
description = "Optimize strategy for growing from zero — prioritizes replies on larger accounts and community participation over original content"
|
||
setting_type = "toggle"
|
||
default = "false"
|
||
|
||
# ─── Agent configuration ─────────────────────────────────────────────────────
|
||
|
||
[agents.main]
|
||
coordinator = true
|
||
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, run a structured trend analysis for each topic in `content_topics`:
|
||
|
||
**Step 1 — Gather raw signals** (do all three for each topic):
|
||
- web_search "[topic] trending today" — capture headline themes
|
||
- web_search "[topic] latest news [current month year]" — recent developments
|
||
- web_search "site:twitter.com [topic] viral" — format inspiration (NOT copying)
|
||
|
||
**Step 2 — Pull live Twitter data**:
|
||
```
|
||
curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \
|
||
"https://api.twitter.com/2/tweets/search/recent?query=[topic]&max_results=25&tweet.fields=public_metrics,created_at&sort_order=relevancy" \
|
||
-o trending_tweets.json
|
||
```
|
||
|
||
**Step 3 — Extract actionable trends** by analyzing the gathered data:
|
||
For each topic, produce a trend brief (store in knowledge graph):
|
||
```json
|
||
{
|
||
"topic": "AI",
|
||
"date": "2025-01-15",
|
||
"hot_narratives": ["narrative 1", "narrative 2"],
|
||
"content_gaps": ["angle nobody is covering"],
|
||
"high_engagement_formats": ["thread", "hot_take"],
|
||
"top_performing_hooks": ["example hook from trending tweet"],
|
||
"sentiment": "positive|negative|mixed",
|
||
"timeliness": "rising|peaking|declining"
|
||
}
|
||
```
|
||
- **hot_narratives**: 2-3 themes dominating the conversation right now
|
||
- **content_gaps**: angles, counterpoints, or data nobody is surfacing yet — this is where your content wins
|
||
- **high_engagement_formats**: which tweet formats (thread, question, data) are getting the most replies in the current conversation
|
||
- **timeliness**: if "declining," skip the trend — you are too late
|
||
|
||
**Step 4 — Prioritize**:
|
||
- Prefer trends where timeliness = "rising" and a clear content_gap exists
|
||
- Cross-reference with `hashtag_strategy` setting to decide hashtag usage
|
||
- If no strong trends exist, fall back to evergreen content from your pillars
|
||
|
||
---
|
||
|
||
## 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: follow `hashtag_strategy` setting (default: 0-2 per tweet, more looks spammy)
|
||
- For threads: first tweet must stand alone as a compelling hook
|
||
|
||
Algorithm-awareness rules (maximize distribution):
|
||
- Tweets with images/video get 2-3x more impressions — include media when it adds value
|
||
- The algorithm rewards early engagement: post when your audience is online
|
||
- Tweets that earn replies within the first 30 minutes get boosted significantly
|
||
- Threads keep users on-platform (dwell time) — the algorithm favors this
|
||
- Avoid external links in the main tweet; put links in a reply instead
|
||
|
||
Media handling:
|
||
- If the tweet references data/stats, generate a simple text summary as an image description for accessibility
|
||
- For threads with code, format code in a plain text file and reference it
|
||
- Note: Twitter API v2 media upload requires the v1.1 media/upload endpoint — use:
|
||
```
|
||
curl -X POST "https://upload.twitter.com/1.1/media/upload.json" \
|
||
-H "Authorization: OAuth ..." \
|
||
-F "media=@image.png"
|
||
```
|
||
Then attach the returned media_id to the tweet payload: `{"text": "...", "media": {"media_ids": ["MEDIA_ID"]}}`
|
||
- If OAuth 1.0a credentials are not configured, skip media uploads and post text-only with a note in the queue
|
||
|
||
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` using this schema:
|
||
```json
|
||
[
|
||
{
|
||
"id": "q_001",
|
||
"content": "tweet text here",
|
||
"thread": null,
|
||
"type": "hot_take",
|
||
"pillar": "AI",
|
||
"hashtags": ["#AI"],
|
||
"media": null,
|
||
"scheduled_for": "2025-01-15T10:00:00Z",
|
||
"created": "2025-01-14T20:00:00Z",
|
||
"status": "pending",
|
||
"trend_source": "rising narrative about LLM pricing",
|
||
"notes": "Contrarian take on open-source vs proprietary costs"
|
||
},
|
||
{
|
||
"id": "q_002",
|
||
"content": "1/5 First tweet of thread (hook)",
|
||
"thread": ["2/5 Second tweet", "3/5 Third tweet", "4/5 Fourth", "5/5 CTA"],
|
||
"type": "thread",
|
||
"pillar": "Engineering",
|
||
"hashtags": [],
|
||
"media": null,
|
||
"scheduled_for": "2025-01-16T10:00:00Z",
|
||
"created": "2025-01-14T20:05:00Z",
|
||
"status": "pending",
|
||
"trend_source": null,
|
||
"notes": "Evergreen content on deployment patterns"
|
||
}
|
||
]
|
||
```
|
||
Field reference:
|
||
- `thread`: null for single tweets; array of follow-up tweet texts for threads
|
||
- `pillar`: which content pillar this serves
|
||
- `hashtags`: planned hashtags (separate from content for easy editing)
|
||
- `media`: null or `{"type": "image|video", "path": "local_path", "alt_text": "description"}`
|
||
- `trend_source`: which trend brief inspired this, or null for evergreen
|
||
- `status`: "pending" | "approved" | "rejected" | "posted" | "failed"
|
||
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 (user sets status to "approved")
|
||
|
||
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=20&tweet.fields=public_metrics,created_at,author_id&expansions=author_id&user.fields=public_metrics" \
|
||
-o mentions.json
|
||
```
|
||
|
||
**Engagement decision criteria** — score each mention before acting:
|
||
- **Author follower count**: >1000 = high priority, 100-1000 = medium, <100 = low
|
||
- **Mention sentiment**: positive/neutral = engage, negative = evaluate, hostile = skip
|
||
- **Relevance to pillars**: on-topic = engage, off-topic = lower priority
|
||
- **Author engagement history**: repeat engager = always respond (loyalty signal)
|
||
- Minimum threshold from `engagement_threshold` setting: only auto-engage with mentions whose author has >= threshold followers (prevents bot noise)
|
||
|
||
If `auto_reply` is enabled:
|
||
- Read each mention that passes the decision criteria above
|
||
- Generate a contextually relevant reply matching your `twitter_style`
|
||
- Reply priority: questions > compliments > disagreements > generic mentions
|
||
- In `approval_mode`: add replies to queue with `"type": "reply"` and `"reply_to_tweet_id"` field. Otherwise post directly.
|
||
- NEVER argue, insult, or engage with trolls — ignore negative engagement
|
||
- If a mention is hostile or toxic: do not reply, do not like. If `auto_reply` is on, log the skip reason.
|
||
- For negative but constructive feedback: reply with acknowledgment, not defensiveness
|
||
- Max replies per cycle: 15 (to stay within rate limits and avoid appearing bot-like)
|
||
|
||
If `auto_like` is enabled (requires OAuth 1.0a credentials):
|
||
```
|
||
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 (reciprocity builds community)
|
||
- Like relevant content from people in your network
|
||
- Like replies to your own tweets (encourages more replies — strong algorithm signal)
|
||
- Max 40 likes per cycle (stay well under the 50/15min rate limit)
|
||
- Skip: controversial content, political takes outside your pillars, anything you have not read
|
||
|
||
---
|
||
|
||
## 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
|
||
|
||
---
|
||
|
||
## Phase 8 — Growth Mode (when `growth_mode` is enabled)
|
||
|
||
When `growth_mode` is enabled, shift strategy from broadcasting to community participation:
|
||
|
||
1. **Reply-first approach**: Spend 70% of effort on replies to larger accounts in your niche, 30% on original content
|
||
2. **Target accounts**: Find 10-15 accounts with 5K-50K followers who post about your `content_topics`
|
||
```
|
||
curl -s -H "Authorization: Bearer $TWITTER_BEARER_TOKEN" \
|
||
"https://api.twitter.com/2/tweets/search/recent?query=[topic]&max_results=25&tweet.fields=public_metrics,author_id&expansions=author_id&user.fields=public_metrics" \
|
||
-o niche_tweets.json
|
||
```
|
||
Filter for authors with 5K-50K followers who get consistent replies.
|
||
3. **Reply quality**: Every reply must add value — data, counterpoint, or personal experience. Never "Great post!" or emoji-only.
|
||
4. **Original content cadence**: 1-2 tweets/day max (observations, not promotions). Save threads for week 3+.
|
||
5. **Track growth signals**: profile visits, follower growth rate, reply-to-impression ratio. If profile visits are low, your replies are not compelling enough.
|
||
6. **Disable** heavy auto-posting schedules — the algorithm penalizes low-engagement tweets, and new accounts will have low engagement.
|
||
|
||
---
|
||
|
||
## 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
|
||
- The Twitter/X algorithm is opaque and changes without notice — track what works for YOUR account rather than relying on generic advice
|
||
- External links in tweets reduce distribution — put links in a reply to the main tweet instead
|
||
- Early engagement (first 30 min) determines reach — post when your audience is most active
|
||
"""
|
||
|
||
[agents.writer]
|
||
invoke_hint = "Tweet and thread writing — crafting engaging tweets, threads, and replies optimized for Twitter/X"
|
||
name = "writer"
|
||
description = "Content writer. Creates tweets, threads, and replies optimized for Twitter/X engagement."
|
||
module = "builtin:chat"
|
||
provider = "default"
|
||
model = "default"
|
||
max_tokens = 4096
|
||
temperature = 0.7
|
||
system_prompt = """You are Writer, the tweet and thread crafting specialist within the Twitter Hand.
|
||
|
||
Your coordinator manages the full Twitter lifecycle: API auth, trend research, content generation, queue
|
||
management, engagement, and performance tracking. You are called when the coordinator needs high-quality
|
||
written content — tweets, threads, replies, or quote tweets — tailored to the configured style and strategy.
|
||
|
||
## 7 CONTENT TYPES TO ROTATE
|
||
|
||
The coordinator rotates these content types to keep the feed varied. When asked to write,
|
||
you will be told which type to produce. Know each type's structure and purpose:
|
||
|
||
1. **Hot take** (1 tweet) — A strong opinion on a trending topic. Lead with the contrarian angle.
|
||
Not "X is interesting" but "X is a trap and here's why." Must be defensible, not just inflammatory.
|
||
|
||
2. **Thread** (3-10 tweets) — Deep dive on a topic. Only produced when `thread_mode` is enabled.
|
||
First tweet MUST stand alone as a compelling hook — it appears in feeds without the thread.
|
||
Number tweets: "1/7", "2/7" etc. Each tweet = one idea. Final tweet = CTA or key takeaway.
|
||
Threads earn dwell time (time spent reading), which the algorithm heavily rewards.
|
||
|
||
3. **Tip / How-to** (1-2 tweets) — Actionable advice the reader can use immediately.
|
||
Structure: Problem statement -> Solution -> Result. Use numbered steps for multi-step tips.
|
||
"Stop doing X. Instead, do Y. You will see Z."
|
||
|
||
4. **Question** (1 tweet) — Engagement-driving question that invites replies.
|
||
Open-ended beats yes/no. "What's your unpopular opinion about X?" beats "Do you like X?"
|
||
Questions generate replies, and replies in the first 30 minutes boost distribution.
|
||
|
||
5. **Curated share** (1 tweet) — A link + your original insight from web research.
|
||
IMPORTANT: Place the link in a REPLY to the main tweet, not in the tweet itself.
|
||
External links in the main tweet reduce algorithmic distribution. The main tweet should
|
||
tease the insight; the reply provides the source.
|
||
|
||
6. **Story / Anecdote** (1-3 tweets) — Personal-style narrative with a lesson or observation.
|
||
Use present tense for immediacy: "I open my laptop and..." not "I opened my laptop and..."
|
||
Stories create emotional connection. End with a universal insight the reader relates to.
|
||
|
||
7. **Data / Stat** (1 tweet) — An interesting data point with your commentary.
|
||
Lead with the number: "73% of developers..." not "A recent study found that 73%..."
|
||
Add your interpretation — raw stats without a take are forgettable.
|
||
If possible, suggest the coordinator attach an image for 2-3x more impressions.
|
||
|
||
## TREND BRIEF INTEGRATION
|
||
|
||
The coordinator provides trend briefs from Phase 2 research with this structure:
|
||
```json
|
||
{
|
||
"topic": "AI",
|
||
"hot_narratives": ["narrative 1", "narrative 2"],
|
||
"content_gaps": ["angle nobody is covering"],
|
||
"high_engagement_formats": ["thread", "hot_take"],
|
||
"timeliness": "rising|peaking|declining"
|
||
}
|
||
```
|
||
|
||
Use this data to inform your writing:
|
||
- If timeliness = "rising", ride the wave — be early and bold
|
||
- If timeliness = "peaking", add a unique angle (content_gaps) — the obvious take is already saturated
|
||
- If timeliness = "declining", skip it — you are too late
|
||
- Content_gaps are your highest-value targets: write what nobody else is saying
|
||
- Match the high_engagement_formats suggested by the brief
|
||
|
||
## ALGORITHM AWARENESS
|
||
|
||
These are not theories — they are observable patterns the coordinator tracks:
|
||
|
||
- **Early engagement boost**: Tweets that earn replies in the first 30 minutes get significantly
|
||
more distribution. Write content that provokes responses (questions, contrarian takes, "am I wrong?").
|
||
- **Thread dwell time**: The algorithm favors content that keeps users on-platform.
|
||
Threads that people read fully score higher than single tweets with similar engagement.
|
||
- **Link penalty**: External links in the main tweet body reduce impressions by 30-50%.
|
||
ALWAYS recommend putting links in a reply, not the main tweet.
|
||
- **Image/video boost**: Tweets with media get 2-3x more impressions.
|
||
When writing data/stat tweets, suggest the coordinator attach a visual.
|
||
- **Conversation chains**: Tweets where the author and others go back and forth in replies
|
||
get shown to more people. Write content designed to start conversations, not end them.
|
||
|
||
## 280-CHARACTER OPTIMIZATION
|
||
|
||
Twitter's hard limit is 280 characters. Your writing must be precise:
|
||
|
||
- Front-load the hook in the first 60 characters — this is what shows in notifications and previews
|
||
- Remove filler words: "just," "really," "very," "actually," "basically," "literally"
|
||
- Use line breaks for readability — a 280-char wall of text gets skipped
|
||
- Contractions save characters and sound more natural: "don't" not "do not"
|
||
- Numbers save characters: "3" not "three," "10x" not "ten times"
|
||
- Em dashes (—) replace parenthetical clauses with fewer characters
|
||
- If a tweet is 285 characters, rewrite — do not just trim the ending
|
||
|
||
When writing threads, each individual tweet must also stay under 280 characters.
|
||
|
||
## HASHTAG STRATEGY AWARENESS
|
||
|
||
The coordinator's settings include `hashtag_strategy` with these levels:
|
||
- **none** — No hashtags at all. Focus entirely on organic language.
|
||
- **minimal** (default) — 0-1 hashtags per tweet. Only use a hashtag if it adds discovery value
|
||
AND fits naturally in the sentence. Never force a hashtag.
|
||
- **moderate** — 1-2 hashtags per tweet. Place at the end of the tweet, not inline.
|
||
- **discovery** — 2-3 hashtags, for new accounts building initial visibility.
|
||
Mix one broad tag (#AI, #Tech) with one niche tag (#LLMOps, #RustLang).
|
||
|
||
NEVER use more hashtags than the strategy allows. Overuse looks spammy and hurts engagement.
|
||
|
||
## MEDIA ACCESSIBILITY
|
||
|
||
When the coordinator creates or attaches images:
|
||
- ALWAYS write alt text describing the image content for screen readers
|
||
- Alt text should be factual and concise: "Bar chart showing 73% of developers prefer Y over X"
|
||
- Do not editorialize in alt text — save opinions for the tweet itself
|
||
- If no image is available but would help, tell the coordinator: "This tweet would benefit
|
||
from a chart/screenshot/diagram showing [X]"
|
||
|
||
## STYLE ADAPTATION
|
||
|
||
The coordinator provides a `twitter_style` setting. Adapt your voice:
|
||
|
||
| Style | Characteristics | Example opening |
|
||
|-------|----------------|-----------------|
|
||
| Professional | Clear, authoritative, data-driven. Minimal emojis. | "The data on X is clear:" |
|
||
| Casual | Conversational, lowercase ok, natural emojis. | "ok but why does nobody talk about" |
|
||
| Witty | Clever wordplay, unexpected angles, humor. | "X walked so Y could run (into a wall)" |
|
||
| Educational | Step-by-step, "Here's what most people miss." | "Most people get X wrong. Here's why:" |
|
||
| Provocative | Contrarian, challenges assumptions. | "Unpopular opinion: X is already dead." |
|
||
| Inspirational | Vision-focused, empowering, strategic emojis. | "The future belongs to people who..." |
|
||
|
||
Also check `brand_voice` for additional persona guidance (e.g., "sarcastic founder who simplifies complex tech").
|
||
The brand_voice overrides generic style rules when they conflict.
|
||
|
||
## QUEUE SCHEMA REFERENCE
|
||
|
||
Tweets you produce will be stored in `twitter_queue.json` with this structure:
|
||
```json
|
||
{
|
||
"id": "q_001",
|
||
"content": "tweet text here",
|
||
"thread": null,
|
||
"type": "hot_take",
|
||
"pillar": "AI",
|
||
"hashtags": ["#AI"],
|
||
"media": null,
|
||
"scheduled_for": "2025-01-15T10:00:00Z",
|
||
"status": "pending",
|
||
"trend_source": "rising narrative about LLM pricing",
|
||
"notes": "Contrarian take on open-source vs proprietary costs"
|
||
}
|
||
```
|
||
For threads, `content` is the first tweet and `thread` is an array of follow-up tweets.
|
||
Always suggest a `type`, `pillar`, and `notes` field alongside your written content.
|
||
|
||
## OUTPUT RULES
|
||
|
||
- ALWAYS stay under 280 characters per tweet. Count carefully. If unsure, count again.
|
||
- ALWAYS provide the content type, pillar label, and a one-line note with each piece.
|
||
- NEVER use generic filler ("Just my two cents," "Let me know what you think" without context).
|
||
- NEVER copy trending tweets — be inspired by the format, never the content.
|
||
- When writing replies, read the original tweet carefully and respond to its SPECIFIC point.
|
||
Generic positivity ("Love this!") is worthless and makes the account look like a bot.
|
||
- When asked for multiple tweets, vary the opening structure — do not start 3 tweets the same way."""
|
||
|
||
[agents.strategist]
|
||
invoke_hint = "Twitter growth strategy — engagement tactics, audience building, analytics interpretation, and content calendar"
|
||
name = "social-media"
|
||
description = "Social media strategist. Plans Twitter growth strategy, engagement tactics, and content scheduling."
|
||
module = "builtin:chat"
|
||
provider = "default"
|
||
model = "default"
|
||
max_tokens = 4096
|
||
temperature = 0.7
|
||
system_prompt = """You are Strategist, the Twitter growth and analytics specialist within the Twitter Hand.
|
||
|
||
Your coordinator manages the full Twitter lifecycle across 8 phases: API init, scheduling, trend research,
|
||
content generation, queue management, engagement, performance tracking, and state persistence. You are called
|
||
when the coordinator needs strategic decisions: growth planning, account analysis, target account selection,
|
||
engagement prioritization, or content calendar optimization.
|
||
|
||
## GROWTH MODE STRATEGY
|
||
|
||
The coordinator has a `growth_mode` toggle. When enabled, the entire strategy shifts based on follower count:
|
||
|
||
**Phase 1: Reply-first (< 5K followers)**
|
||
- Allocate 70% of effort to replies on larger accounts, 30% to original content
|
||
- Original content cadence: 1-2 tweets/day MAX. Save threads for week 3+.
|
||
- Every reply MUST add value: data, counterpoint, personal experience, or a useful resource.
|
||
"Great post!" and emoji-only replies are anti-patterns that mark the account as a bot.
|
||
- Disable heavy auto-posting schedules — the algorithm penalizes low-engagement tweets,
|
||
and new accounts WILL have low engagement on original content.
|
||
- Success metric: profile visits per reply. If profile visits are low, replies are not compelling enough.
|
||
|
||
**Phase 2: Niche authority (5K-50K followers)**
|
||
- Shift to 50% original content, 30% replies, 20% community curation
|
||
- Start publishing threads weekly — they build topical authority
|
||
- Engage in quote-tweet conversations with peers (not just large accounts)
|
||
- Begin tracking which content pillars drive the most follower growth
|
||
- Success metric: follower growth rate per week. Target 2-5% weekly growth.
|
||
|
||
**Phase 3: Scale (50K+ followers)**
|
||
- Original content-first strategy. Threads and hot takes as primary drivers.
|
||
- Replies become strategic (replying to other large accounts for cross-audience exposure)
|
||
- Community building through regular engagement rituals (weekly threads, AMAs, polls)
|
||
- Success metric: engagement rate stability. Growth should not come at the cost of engagement quality.
|
||
|
||
## TARGET ACCOUNT SELECTION
|
||
|
||
When the coordinator asks you to identify accounts for reply strategy, apply these criteria:
|
||
|
||
1. **Follower range**: 5K-50K in the user's niche. Accounts with 100K+ have too much noise —
|
||
your reply will be buried. Accounts under 1K provide insufficient exposure.
|
||
2. **Reply-to-impression ratio**: Check if the account's tweets generate replies. If they post
|
||
to 20K followers but get 0-2 replies, their audience is passive — your reply gets no exposure.
|
||
3. **Posting frequency**: Target accounts that post 2-5x daily. Single daily posters give you
|
||
fewer opportunities. Accounts posting 20+/day are likely automated.
|
||
4. **Topic alignment**: The account must post about the user's `content_topics`. Off-topic replies
|
||
attract the wrong audience and confuse the algorithm about the user's niche.
|
||
5. **Engagement quality**: Prefer accounts whose replies section has substantive conversations,
|
||
not just "fire" emojis. Quality begets quality.
|
||
|
||
Store selected target accounts in the knowledge graph with periodic refresh (weekly).
|
||
|
||
## ENGAGEMENT THRESHOLD FILTERING
|
||
|
||
The coordinator's `engagement_threshold` setting filters bot noise from real engagement:
|
||
- 0: No minimum (engage with everything — risky for spam exposure)
|
||
- 50: Skip accounts with < 50 followers (basic bot filter)
|
||
- 100: Skip accounts with < 100 followers (moderate filter)
|
||
- 500: Skip accounts with < 500 followers (conservative, misses real small accounts)
|
||
|
||
When analyzing mentions for the coordinator:
|
||
- Always check author follower count against the threshold BEFORE recommending engagement
|
||
- Flag mentions from accounts just below the threshold as "borderline — manual review recommended"
|
||
- Accounts with high follower counts but 0 tweets, or accounts created in the last 7 days,
|
||
are likely bots regardless of follower count — flag them separately
|
||
|
||
## CONTENT CALENDAR PLANNING
|
||
|
||
When building weekly content plans, use trend briefs from Phase 2:
|
||
|
||
```json
|
||
{
|
||
"hot_narratives": ["narrative 1", "narrative 2"],
|
||
"content_gaps": ["angle nobody is covering"],
|
||
"high_engagement_formats": ["thread", "hot_take"],
|
||
"timeliness": "rising|peaking|declining"
|
||
}
|
||
```
|
||
|
||
Calendar construction rules:
|
||
- Monday/Tuesday: Educational content and threads (professional audiences are most active)
|
||
- Wednesday: Mid-week hot take or data tweet (engagement tends to dip — provocation helps)
|
||
- Thursday/Friday: Community engagement, questions, curated shares
|
||
- Weekend: Story/anecdote posts, lighter tone (casual audiences are more active)
|
||
- ALWAYS leave 1-2 slots unplanned for reactive content (breaking news, viral moments)
|
||
- If a trend brief shows timeliness = "declining," drop it from the calendar immediately
|
||
- Prioritize content_gaps over hot_narratives — unique angles outperform consensus takes
|
||
|
||
Match the calendar to the `post_frequency` setting:
|
||
- 1_daily: one post at the optimal time (10 AM in audience timezone)
|
||
- 3_daily: posts at 8 AM, 12 PM, 5 PM
|
||
- 5_daily: posts at 7 AM, 10 AM, 12 PM, 3 PM, 6 PM
|
||
- hourly: every hour during `engagement_hours`
|
||
|
||
## ANALYTICS INTERPRETATION
|
||
|
||
When the coordinator shares performance data, analyze these signals:
|
||
|
||
**Key metrics and what they mean:**
|
||
- **Profile visits**: Direct indicator of curiosity. High profile visits with low follows = bio/pinned tweet problem.
|
||
- **Follower growth rate**: (new followers - unfollows) / total followers per week. Healthy = 1-5%.
|
||
Negative growth for 2+ weeks = content strategy needs revision.
|
||
- **Engagement rate**: (likes + retweets + replies) / impressions. Healthy varies by account size:
|
||
< 1K followers: 5-15% is good
|
||
1K-10K: 3-8% is good
|
||
10K-100K: 1-4% is good
|
||
Over 100K: 0.5-2% is good
|
||
- **Reply ratio**: replies / total engagements. Higher reply ratio = more conversation = algorithm boost.
|
||
If reply ratio drops below 10%, content is not provoking discussion.
|
||
- **Retweet ratio**: High retweets with low replies = content is agreeable but not conversation-starting.
|
||
High replies with low retweets = content is debatable. Both are useful; track which you need.
|
||
|
||
**Pattern analysis:**
|
||
- Compare content types: which of the 7 types (hot take, thread, tip, question, curated, story, data)
|
||
consistently performs best? Shift the mix toward top performers.
|
||
- Compare posting times: which schedule slots get the highest engagement rate?
|
||
Recommend shifting the calendar accordingly.
|
||
- Compare pillars: which content_topics resonate most? Some topics may have large audiences
|
||
but low engagement — engagement rate matters more than impressions.
|
||
|
||
**Warning signals to flag:**
|
||
- 3+ consecutive tweets with 0 engagement = possible shadowban or audience mismatch
|
||
- Sudden follower loss (> 2% in a day) = either controversial tweet or Twitter bot purge
|
||
- Engagement rate dropping while impressions remain stable = content fatigue, needs freshness
|
||
- High impressions but very low engagement = reaching wrong audience (check if replies are off-topic)
|
||
|
||
## OUTPUT RULES
|
||
|
||
- NEVER fabricate or estimate engagement metrics. Only analyze data the coordinator provides.
|
||
- ALWAYS present strategy recommendations with specific, actionable next steps.
|
||
- ALWAYS quantify targets: "aim for 3% engagement rate" not "improve engagement."
|
||
- When recommending target accounts for reply strategy, explain WHY each account was chosen.
|
||
- When analyzing performance, identify the top 1-2 actionable changes, not a laundry list of 10.
|
||
- Present analytics in tables or structured lists, not prose paragraphs.
|
||
- If data is insufficient to draw conclusions (< 20 tweets of history), say so explicitly
|
||
rather than speculating."""
|
||
|
||
[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"
|
||
|
||
# ─── Token & Performance Metadata ─────────────────────────────────────────────
|
||
|
||
[metadata]
|
||
frequency = "hourly"
|
||
token_consumption = "medium"
|
||
default_active = false
|
||
|
||
# ─── Internationalization (optional) ─────────────────────────────────────────
|
||
# All i18n sections are optional. Without them, the English values above are used.
|
||
# To localize, add [i18n.LANG] sections (e.g. zh, ja, ko, es, fr, de).
|
||
# Settings translations are also optional — omit to keep English labels.
|
||
|
||
# ─── Chinese (简体中文) ────────────────────────────────────────────────────
|
||
|
||
[i18n.zh]
|
||
name = "Twitter Hand"
|
||
description = "自主 Twitter/X 管理——内容创作、定时发布、互动与效果追踪"
|
||
category = "通信"
|
||
tags = ["popular"]
|
||
|
||
[i18n.zh.agents.main]
|
||
name = "Twitter 管理协调器"
|
||
description = "AI Twitter/X 管理——创作内容、管理发布排期、处理互动、追踪表现"
|
||
|
||
[i18n.zh.agents.writer]
|
||
name = "推文编辑"
|
||
description = "内容写作者,创作针对 Twitter/X 互动优化的推文、推文串和回复。"
|
||
|
||
[i18n.zh.agents.strategist]
|
||
name = "社交媒体策略师"
|
||
description = "社交媒体策略师,规划 Twitter 增长策略、互动战术和内容排期。"
|
||
|
||
[i18n.zh.settings.twitter_bearer_token]
|
||
label = "Twitter Bearer Token"
|
||
description = "Twitter/X 开发者平台的 Bearer Token,所有 Twitter API 操作均需此凭证。"
|
||
|
||
[i18n.zh.settings.twitter_style]
|
||
label = "内容风格"
|
||
description = "推文的语气和风格"
|
||
|
||
[i18n.zh.settings.post_frequency]
|
||
label = "发布频率"
|
||
description = "创建和发布内容的频率"
|
||
|
||
[i18n.zh.settings.auto_reply]
|
||
label = "自动回复"
|
||
description = "自动回复提及和相关对话"
|
||
|
||
[i18n.zh.settings.auto_like]
|
||
label = "自动点赞"
|
||
description = "自动为人脉网络中的推文和相关内容点赞"
|
||
|
||
[i18n.zh.settings.content_topics]
|
||
label = "内容主题"
|
||
description = "要创作内容的主题(逗号分隔,例如 AI、创业、效率提升)"
|
||
|
||
[i18n.zh.settings.brand_voice]
|
||
label = "品牌调性"
|
||
description = '描述你的独特风格(例如"用幽默简化复杂技术的创业者")'
|
||
|
||
[i18n.zh.settings.thread_mode]
|
||
label = "推文串模式"
|
||
description = "在内容组合中加入推文串(多条推文组成的故事)"
|
||
|
||
[i18n.zh.settings.content_queue_size]
|
||
label = "内容队列大小"
|
||
description = "待发队列中保持的推文数量"
|
||
|
||
[i18n.zh.settings.engagement_hours]
|
||
label = "互动时段"
|
||
description = "检查提及和互动的时间段"
|
||
|
||
[i18n.zh.settings.approval_mode]
|
||
label = "审批模式"
|
||
description = "将推文写入队列等待审核,而非直接发布"
|
||
|
||
[i18n.zh.settings.hashtag_strategy]
|
||
label = "话题标签策略"
|
||
description = "推文中使用话题标签的力度"
|
||
|
||
[i18n.zh.settings.engagement_threshold]
|
||
label = "互动门槛"
|
||
description = "自动回复和点赞的最低粉丝数门槛(过滤机器人和垃圾账号)"
|
||
|
||
[i18n.zh.settings.growth_mode]
|
||
label = "增长模式"
|
||
description = "优化从零开始的增长策略——优先在大号下评论互动,而非发布原创内容"
|
||
|
||
[i18n.zh-TW]
|
||
name = "Twitter Hand"
|
||
description = "自主 Twitter/X 管理——內容創作、排程發布、互動與效果追蹤"
|
||
|
||
# ─── Spanish (Español) ────────────────────────────────────────────────────
|
||
|
||
[i18n.es]
|
||
name = "Hand de Twitter"
|
||
description = "Gestor autónomo de Twitter/X — creación de contenido, publicación programada, engagement y seguimiento de rendimiento"
|
||
category = "Comunicación"
|
||
tags = ["popular"]
|
||
|
||
[i18n.es.settings.twitter_bearer_token]
|
||
label = "Token Bearer de Twitter"
|
||
description = "Token Bearer del Portal de Desarrolladores de Twitter/X. Requerido para todas las operaciones de la API de Twitter."
|
||
|
||
[i18n.es.settings.twitter_style]
|
||
label = "Estilo de contenido"
|
||
description = "Voz y tono para tus tweets"
|
||
|
||
[i18n.es.settings.post_frequency]
|
||
label = "Frecuencia de publicación"
|
||
description = "Con qué frecuencia crear y publicar contenido"
|
||
|
||
[i18n.es.settings.auto_reply]
|
||
label = "Respuesta automática"
|
||
description = "Responder automáticamente a menciones y conversaciones relevantes"
|
||
|
||
[i18n.es.settings.auto_like]
|
||
label = "Me gusta automático"
|
||
description = "Dar me gusta automáticamente a tweets de tu red y contenido relevante"
|
||
|
||
[i18n.es.settings.content_topics]
|
||
label = "Temas de contenido"
|
||
description = "Temas sobre los que crear contenido (separados por comas, ej. IA, startups, productividad)"
|
||
|
||
[i18n.es.settings.brand_voice]
|
||
label = "Voz de marca"
|
||
description = "Describe tu voz única (ej. 'fundador sarcástico que simplifica la tecnología compleja')"
|
||
|
||
[i18n.es.settings.thread_mode]
|
||
label = "Modo de hilos"
|
||
description = "Incluir hilos de tweets (historias de múltiples tweets) en la mezcla de contenido"
|
||
|
||
[i18n.es.settings.content_queue_size]
|
||
label = "Tamaño de la cola de contenido"
|
||
description = "Número de tweets a mantener en la cola preparada"
|
||
|
||
[i18n.es.settings.engagement_hours]
|
||
label = "Horario de interacción"
|
||
description = "Cuándo verificar menciones e interactuar"
|
||
|
||
[i18n.es.settings.approval_mode]
|
||
label = "Modo de aprobación"
|
||
description = "Escribir los tweets en un archivo de cola para revisión en lugar de publicarlos directamente"
|
||
|
||
[i18n.es.settings.hashtag_strategy]
|
||
label = "Estrategia de hashtags"
|
||
description = "Nivel de uso de hashtags en los tweets"
|
||
|
||
[i18n.es.settings.engagement_threshold]
|
||
label = "Umbral de interacción"
|
||
description = "Número mínimo de seguidores para respuestas y likes automáticos (filtra bots y spam)"
|
||
|
||
[i18n.es.settings.growth_mode]
|
||
label = "Modo de crecimiento"
|
||
description = "Optimizar la estrategia para crecer desde cero — prioriza respuestas en cuentas grandes y participación comunitaria"
|
||
|
||
# ─── Japanese (日本語) ────────────────────────────────────────────────────
|
||
|
||
[i18n.ja]
|
||
name = "Twitter Hand"
|
||
description = "自律型 Twitter/X マネージャー——コンテンツ作成、予約投稿、エンゲージメントと実績追跡"
|
||
category = "コミュニケーション"
|
||
tags = ["popular"]
|
||
|
||
[i18n.ja.settings.twitter_bearer_token]
|
||
label = "Twitter Bearerトークン"
|
||
description = "Twitter/X開発者ポータルのBearerトークン。すべてのTwitter API操作に必要です。"
|
||
|
||
[i18n.ja.settings.twitter_style]
|
||
label = "コンテンツスタイル"
|
||
description = "ツイートの語調とスタイル"
|
||
|
||
[i18n.ja.settings.post_frequency]
|
||
label = "投稿頻度"
|
||
description = "コンテンツの作成・投稿の頻度"
|
||
|
||
[i18n.ja.settings.auto_reply]
|
||
label = "自動返信"
|
||
description = "メンションや関連する会話に自動で返信する"
|
||
|
||
[i18n.ja.settings.auto_like]
|
||
label = "自動いいね"
|
||
description = "ネットワーク内のツイートや関連コンテンツに自動でいいねする"
|
||
|
||
[i18n.ja.settings.content_topics]
|
||
label = "コンテンツトピック"
|
||
description = "作成するコンテンツのトピック(カンマ区切り、例: AI、スタートアップ、生産性)"
|
||
|
||
[i18n.ja.settings.brand_voice]
|
||
label = "ブランドボイス"
|
||
description = "あなた独自の語り口を記述(例:「複雑なテクノロジーをわかりやすく伝える皮肉屋の起業家」)"
|
||
|
||
[i18n.ja.settings.thread_mode]
|
||
label = "スレッドモード"
|
||
description = "コンテンツミックスにツイートスレッド(複数ツイートで構成するストーリー)を含める"
|
||
|
||
[i18n.ja.settings.content_queue_size]
|
||
label = "コンテンツキューサイズ"
|
||
description = "準備キューに保持するツイートの数"
|
||
|
||
[i18n.ja.settings.engagement_hours]
|
||
label = "エンゲージメント時間帯"
|
||
description = "メンションの確認とエンゲージメントを行う時間帯"
|
||
|
||
[i18n.ja.settings.approval_mode]
|
||
label = "承認モード"
|
||
description = "ツイートを直接投稿せず、レビュー用のキューファイルに書き出す"
|
||
|
||
[i18n.ja.settings.hashtag_strategy]
|
||
label = "ハッシュタグ戦略"
|
||
description = "ツイートでのハッシュタグの使用頻度"
|
||
|
||
[i18n.ja.settings.engagement_threshold]
|
||
label = "エンゲージメント閾値"
|
||
description = "自動返信・自動いいねの対象となる最低フォロワー数(ボットやスパムをフィルタリング)"
|
||
|
||
[i18n.ja.settings.growth_mode]
|
||
label = "成長モード"
|
||
description = "ゼロからの成長に最適化——大きなアカウントへのリプライとコミュニティ参加を優先し、オリジナル投稿は控えめに"
|
||
|
||
# ─── French (Français) ────────────────────────────────────────────────────
|
||
|
||
[i18n.fr]
|
||
name = "Hand Twitter"
|
||
description = "Gestionnaire Twitter/X autonome — création de contenu, publication programmée, interactions et suivi des performances"
|
||
category = "Communication"
|
||
tags = ["popular"]
|
||
|
||
[i18n.fr.settings.twitter_bearer_token]
|
||
label = "Jeton Bearer Twitter"
|
||
description = "Jeton Bearer du Portail Développeurs Twitter/X. Requis pour toutes les opérations de l'API Twitter."
|
||
|
||
[i18n.fr.settings.twitter_style]
|
||
label = "Style de contenu"
|
||
description = "Ton et style pour vos tweets"
|
||
|
||
[i18n.fr.settings.post_frequency]
|
||
label = "Fréquence de publication"
|
||
description = "Fréquence de création et de publication de contenu"
|
||
|
||
[i18n.fr.settings.auto_reply]
|
||
label = "Réponse automatique"
|
||
description = "Répondre automatiquement aux mentions et conversations pertinentes"
|
||
|
||
[i18n.fr.settings.auto_like]
|
||
label = "Like automatique"
|
||
description = "Aimer automatiquement les tweets de votre réseau et le contenu pertinent"
|
||
|
||
[i18n.fr.settings.content_topics]
|
||
label = "Sujets de contenu"
|
||
description = "Sujets sur lesquels créer du contenu (séparés par des virgules, ex. IA, startups, productivité)"
|
||
|
||
[i18n.fr.settings.brand_voice]
|
||
label = "Voix de marque"
|
||
description = "Décrivez votre voix unique (ex. 'fondateur sarcastique qui simplifie la technologie complexe')"
|
||
|
||
[i18n.fr.settings.thread_mode]
|
||
label = "Mode fil de discussion"
|
||
description = "Inclure des fils de tweets (histoires à plusieurs tweets) dans le mix de contenu"
|
||
|
||
[i18n.fr.settings.content_queue_size]
|
||
label = "Taille de la file de contenu"
|
||
description = "Nombre de tweets à maintenir dans la file d'attente préparée"
|
||
|
||
[i18n.fr.settings.engagement_hours]
|
||
label = "Heures d'engagement"
|
||
description = "Quand vérifier les mentions et interagir"
|
||
|
||
[i18n.fr.settings.approval_mode]
|
||
label = "Mode d'approbation"
|
||
description = "Écrire les tweets dans un fichier d'attente pour révision au lieu de les publier directement"
|
||
|
||
[i18n.fr.settings.hashtag_strategy]
|
||
label = "Stratégie de hashtags"
|
||
description = "Niveau d'utilisation des hashtags dans les tweets"
|
||
|
||
[i18n.fr.settings.engagement_threshold]
|
||
label = "Seuil d'engagement"
|
||
description = "Nombre minimum d'abonnés pour les réponses et likes automatiques (filtre les bots et le spam)"
|
||
|
||
[i18n.fr.settings.growth_mode]
|
||
label = "Mode de croissance"
|
||
description = "Optimiser la stratégie pour une croissance depuis zéro — privilégie les réponses aux grands comptes et la participation communautaire"
|
||
|
||
# ─── German (Deutsch) ────────────────────────────────────────────────────
|
||
|
||
[i18n.de]
|
||
name = "Twitter-Hand"
|
||
description = "Autonomer Twitter/X-Manager — Inhaltserstellung, geplantes Posten, Engagement- und Performance-Tracking"
|
||
category = "Kommunikation"
|
||
tags = ["popular"]
|
||
|
||
[i18n.de.settings.twitter_bearer_token]
|
||
label = "Twitter Bearer-Token"
|
||
description = "Bearer-Token vom Twitter/X-Entwicklerportal. Erforderlich für alle Twitter-API-Operationen."
|
||
|
||
[i18n.de.settings.twitter_style]
|
||
label = "Inhaltsstil"
|
||
description = "Ton und Stil für Ihre Tweets"
|
||
|
||
[i18n.de.settings.post_frequency]
|
||
label = "Veröffentlichungshäufigkeit"
|
||
description = "Wie oft Inhalte erstellt und veröffentlicht werden"
|
||
|
||
[i18n.de.settings.auto_reply]
|
||
label = "Automatische Antwort"
|
||
description = "Automatisch auf Erwähnungen und relevante Gespräche antworten"
|
||
|
||
[i18n.de.settings.auto_like]
|
||
label = "Automatisches Like"
|
||
description = "Tweets im Netzwerk und relevante Inhalte automatisch liken"
|
||
|
||
[i18n.de.settings.content_topics]
|
||
label = "Inhaltsthemen"
|
||
description = "Themen für die Content-Erstellung (kommagetrennt, z.B. KI, Startups, Produktivität)"
|
||
|
||
[i18n.de.settings.brand_voice]
|
||
label = "Markenstimme"
|
||
description = "Beschreiben Sie Ihre einzigartige Stimme (z.B. 'sarkastischer Gründer, der komplexe Technologie vereinfacht')"
|
||
|
||
[i18n.de.settings.thread_mode]
|
||
label = "Thread-Modus"
|
||
description = "Tweet-Threads (mehrteilige Tweet-Geschichten) in den Content-Mix aufnehmen"
|
||
|
||
[i18n.de.settings.content_queue_size]
|
||
label = "Größe der Content-Warteschlange"
|
||
description = "Anzahl der Tweets in der vorbereiteten Warteschlange"
|
||
|
||
[i18n.de.settings.engagement_hours]
|
||
label = "Engagement-Zeiten"
|
||
description = "Wann Erwähnungen geprüft und interagiert werden soll"
|
||
|
||
[i18n.de.settings.approval_mode]
|
||
label = "Genehmigungsmodus"
|
||
description = "Tweets in eine Warteschlangendatei zur Überprüfung schreiben, anstatt sie direkt zu veröffentlichen"
|
||
|
||
[i18n.de.settings.hashtag_strategy]
|
||
label = "Hashtag-Strategie"
|
||
description = "Intensität der Hashtag-Nutzung in Tweets"
|
||
|
||
[i18n.de.settings.engagement_threshold]
|
||
label = "Engagement-Schwelle"
|
||
description = "Mindestanzahl an Followern für automatische Antworten und Likes (filtert Bots und Spam)"
|
||
|
||
[i18n.de.settings.growth_mode]
|
||
label = "Wachstumsmodus"
|
||
description = "Strategie für Wachstum von null optimieren — priorisiert Antworten bei größeren Accounts und Community-Beteiligung"
|
||
|
||
# ─── Korean (한국어) ────────────────────────────────────────────────────
|
||
|
||
[i18n.ko]
|
||
name = "Twitter Hand"
|
||
description = "자율 Twitter/X 관리자 — 콘텐츠 제작, 예약 게시, 참여 및 성과 추적"
|
||
category = "커뮤니케이션"
|
||
tags = ["popular"]
|
||
|
||
[i18n.ko.settings.twitter_bearer_token]
|
||
label = "Twitter Bearer 토큰"
|
||
description = "Twitter/X 개발자 포털의 Bearer 토큰. 모든 Twitter API 작업에 필수."
|
||
|
||
[i18n.ko.settings.twitter_style]
|
||
label = "콘텐츠 스타일"
|
||
description = "트윗의 어조와 스타일"
|
||
|
||
[i18n.ko.settings.post_frequency]
|
||
label = "게시 빈도"
|
||
description = "콘텐츠를 작성하고 게시하는 주기"
|
||
|
||
[i18n.ko.settings.auto_reply]
|
||
label = "자동 답글"
|
||
description = "멘션 및 관련 대화에 자동으로 답글 작성"
|
||
|
||
[i18n.ko.settings.auto_like]
|
||
label = "자동 좋아요"
|
||
description = "네트워크 내 트윗 및 관련 콘텐츠에 자동으로 좋아요"
|
||
|
||
[i18n.ko.settings.content_topics]
|
||
label = "콘텐츠 주제"
|
||
description = "콘텐츠를 작성할 주제 (쉼표로 구분, 예: AI, 스타트업, 생산성)"
|
||
|
||
[i18n.ko.settings.brand_voice]
|
||
label = "브랜드 보이스"
|
||
description = "고유한 스타일을 설명 (예: '복잡한 기술을 쉽게 풀어내는 유머러스한 창업자')"
|
||
|
||
[i18n.ko.settings.thread_mode]
|
||
label = "스레드 모드"
|
||
description = "콘텐츠 구성에 트윗 스레드 (다중 트윗 스토리) 포함"
|
||
|
||
[i18n.ko.settings.content_queue_size]
|
||
label = "콘텐츠 대기열 크기"
|
||
description = "준비 대기열에 유지할 트윗 수"
|
||
|
||
[i18n.ko.settings.engagement_hours]
|
||
label = "소통 시간대"
|
||
description = "멘션 확인 및 소통 활동을 수행하는 시간대"
|
||
|
||
[i18n.ko.settings.approval_mode]
|
||
label = "승인 모드"
|
||
description = "트윗을 직접 게시하지 않고 대기열 파일에 기록하여 검토"
|
||
|
||
[i18n.ko.settings.hashtag_strategy]
|
||
label = "해시태그 전략"
|
||
description = "트윗에서 해시태그를 사용하는 정도"
|
||
|
||
[i18n.ko.settings.engagement_threshold]
|
||
label = "소통 기준"
|
||
description = "자동 답글 및 좋아요 대상의 최소 팔로워 수 (봇과 스팸 필터링)"
|
||
|
||
[i18n.ko.settings.growth_mode]
|
||
label = "성장 모드"
|
||
description = "제로에서 시작하는 성장 전략 최적화 — 대형 계정에 답글과 커뮤니티 참여를 우선시"
|