Twitter Integration

Configuration
Configure your Twitter client using environment variables and the twitterConfigSchema:
// Environment variables
TWITTER_USERNAME="your-username"
TWITTER_PASSWORD="your-password"
TWITTER_EMAIL="your-email"
TWITTER_2FA_SECRET="optional-2fa-secret"
TWITTER_POST_INTERVAL_HOURS=4
TWITTER_POLLING_INTERVAL=5 # minutes
TWITTER_DRY_RUN=true # For testing
// Configuration schema
const twitterConfigSchema = z.object({
username: z.string().min(1, "Twitter username is required"),
password: z.string().min(1, "Twitter password is required"),
email: z.string().email("Valid email is required"),
twoFactorSecret: z.string().optional(),
retryLimit: z.number().int().min(1).default(5),
postIntervalHours: z.number().int().min(1).default(4),
enableActions: z.boolean().default(false)
});
Setting Up the Client
Initialize and start the Twitter client with your agent:
import { TwitterClient } from "@liz/twitter-client";
const config = {
username: process.env.TWITTER_USERNAME,
password: process.env.TWITTER_PASSWORD,
email: process.env.TWITTER_EMAIL,
twoFactorSecret: process.env.TWITTER_2FA_SECRET,
retryLimit: 3,
postIntervalHours: 4,
pollingInterval: 5,
dryRun: process.env.NODE_ENV !== "production",
};
const twitter = new TwitterClient(agent, config);
await twitter.start(); // Starts posting & monitoring intervals
Automated Posting
The client can automatically generate and post tweets at regular intervals:
// Automatic posting loop
async generateAndPost() {
const responseText = await this.fetchTweetContent({
agentId: this.agent.getAgentId(),
userId: "twitter_client",
roomId: "twitter",
text: "<SYSTEM> Generate a new tweet to post on your timeline </SYSTEM>",
type: "text"
});
const tweets = await sendThreadedTweet(this, responseText);
// Store tweets in memory
for (const tweet of tweets) {
await storeTweetIfNotExists({
id: tweet.id,
text: tweet.text,
userId: this.config.username,
username: this.config.username,
conversationId: tweet.conversationId,
permanentUrl: tweet.permanentUrl
});
}
}
Mention Monitoring
Monitor and respond to mentions automatically:
// Check for new mentions
async checkInteractions() {
const mentions = await this.getMentions();
for (const mention of mentions) {
if (mention.id <= this.lastCheckedTweetId) continue;
await this.handleMention(mention);
this.lastCheckedTweetId = mention.id;
}
}
// Handle mention with agent
async handleMention(tweet) {
const responseText = await this.fetchTweetContent({
agentId: this.agent.getAgentId(),
userId: `tw_user_${tweet.userId}`,
roomId: tweet.conversationId || "twitter",
text: `@${tweet.username}: ${tweet.text}`,
type: "text"
});
const replies = await sendThreadedTweet(this, responseText, tweet.id);
}
Thread Management
Handle tweet threads and conversations:
// Split long content into tweets
function splitTweetContent(text, maxLength = 280) {
if (text.length <= maxLength) return [text];
const tweets = [];
const sentences = text.match(/[^.!?]+[.!?]+/g) || [text];
let currentTweet = "";
for (const sentence of sentences) {
if ((currentTweet + sentence).length <= maxLength) {
currentTweet += sentence;
} else {
tweets.push(currentTweet.trim());
currentTweet = sentence;
}
}
if (currentTweet) tweets.push(currentTweet.trim());
return tweets;
}
// Send threaded tweets
async function sendThreadedTweet(client, content, replyToId) {
const tweets = [];
const parts = splitTweetContent(content);
let lastTweetId = replyToId;
for (const part of parts) {
const tweet = await client.sendTweet(part, lastTweetId);
tweets.push(tweet);
lastTweetId = tweet.id;
await new Promise((resolve) => setTimeout(resolve, 1000));
}
return tweets;
}
Memory Integration
Store tweets and maintain conversation context:
// Store tweet in database
async function storeTweetIfNotExists(tweet) {
const exists = await prisma.tweet.count({
where: { id: tweet.id },
});
if (!exists) {
await prisma.tweet.create({
data: {
id: tweet.id,
text: tweet.text,
userId: tweet.userId,
username: tweet.username,
conversationId: tweet.conversationId,
inReplyToId: tweet.inReplyToId,
permanentUrl: tweet.permanentUrl,
},
});
return true;
}
return false;
}
// Get conversation thread
async function getTweetThread(conversationId) {
return prisma.tweet.findMany({
where: { conversationId },
orderBy: { createdAt: "asc" },
});
}
Best Practices
Rate Limiting
Use RequestQueue for API calls
Add delays between tweets
Handle API errors gracefully
Implement exponential backoff
Testing
Use dryRun mode for testing
Monitor tweet content
Test thread splitting
Verify mention handling
Last updated