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)
});
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.TWITTER_DRY_RUN === "true"
};
const twitter = new TwitterClient(agent, config);
await twitter.start(); // Starts posting & monitoring intervals
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
});
}
}
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);
}
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;
}
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" }
});
}