Examples
This document provides practical examples of using the @elizaos/plugin-twitter package in various scenarios.
Twitter Plugin Examples
This document provides practical examples of using the @elizaos/plugin-twitter package in various scenarios.
Basic Bot Setup
Simple Posting Bot
Create a basic Twitter bot that posts autonomously:
import { AgentRuntime } from '@elizaos/core';
import { twitterPlugin } from '@elizaos/plugin-twitter';
import { bootstrapPlugin } from '@elizaos/plugin-bootstrap';
const character = {
name: "SimpleTwitterBot",
description: "A simple Twitter bot that posts updates",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
postExamples: [
"Just thinking about the future of technology...",
"Building something new today! 🚀",
"The best code is no code, but sometimes you need to write some.",
"Learning something new every day keeps the mind sharp."
],
settings: {
TWITTER_API_KEY: process.env.TWITTER_API_KEY,
TWITTER_API_SECRET_KEY: process.env.TWITTER_API_SECRET_KEY,
TWITTER_ACCESS_TOKEN: process.env.TWITTER_ACCESS_TOKEN,
TWITTER_ACCESS_TOKEN_SECRET: process.env.TWITTER_ACCESS_TOKEN_SECRET,
TWITTER_POST_ENABLE: "true",
TWITTER_POST_IMMEDIATELY: "true",
TWITTER_POST_INTERVAL_MIN: "120",
TWITTER_POST_INTERVAL_MAX: "240"
}
};
// Create and start the runtime
const runtime = new AgentRuntime({ character });
await runtime.start();
console.log('Twitter bot is running and will post every 2-4 hours!');
Content Creator Bot
Bot focused on creating engaging content:
const contentCreatorBot = {
name: "ContentCreator",
description: "Creates engaging Twitter content",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
postExamples: [
"🧵 Thread: Let's talk about why decentralization matters...",
"Hot take: The future of AI isn't about replacing humans, it's about augmentation",
"Day 30 of building in public: Today I learned...",
"Unpopular opinion: Simplicity > Complexity in system design",
"What's your biggest challenge in tech right now? Let's discuss 👇"
],
topics: [
"artificial intelligence",
"web3 and blockchain",
"software engineering",
"startups and entrepreneurship",
"future of technology"
],
style: {
tone: "thought-provoking but approachable",
format: "mix of threads, questions, and insights",
emoji: "use sparingly for emphasis"
},
settings: {
TWITTER_POST_ENABLE: "true",
TWITTER_POST_INTERVAL_MIN: "90",
TWITTER_POST_INTERVAL_MAX: "180",
TWITTER_POST_INTERVAL_VARIANCE: "0.3",
TWITTER_MAX_TWEET_LENGTH: "280" // Keep it concise
}
};
Thread Poster
Bot that creates detailed threads:
const threadPosterBot = {
name: "ThreadMaster",
description: "Creates informative Twitter threads",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
postExamples: [
"🧵 A thread on system design principles:\n\n1/ Start with the problem, not the solution",
"🧵 How to build a successful side project:\n\n1/ Pick something you'll use yourself",
"🧵 Lessons learned from 10 years in tech:\n\n1/ Technology changes, principles remain"
],
settings: {
TWITTER_POST_ENABLE: "true",
TWITTER_MAX_TWEET_LENGTH: "4000", // Support for longer threads
// Custom action for thread creation
customActions: ["CREATE_THREAD"]
}
};
// Custom thread creation action
const createThreadAction: Action = {
name: "CREATE_THREAD",
description: "Creates a Twitter thread",
handler: async (runtime, message, state, options, callback) => {
const topic = options.topic || "technology trends";
// Generate thread content
const threadContent = await runtime.generateText({
messages: [{
role: "system",
content: `Create a Twitter thread about ${topic}. Format as numbered tweets (1/, 2/, etc). Make it informative and engaging.`
}],
maxTokens: 1000
});
// Split into individual tweets
const tweets = threadContent.text.split(/\d+\//).filter(t => t.trim());
// Post as thread
let previousTweetId = null;
for (const tweet of tweets) {
const response = await runtime.getService('twitter').client.tweet(
tweet.trim(),
previousTweetId ? { reply: { in_reply_to_tweet_id: previousTweetId } } : {}
);
previousTweetId = response.id;
}
await callback({
text: `Thread posted! First tweet: ${tweets[0].substring(0, 50)}...`
});
return true;
}
};
Interaction Bots
Reply Bot
Bot that responds to mentions and replies:
const replyBot = {
name: "ReplyBot",
description: "Responds to mentions and conversations",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
settings: {
TWITTER_POST_ENABLE: "false", // Don't post autonomously
TWITTER_SEARCH_ENABLE: "true",
TWITTER_AUTO_RESPOND_MENTIONS: "true",
TWITTER_AUTO_RESPOND_REPLIES: "true",
TWITTER_POLL_INTERVAL: "60", // Check every minute
TWITTER_INTERACTION_INTERVAL_MIN: "5",
TWITTER_INTERACTION_INTERVAL_MAX: "15"
},
responseExamples: [
{
input: "What do you think about AI?",
output: "AI is a tool that amplifies human capability. The key is ensuring it serves humanity's best interests."
},
{
input: "Can you help me with coding?",
output: "I'd be happy to help! What specific coding challenge are you working on?"
}
]
};
Mention Handler
Bot that processes specific mentions:
const mentionHandler = {
name: "MentionBot",
description: "Handles mentions with specific commands",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
settings: {
TWITTER_SEARCH_ENABLE: "true",
TWITTER_AUTO_RESPOND_MENTIONS: "true"
}
};
// Custom mention handler
const handleMentionAction: Action = {
name: "HANDLE_MENTION",
description: "Process mention commands",
handler: async (runtime, message, state, options, callback) => {
const text = message.content.text.toLowerCase();
const twitterService = runtime.getService('twitter');
// Command: @bot summarize [url]
if (text.includes('summarize')) {
const urlMatch = text.match(/https?:\/\/[^\s]+/);
if (urlMatch) {
const summary = await summarizeUrl(urlMatch[0]);
await callback({
text: `Summary: ${summary}`,
replyTo: message.id
});
}
}
// Command: @bot remind me [message] in [time]
else if (text.includes('remind me')) {
const reminderMatch = text.match(/remind me (.+) in (\d+) (minutes?|hours?)/);
if (reminderMatch) {
const [, message, amount, unit] = reminderMatch;
const delay = unit.startsWith('hour') ? amount * 60 * 60 * 1000 : amount * 60 * 1000;
setTimeout(async () => {
await twitterService.client.tweet(
`@${message.username} Reminder: ${message}`,
{ reply: { in_reply_to_tweet_id: message.id } }
);
}, delay);
await callback({
text: `I'll remind you in ${amount} ${unit}! ⏰`,
replyTo: message.id
});
}
}
return true;
}
};
Quote Tweet Bot
Bot that quotes interesting tweets:
const quoteTweetBot = {
name: "QuoteTweeter",
description: "Quotes and comments on interesting tweets",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
settings: {
TWITTER_SEARCH_ENABLE: "true",
TWITTER_TIMELINE_ALGORITHM: "weighted",
TWITTER_TIMELINE_RELEVANCE_WEIGHT: "7", // Prioritize relevant content
TWITTER_TARGET_USERS: "sama,pmarca,naval,elonmusk" // Quote these users
}
};
// Quote tweet evaluation
const quoteEvaluator = {
shouldQuote: (tweet: Tweet): boolean => {
// Check if tweet is quotable
if (tweet.text.length < 50) return false; // Too short
if (tweet.public_metrics.retweet_count < 10) return false; // Not popular enough
if (hasAlreadyQuoted(tweet.id)) return false;
// Check content relevance
const relevantKeywords = ['AI', 'future', 'technology', 'innovation'];
return relevantKeywords.some(keyword =>
tweet.text.toLowerCase().includes(keyword.toLowerCase())
);
},
generateQuoteComment: async (tweet: Tweet, runtime: IAgentRuntime): Promise<string> => {
const response = await runtime.generateText({
messages: [{
role: "system",
content: "Add insightful commentary to this tweet. Be thoughtful and add value."
}, {
role: "user",
content: tweet.text
}],
maxTokens: 100
});
return response.text;
}
};
Search & Monitor Bots
Keyword Monitor
Bot that monitors specific keywords:
const keywordMonitor = {
name: "KeywordTracker",
description: "Monitors and responds to keyword mentions",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
keywords: ["#AIagents", "#ElizaOS", "autonomous agents", "AI automation"],
settings: {
TWITTER_SEARCH_ENABLE: "true",
TWITTER_POST_ENABLE: "false"
}
};
// Custom search action
const searchKeywordsAction: Action = {
name: "SEARCH_KEYWORDS",
description: "Search for specific keywords",
handler: async (runtime, message, state, options, callback) => {
const twitterService = runtime.getService('twitter');
const keywords = runtime.character.keywords;
for (const keyword of keywords) {
const results = await twitterService.client.search(keyword, {
max_results: 10,
'tweet.fields': ['created_at', 'public_metrics', 'author_id']
});
for (const tweet of results.data || []) {
// Process relevant tweets
if (shouldEngageWith(tweet)) {
await engageWithTweet(tweet, runtime);
}
}
}
return true;
}
};
Hashtag Tracker
Bot that tracks trending hashtags:
const hashtagTracker = {
name: "HashtagBot",
description: "Tracks and engages with trending hashtags",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
trackedHashtags: ["#Web3", "#AI", "#BuildInPublic", "#100DaysOfCode"],
settings: {
TWITTER_SEARCH_ENABLE: "true",
TWITTER_INTERACTION_INTERVAL_MIN: "30", // Don't spam
TWITTER_MAX_INTERACTIONS_PER_RUN: "5" // Limit interactions
}
};
User Monitor
Bot that monitors specific users:
const userMonitor = {
name: "UserTracker",
description: "Monitors and interacts with specific users",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
settings: {
TWITTER_TARGET_USERS: "vitalikbuterin,balajis,cdixon",
TWITTER_TIMELINE_ALGORITHM: "weighted",
TWITTER_TIMELINE_USER_BASED_WEIGHT: "10", // Heavily prioritize target users
TWITTER_AUTO_RESPOND_MENTIONS: "false", // Only interact with targets
TWITTER_AUTO_RESPOND_REPLIES: "false"
}
};
Advanced Bots
Full Engagement Bot
Bot with all features enabled:
const fullEngagementBot = {
name: "FullEngagement",
description: "Complete Twitter engagement bot",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
postExamples: [
"What's the most underrated technology right now?",
"Building in public update: Just crossed 1000 users!",
"The best developers I know are constantly learning"
],
settings: {
// Posting
TWITTER_POST_ENABLE: "true",
TWITTER_POST_INTERVAL_MIN: "180",
TWITTER_POST_INTERVAL_MAX: "360",
// Interactions
TWITTER_SEARCH_ENABLE: "true",
TWITTER_AUTO_RESPOND_MENTIONS: "true",
TWITTER_AUTO_RESPOND_REPLIES: "true",
// Timeline processing
TWITTER_ENABLE_ACTION_PROCESSING: "true",
TWITTER_ACTION_INTERVAL: "240",
// Algorithm configuration
TWITTER_TIMELINE_ALGORITHM: "weighted",
TWITTER_TIMELINE_USER_BASED_WEIGHT: "4",
TWITTER_TIMELINE_TIME_BASED_WEIGHT: "3",
TWITTER_TIMELINE_RELEVANCE_WEIGHT: "6"
}
};
Multi-Account Bot
Managing multiple Twitter accounts:
const multiAccountSetup = async (runtime: IAgentRuntime) => {
const twitterService = runtime.getService('twitter') as TwitterService;
// Main account
const mainAccount = await twitterService.createClient(
runtime,
'main-account',
{
TWITTER_API_KEY: process.env.MAIN_API_KEY,
TWITTER_API_SECRET_KEY: process.env.MAIN_API_SECRET,
TWITTER_ACCESS_TOKEN: process.env.MAIN_ACCESS_TOKEN,
TWITTER_ACCESS_TOKEN_SECRET: process.env.MAIN_ACCESS_SECRET,
TWITTER_POST_ENABLE: "true"
}
);
// Support account
const supportAccount = await twitterService.createClient(
runtime,
'support-account',
{
TWITTER_API_KEY: process.env.SUPPORT_API_KEY,
TWITTER_API_SECRET_KEY: process.env.SUPPORT_API_SECRET,
TWITTER_ACCESS_TOKEN: process.env.SUPPORT_ACCESS_TOKEN,
TWITTER_ACCESS_TOKEN_SECRET: process.env.SUPPORT_ACCESS_SECRET,
TWITTER_POST_ENABLE: "false",
TWITTER_SEARCH_ENABLE: "true"
}
);
// News account
const newsAccount = await twitterService.createClient(
runtime,
'news-account',
{
TWITTER_API_KEY: process.env.NEWS_API_KEY,
TWITTER_API_SECRET_KEY: process.env.NEWS_API_SECRET,
TWITTER_ACCESS_TOKEN: process.env.NEWS_ACCESS_TOKEN,
TWITTER_ACCESS_TOKEN_SECRET: process.env.NEWS_ACCESS_SECRET,
TWITTER_POST_ENABLE: "true",
TWITTER_POST_INTERVAL_MIN: "60" // More frequent posts
}
);
console.log('Multi-account setup complete!');
};
Analytics Bot
Bot that tracks and reports analytics:
const analyticsBot = {
name: "AnalyticsBot",
description: "Tracks Twitter performance metrics",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
settings: {
TWITTER_POST_ENABLE: "true",
TWITTER_SEARCH_ENABLE: "false" // Focus on analytics
}
};
// Analytics action
const analyticsAction: Action = {
name: "TWITTER_ANALYTICS",
description: "Generate Twitter analytics report",
handler: async (runtime, message, state, options, callback) => {
const twitterService = runtime.getService('twitter');
const client = twitterService.getClient(runtime.agentId);
// Get recent tweets
const tweets = await client.client.getUserTweets(client.profile.id, {
max_results: 100,
'tweet.fields': ['created_at', 'public_metrics']
});
// Calculate metrics
const metrics = {
totalTweets: tweets.data.length,
totalLikes: 0,
totalRetweets: 0,
totalReplies: 0,
avgEngagement: 0
};
tweets.data.forEach(tweet => {
metrics.totalLikes += tweet.public_metrics.like_count;
metrics.totalRetweets += tweet.public_metrics.retweet_count;
metrics.totalReplies += tweet.public_metrics.reply_count;
});
metrics.avgEngagement =
(metrics.totalLikes + metrics.totalRetweets + metrics.totalReplies) /
metrics.totalTweets;
// Generate report
const report = `
📊 Twitter Analytics Report
📝 Total Tweets: ${metrics.totalTweets}
❤️ Total Likes: ${metrics.totalLikes}
🔄 Total Retweets: ${metrics.totalRetweets}
💬 Total Replies: ${metrics.totalReplies}
📈 Avg Engagement: ${metrics.avgEngagement.toFixed(2)}
Top performing tweets coming in next thread...
`;
await callback({ text: report });
return true;
}
};
Testing Examples
Dry Run Bot
Test without actually posting:
const testBot = {
name: "TestBot",
description: "Bot for testing configurations",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
postExamples: [
"This is a test tweet that won't actually post",
"Testing the Twitter integration..."
],
settings: {
TWITTER_DRY_RUN: "true", // Simulate all actions
TWITTER_POST_ENABLE: "true",
TWITTER_POST_IMMEDIATELY: "true",
TWITTER_SEARCH_ENABLE: "true"
}
};
// Monitor dry run output
runtime.on('twitter:dryRun', (action) => {
console.log(`[DRY RUN] Would ${action.type}:`, action.content);
});
Debug Bot
Bot with extensive logging:
const debugBot = {
name: "DebugBot",
description: "Bot with debug logging enabled",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
settings: {
DEBUG: "eliza:twitter:*", // Enable all Twitter debug logs
TWITTER_POST_ENABLE: "true",
TWITTER_RETRY_LIMIT: "1", // Fail fast for debugging
TWITTER_POST_INTERVAL_MIN: "1" // Quick testing
}
};
Error Handling Examples
Resilient Bot
Bot with comprehensive error handling:
const resilientBot = {
name: "ResilientBot",
description: "Bot with robust error handling",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
settings: {
TWITTER_RETRY_LIMIT: "5",
TWITTER_POST_ENABLE: "true"
}
};
// Error handling wrapper
const safeTwitterAction = (action: Action): Action => ({
...action,
handler: async (runtime, message, state, options, callback) => {
try {
return await action.handler(runtime, message, state, options, callback);
} catch (error) {
runtime.logger.error(`Twitter action failed: ${action.name}`, error);
// Handle specific errors
if (error.code === 403) {
await callback({
text: "I don't have permission to do that. Please check my Twitter app permissions."
});
} else if (error.code === 429) {
await callback({
text: "I'm being rate limited. I'll try again later."
});
} else {
await callback({
text: "Something went wrong with Twitter. I'll try again soon."
});
}
return false;
}
}
});
Integration Examples
With Other Platforms
import { discordPlugin } from '@elizaos/plugin-discord';
import { telegramPlugin } from '@elizaos/plugin-telegram';
const crossPlatformBot = {
name: "CrossPlatform",
description: "Bot that posts across platforms",
plugins: [bootstrapPlugin, twitterPlugin, discordPlugin, telegramPlugin],
clients: ["twitter", "discord", "telegram"],
postExamples: [
"New blog post: Understanding distributed systems",
"What's your favorite programming language and why?"
],
settings: {
// Twitter settings
TWITTER_POST_ENABLE: "true",
TWITTER_POST_INTERVAL_MIN: "180",
// Discord settings
DISCORD_API_TOKEN: process.env.DISCORD_TOKEN,
// Telegram settings
TELEGRAM_BOT_TOKEN: process.env.TELEGRAM_TOKEN
}
};
// Cross-platform posting action
const crossPostAction: Action = {
name: "CROSS_POST",
description: "Post to all platforms",
handler: async (runtime, message, state, options, callback) => {
const content = options.content || "Hello from all platforms!";
// Post to Twitter
const twitterService = runtime.getService('twitter');
await twitterService.client.tweet(content);
// Post to Discord
const discordService = runtime.getService('discord');
await discordService.sendMessage(CHANNEL_ID, content);
// Post to Telegram
const telegramService = runtime.getService('telegram');
await telegramService.sendMessage(CHAT_ID, content);
await callback({
text: "Posted to all platforms successfully!"
});
return true;
}
};
Best Practices Example
Production Bot
Complete production-ready configuration:
import { twitterPlugin } from '@elizaos/plugin-twitter';
import { bootstrapPlugin } from '@elizaos/plugin-bootstrap';
import { AgentRuntime } from '@elizaos/core';
const productionBot = {
name: "ProductionTwitterBot",
description: "Production-ready Twitter bot",
plugins: [bootstrapPlugin, twitterPlugin],
clients: ["twitter"],
// Diverse post examples
postExamples: [
// Questions to drive engagement
"What's the biggest challenge you're facing in your project right now?",
"If you could automate one thing in your workflow, what would it be?",
// Insights and observations
"The best code is the code you don't have to write",
"Sometimes the simplest solution is the hardest to find",
// Personal updates
"Working on something exciting today. Can't wait to share more soon!",
"Learning from yesterday's debugging session: always check the obvious first",
// Threads
"Thread: 5 lessons from building production systems 🧵\n\n1/",
// Reactions to trends
"Interesting to see how AI is changing the way we think about software development"
],
settings: {
// Credentials from environment
TWITTER_API_KEY: process.env.TWITTER_API_KEY,
TWITTER_API_SECRET_KEY: process.env.TWITTER_API_SECRET_KEY,
TWITTER_ACCESS_TOKEN: process.env.TWITTER_ACCESS_TOKEN,
TWITTER_ACCESS_TOKEN_SECRET: process.env.TWITTER_ACCESS_TOKEN_SECRET,
// Conservative posting schedule
TWITTER_POST_ENABLE: "true",
TWITTER_POST_INTERVAL_MIN: "240", // 4 hours
TWITTER_POST_INTERVAL_MAX: "480", // 8 hours
TWITTER_POST_INTERVAL_VARIANCE: "0.2",
// Moderate interaction settings
TWITTER_SEARCH_ENABLE: "true",
TWITTER_INTERACTION_INTERVAL_MIN: "30",
TWITTER_INTERACTION_INTERVAL_MAX: "60",
TWITTER_MAX_INTERACTIONS_PER_RUN: "5",
// Quality over quantity
TWITTER_TIMELINE_ALGORITHM: "weighted",
TWITTER_TIMELINE_RELEVANCE_WEIGHT: "7",
// Safety settings
TWITTER_RETRY_LIMIT: "3",
TWITTER_DRY_RUN: process.env.NODE_ENV === 'development' ? "true" : "false"
}
};
// Initialize with monitoring
const runtime = new AgentRuntime({ character: productionBot });
// Add monitoring
runtime.on('error', (error) => {
console.error('Runtime error:', error);
// Send to monitoring service
});
runtime.on('twitter:post', (tweet) => {
console.log('Posted tweet:', tweet.id);
// Track metrics
});
runtime.on('twitter:rateLimit', (info) => {
console.warn('Rate limit warning:', info);
// Alert if critical
});
// Graceful shutdown
process.on('SIGTERM', async () => {
console.log('Shutting down gracefully...');
await runtime.stop();
process.exit(0);
});
// Start the bot
await runtime.start();
console.log('Production bot is running!');
Was this page helpful?
- Twitter Plugin Examples
- Basic Bot Setup
- Simple Posting Bot
- Content Creator Bot
- Thread Poster
- Interaction Bots
- Reply Bot
- Mention Handler
- Quote Tweet Bot
- Search & Monitor Bots
- Keyword Monitor
- Hashtag Tracker
- User Monitor
- Advanced Bots
- Full Engagement Bot
- Multi-Account Bot
- Analytics Bot
- Testing Examples
- Dry Run Bot
- Debug Bot
- Error Handling Examples
- Resilient Bot
- Integration Examples
- With Other Platforms
- Best Practices Example
- Production Bot