bankr-twitter-agent/SKILL.md
Build and run a Twitter/X agent with a distinct personality and automated workflows
npx skillsauth add bankrbot/openclaw-skills twitter-agentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill provides a framework for creating, managing, and automating a Twitter/X agent with a persistent personality and voice.
Before anything else, the agent's X account MUST be marked as an automated account. X requires this disclosure for any account posting with API automation; skipping it is the fastest way to get the account suspended.
Exact path (do this once, while logged in as the agent account):
Direct link: https://x.com/settings/account/automation
This adds the "Automated by @…" label to the profile and replies. It is non-negotiable — do not run this skill against an account that has not been labeled.
Set these 4 variables in your Bankr settings (gear icon -> Env Vars). Generate them from the X Developer Portal with Read and Write permissions enabled:
X_API_KEY: Consumer Key (OAuth 1.0a)X_API_KEY_SECRET: Consumer SecretX_ACCESS_TOKEN: User Access TokenX_ACCESS_TOKEN_SECRET: User Access Token SecretBankr automations natively support routing their output to Telegram. When creating an automation, choose Telegram as the delivery destination — the automation's final message is delivered to your linked Telegram directly, no bot token or custom code required. Automations used as "approval-gated" drafters rely on this: the automation composes drafts, runs guardrail checks, and instead of posting flagged drafts, it ends its run by sending them to Telegram for you to approve manually.
No env vars are needed for this — just link your Telegram to your Bankr account and select Telegram as the output when setting up each automation.
Every agent requires two files in the Bankr file system to maintain a consistent voice and narrative:
twitter-personality.md: Defines the character, voice, and style rules.twitter-storyline.md: Tracks the ongoing narrative, recent events, and current state of the character.If no personality file exists, the agent should walk the user through creating one by asking:
After gathering answers, the agent composes the personality file and saves it as twitter-personality.md.
Before composing or posting any tweet, the agent MUST:
twitter-personality.md using read_file.twitter-storyline.md using read_file to understand the current narrative context.twitter-storyline.md with the new tweet and any narrative developments using edit_file (NOT create_file -- see File Management below).These apply to every tweet the agent drafts, whether running manually or on a schedule. A draft that violates any of these routes to approval instead of posting.
The agent MUST NEVER reply to a post it was not invited into. An agent that cold-replies to strangers' timelines is the single fastest path to an X suspension. There are exactly three legal post types:
@handle token in text, not merely an in_reply_to_user_id match).in_reply_to_user_id is the agent's own user ID AND the parent tweet in the conversation tree is authored by the agent.Anything outside those three categories is FORBIDDEN and must be dropped from the draft set before the guardrail check even runs. Quote-tweets of random accounts, reply-chains the agent isn't tagged in, trending-topic replies, "drive-by" replies to big accounts the agent admires — all prohibited under autonomous operation. If the user manually drafts one of these in a session, it still requires explicit approval and is never posted automatically.
Mention-scan filter (enforce in the fetch step):
text contains the agent's @handle as a standalone token.in_reply_to_user_id === agentUserId AND the root of conversation_id is authored by the agent.@bankrbot. Bankr's X agent executes onchain actions (transfers, swaps, deploys) when tagged from a wallet-linked account. Any tweet -- top-level or reply -- that mentions @bankrbot MUST be drafted and surfaced to the user for approval. The agent does not tag @bankrbot without explicit approval for that specific draft, every time.0x[a-fA-F0-9]{40}), a Solana address, the word "send" combined with a ticker (e.g. "send 100 USDC"), a signed-message pattern, or anything that reads like a transaction instruction -- route to approval.## Approval-Gated Milestones section. Automations check drafts against this list and route matches to approval.## Approval-Gated Accounts. Replies to those accounts route to approval.Automations should never engage with:
Bankr automations can deliver their output directly to Telegram — no custom code needed. When a draft hits a guardrail, the automation should:
pending-approval entry to twitter-storyline.md under the ## Pending Approval Queue section so the next session sees what's waiting.When the user asks to check mentions and reply, follow this exact sequence:
Use execute_cli with [email protected] to fetch recent mentions. The scan script should:
userMentionTimelinetext, OR replies on the agent's own conversation tree. Drop everything else before ranking.Load twitter-storyline.md BEFORE drafting any replies. Check:
Filter and rank unreplied mentions using this hierarchy:
execute_cli (rate-limit ~1.5s between posts)twitter-storyline.md with all new entries using edit_fileWhen updating twitter-storyline.md, ALWAYS use edit_file with the existing file ID. Using create_file will spawn duplicate files. If duplicates are created, merge them by reading both, combining content into the newer/larger file, and deleting the old one.
The storyline file should maintain:
@bankrbot) whose interactions always require approvalBankr automations run an agent prompt on a cron schedule. Each recipe below is a self-contained automation -- when creating it in Bankr, paste the prompt, set the cron schedule, and select Telegram as the output destination so approval-gated drafts reach you directly.
The prompt in each recipe is the exact instruction the agent executes the moment the automation fires. Paste it into the automation's command field verbatim — do NOT prefix it with the automation name, do NOT wrap it in quotes, and do NOT add extra context like "run this:" or "here is the prompt:". The automation runs the command immediately when triggered; the text you paste IS the command, and it must read as an imperative that executes RIGHT NOW (not as a description of what the automation will eventually do).
Why this matters: Bankr automations feed the command text directly to the agent as the user's message for that run. If the text reads like a label or description ("Weekday Morning Post: …", "This automation will post…"), the agent treats it as context and may not execute. If it reads like a direct imperative ("Run the twitter-agent skill and post now…"), the agent executes immediately. Every recipe below is already written in the imperative — paste it verbatim and it will fire correctly.
Wrong (prefixed with automation name — reads as a label, not a command):
Weekday Morning Post: Run the twitter-agent skill for a weekday morning top-level post...
Wrong (framed as a future/conditional action — reads as a description):
When this runs, the agent should run the twitter-agent skill and post a morning tweet...
Right (direct imperative — executes RIGHT NOW when the automation fires):
Run the twitter-agent skill for a weekday morning top-level post...
Run the skill manually first. Post 5-10 times by hand, get comfortable with the voice, confirm the storyline is updating cleanly. Only then enable automations, ONE AT A TIME, starting with the lowest-frequency autonomous one. Watch it for 3-5 days before adding the next.
Recommended onboarding progression:
All Bankr crons run in UTC. Convert your local target time to UTC.
Cron (UTC): 15 13 * * 1-5 (9:15am ET weekdays during DST)
Output destination: Telegram (for post confirmations + any flagged drafts)
Prompt:
Run the twitter-agent skill for a weekday morning top-level post. Steps: (1) Load the twitter-agent skill with use_skill. (2) Read twitter-personality.md and twitter-storyline.md. (3) Fetch recent tweets from the account via the X API to confirm what was just posted and avoid immediate repetition. (4) Compose ONE top-level tweet, target length 80-180 characters, following all personality rules from twitter-personality.md. It should advance or reference an existing thread from the 'Storyline Threads to Continue' section. (5) Run the full Guardrail Check from the skill: no @bankrbot, no 0x addresses, no onchain-action language, no approval-gated milestones. If the best draft hits a guardrail, pick a different beat. If no safe beat fits, do NOT post — output the draft and the flag reason as the final message so it reaches Telegram for approval, and log it in the Pending Approval Queue. (6) Cross-reference the storyline to ensure no phrase/joke repeats. (7) Post via execute_cli. (8) Append an Entry to twitter-storyline.md with the tweet ID, content, narrative impact, and any new lore. (9) Update the Current State section if the character's time/mood changed. (10) Return a short final message summarizing what was posted (this is what gets delivered to Telegram).
Cron (UTC): 30 16 * * * (12:30pm ET daily during DST)
Output destination: Telegram (for approval of flagged drafts + sweep summary)
Prompt:
Run the twitter-agent skill for a mentions reply sweep. Steps: (1) Load the twitter-agent skill. (2) Read twitter-personality.md and twitter-storyline.md. (3) Fetch the last 50 mentions via the X API. (4) Apply the "Never Reply Unprompted" filter from the skill: keep only tweets where the agent's @handle appears as a standalone token in
text, OR replies whosein_reply_to_user_idmatches the agent's user ID AND whose conversation root is authored by the agent. Discard all other candidates before any ranking. (5) From the survivors, filter to UNREPLIED mentions by cross-referencing tweet IDs against the storyline's replied-to list. (6) Apply the Skip List: no FUD, no politics, no financial-advice requests, no spam/tag-farm threads, no shills of unrelated tokens. (7) Rank remaining mentions by setup quality and follower count. Select the top 2-4. (8) For each, draft a reply (target 60-200 chars) in the personality voice, cross-referencing the storyline for tone and callbacks. (9) Run Guardrail Check per draft. Any draft that mentions @bankrbot, contains an EVM/Solana address, reads like an onchain action, matches an approval-gated milestone, targets an approval-gated account, OR targets an account with >50k followers -- DO NOT POST. Instead, include the draft + flag reason + target tweet ID + author handle + follower count in the final output message so it reaches Telegram for approval, and log it in the Pending Approval Queue. (10) Post the safe drafts via execute_cli with 1.5s spacing. (11) Append an Entry to twitter-storyline.md logging every posted reply AND every draft routed to Telegram. (12) Return a final summary message listing what was posted and what was escalated (this is the Telegram delivery).
Cron (UTC): 0 23 * * * (7:00pm ET daily during DST)
Output destination: Telegram
Prompt: (identical to Recipe 2)
Cron (UTC): 0 15 * * 6,0 (11:00am ET Saturday + Sunday during DST)
Output destination: Telegram
Prompt:
Run the twitter-agent skill for a weekend top-level post. Steps: (1) Load the twitter-agent skill. (2) Read twitter-personality.md and twitter-storyline.md. (3) Compose ONE top-level tweet, target 80-220 characters, in the personality voice. Lean into weekend-specific atmosphere or whatever threads are marked as weekend-appropriate in the storyline. (4) Run full Guardrail Check (same as Recipe 1). If the best draft hits a guardrail, route to Telegram approval via the final output message and log in Pending Approval Queue. (5) Post via execute_cli. (6) Append an Entry to twitter-storyline.md. (7) Return a short final summary message for Telegram delivery.
Cron (UTC): 0 2 * * 1 (10:00pm ET Sunday during DST)
Output destination: Telegram (digest of audit findings)
Prompt:
Run a storyline audit for the twitter-agent skill. Steps: (1) Read twitter-storyline.md end-to-end. (2) Identify: threads not referenced in 10+ days that could be revived, threads overused (3+ references in a week), repeated phrases/jokes, contradictions in the lore, the current state of each pending approval-gated milestone, and any Pending Approval Queue entries that never got resolved. (3) Prepend a '### Weekly Audit [date]' entry to twitter-storyline.md with bullet-point notes. Do NOT post any tweets. Do NOT generate character content. (4) Return the audit notes as the final message so they're delivered to Telegram as a weekly digest.
@bankrbot -- always manual approval, every time (onchain risk).To use this skill, reference it in your prompt so the agent knows to load the personality and storyline files first. Examples:
All Twitter interactions use execute_cli with the [email protected] package.
const { TwitterApi } = require('twitter-api-v2');
const client = new TwitterApi({
appKey: process.env.X_API_KEY,
appSecret: process.env.X_API_KEY_SECRET,
accessToken: process.env.X_ACCESS_TOKEN,
accessSecret: process.env.X_ACCESS_TOKEN_SECRET,
});
// Post a tweet
const tweet = await client.v2.tweet('your personality-filtered text');
console.log('Tweet ID:', tweet.data.id);
// Reply to a tweet
await client.v2.reply('reply text', originalTweetId);
// Quote tweet
await client.v2.tweet('quote text', { quote_tweet_id: tweetId });
// Get user timeline
const timeline = await client.v2.userTimeline(userId);
const me = await client.v2.me();
const mentions = await client.v2.userMentionTimeline(me.data.id, {
max_results: 50,
expansions: ['author_id', 'in_reply_to_user_id', 'referenced_tweets.id'],
'tweet.fields': ['created_at', 'conversation_id', 'in_reply_to_user_id', 'referenced_tweets', 'text', 'public_metrics'],
'user.fields': ['username', 'name', 'public_metrics']
});
// REQUIRED: enforce the "Never Reply Unprompted" filter before drafting
const myHandle = me.data.username.toLowerCase();
const myId = me.data.id;
const tagRegex = new RegExp(`(^|[^a-zA-Z0-9_])@${myHandle}([^a-zA-Z0-9_]|$)`, 'i');
const eligible = (mentions.data.data || []).filter(t => {
const explicitlyTagged = tagRegex.test(t.text || '');
const isReplyOnOurTree = t.in_reply_to_user_id === myId; // also verify conversation root is ours via conversation_id lookup
return explicitlyTagged || isReplyOnOurTree;
});
["[email protected]"]true (critical -- this injects the X API keys)30000bun available (invoke scripts with bun script.js). node is NOT available.twitter-storyline.md files exist, merge them into one and delete the extras. Always use edit_file to prevent this.node: command not found: Sandbox uses bun. Use bun script.js instead of node script.js.twitter-storyline.md after posting so the next session has context.[email protected] for cached installs.edit_file for storyline updates. Never create_file for existing files.data-ai
Discover, bet on, track, and settle Hunch prediction markets in natural language. Trigger when a user wants to bet, take a position, or get odds on a crypto outcome — token market-cap milestones and flips, launchpad races (Bankr vs pump.fun volume / #1-days / launches over a cap), token head-to-head outperformance, mcap strike-ladders, and up/down price rounds. Also trigger on "what can I bet on about $TOKEN", "odds on …", "take YES/NO on …", "show my Hunch bets", "did my market resolve". Settles in USDC on Base via x402 (≤ $10 / bet); every bet returns an on-chain proof.
tools
HSM-backed secret management for AI agents. Store API keys (including Bankr `bk_` keys), passwords, and credentials in an encrypted vault; retrieve them at runtime via MCP without keeping secrets in chat context. Bankr Dynamic Key Vending issues short-lived scoped `bk_usr_` keys from a partner key (`bk_ptr_`) without manual rotation. Policy-based access control, secret rotation, sharing, EVM transaction intents (sign/simulate/broadcast), multi-chain signing keys, treasury multisig proposals, OIDC federation for external service auth, built-in prompt injection detection, and optional Shroud TEE LLM proxy. Use when the agent needs secure credential storage, just-in-time secret access, guarded on-chain signing, or security scanning — not for Bankr trading prompts, portfolio checks, or x402 calls (use the bankr skill instead).
development
Give your Bankr agent its own brain and a wallet-signed line to every other agent — on any framework, with no API key. SIGNA is the keyless agent layer on Base: resolve any identity to a messageable wallet, send and read wallet-signed DMs, invoke capabilities on the network, and run a brain that reasons on decentralized inference and acts through those capabilities. The Bankr wallet is the only credential. Triggers: "message that agent", "DM this wallet/handle", "reach the agent behind @x", "what is the base market", "resolve @handle to a wallet", "ask the network", "let my agent think and report".
development
AI-powered crypto trading agent, wallet API, and LLM gateway via natural language. Use when the user wants to trade crypto, check portfolio balances (with PnL and NFTs), view token prices, search tokens, transfer crypto, manage NFTs, use leverage (Hyperliquid or Avantis), bet on Polymarket, deploy tokens, set up automated trading, sign and submit raw transactions, call or deploy x402 paid API endpoints, browse the web, or access LLM models through the Bankr LLM gateway funded by your Bankr wallet. Supports Base, Ethereum, Polygon, Solana, Unichain, World Chain, Arbitrum, and BNB Chain.