Twitter data access for elizaOS agents without requiring login credentials.
Traditional Twitter/X integrations require users to provide their own Twitter account credentials, which creates several problems:
- Account Risk: Using personal accounts for scraping can lead to rate limits or bans
- Credential Management: Storing Twitter passwords and handling 2FA is complex and risky
- Rate Limits: Personal accounts have strict rate limits that throttle AI agents
This plugin solves these problems by using twitterapi.io, a third-party API service that provides:
- No login required - just an API key
- High rate limits (100 QPS per key)
- No risk to personal accounts
- Reliable, battle-tested infrastructure (millions of API calls processed)
# The plugin is part of the elizaOS monorepo
# Add to your character's plugins array:
plugins: ['@elizaos/plugin-twitterapi-io']Set your API key in .env:
# Get your key at https://twitterapi.io
TWITTER_API_IO_KEY=your_api_key_hereThe plugin is designed to load even without an API key. This is intentional because:
- Developer Experience: Developers can include the plugin in their character config without immediately needing an API key
- Production Flexibility: In production, some agents may need Twitter access while others don't
- No Crashes: Missing config shouldn't crash the entire agent - it should just disable that capability
When no API key is configured:
- The plugin loads successfully
- The service starts but reports "not functional"
- Actions return
falsefromvalidate()so the LLM won't try to use them - Warning logs explain how to enable the plugin
Search Twitter for tweets matching any query.
Triggers: "search twitter for...", "find tweets about...", "what are people saying about..."
Example:
User: Search Twitter for AI news
Agent: Here's what I found on Twitter about "AI news":
β’ @TechNews: "OpenAI announces..." (5.2k likes, 1.2k RTs)
...
Get profile information about a Twitter user.
Triggers: "who is @username", "tell me about Twitter user...", "get info on..."
Example:
User: Who is @elonmusk on Twitter?
Agent: **@elonmusk** (Elon Musk)
Technoking of Tesla...
π Stats: Followers: 150M, Following: 500
Get recent tweets from a specific user.
Triggers: "what has @user tweeted", "recent tweets from...", "show me @user's tweets"
Example:
User: What has @sama tweeted recently?
Agent: Recent tweets from @sama:
1. "Excited to announce..." π
Jan 20 | β€οΈ 5.2K
...
Get tweets mentioning a specific user.
Triggers: "who mentioned @user", "mentions of...", "what are people saying to @user"
Example:
User: Who mentioned @OpenAI recently?
Agent: Recent mentions of @OpenAI:
1. @Developer: "Hey @OpenAI, your API is amazing..."
...
For custom code, access the service directly:
import type { TwitterApiService } from '@elizaos/plugin-twitterapi-io';
// In your action/provider/service:
const twitterService = runtime.getService('twitterapi-io') as TwitterApiService;
// Check if service is available (has valid API key)
if (twitterService?.isAvailable()) {
// Search tweets
const results = await twitterService.client.advancedSearch({
query: 'elizaOS',
queryType: 'Latest' // or 'Top'
});
// Get user info
const user = await twitterService.client.getUserInfo({
userName: 'elikimy'
});
// Get user timeline
const timeline = await twitterService.client.getUserTimeLine({
userName: 'sama',
include_replys: false,
since_time: Math.floor(Date.now() / 1000) - 86400 // Last 24h
});
// Get mentions
const mentions = await twitterService.client.getMentions({
userName: 'OpenAI',
since_time: sevenDaysAgo,
until_time: now
});
}The TwitterApiClient provides these methods:
| Method | Description | Use Case |
|---|---|---|
advancedSearch(params) |
Search tweets with advanced query syntax | Finding tweets about topics |
getUserInfo(params) |
Get user profile data | Looking up users |
getUserFollowers(params) |
Get user's followers | Social graph analysis |
getTweetReplies(params) |
Get replies to a tweet | Conversation threads |
getMentions(params) |
Get tweets mentioning a user | Monitoring mentions |
getUserTimeLine(params) |
Get user's recent tweets | Following users |
getListTweets(params) |
Get tweets from a Twitter list | Curated feeds |
The search query supports Twitter's advanced search syntax:
elonmusk # Basic keyword search
from:elonmusk # Tweets from a user
to:elonmusk # Tweets to a user
@elonmusk # Mentions of a user
#bitcoin # Hashtag search
elonmusk since:2024-01-01 # Date filtering
elonmusk until:2024-12-31 # Date filtering
elonmusk min_faves:100 # Minimum likes
Reference: Twitter Advanced Search
src/
βββ index.ts # Plugin definition - single entry point for elizaOS
βββ service.ts # Service layer - manages lifecycle and state
βββ client.ts # API client - handles HTTP requests and caching
βββ config.ts # Configuration - validation and defaults
βββ types.ts # TypeScript types - shared interfaces
βββ actions/ # Agent actions - LLM-invokable capabilities
Why separate Service and Client?
- Service: Handles elizaOS integration (lifecycle, runtime access)
- Client: Pure API wrapper (no elizaOS dependencies, easily testable)
This separation allows:
- Testing the client without mocking elizaOS runtime
- Reusing the client in other contexts
- Clear responsibility boundaries
Why Actions in separate files?
- Each action has distinct trigger phrases and handling logic
- Easier to maintain and test individually
- Clear mapping: one file = one capability
The client implements in-memory caching because:
- Rate Limit Protection: Reduces API calls for repeated queries
- Response Time: Cached responses return instantly
- Cost Efficiency: Each API call has a cost
Cache duration is 30 seconds by default - long enough to prevent duplicate calls, short enough to stay fresh.
API calls include retry logic with exponential backoff because:
- Network Reliability: Transient failures are common
- API Stability: Even reliable APIs have occasional hiccups
- User Experience: Silent retry is better than immediate failure
Default: 3 attempts with exponential backoff (1s, 2s, 4s delays).
# Run all tests
bun test
# Tests are split into:
# - Unit tests: Always run, test code logic
# - Integration tests: Only run with TWITTER_API_IO_KEY setIntegration tests make real API calls, which:
- Require a valid API key
- Cost money (API usage)
- Can be slow (network latency)
- May fail due to external factors
By making them conditional, developers can:
- Run unit tests quickly during development
- Run full integration tests in CI with secrets
- Avoid test failures due to missing keys
Check logs for:
[TwitterAPI.io] API key not provided - service loaded but not functional
Solution: Set TWITTER_API_IO_KEY in your .env file.
Your API key is invalid or expired.
Solution: Get a new key at twitterapi.io.
You've exceeded your API quota.
Solution:
- Upgrade your twitterapi.io plan
- Implement request throttling in your agent
MIT - See LICENSE file in the elizaOS repository.
- Original PR #1641 by @kaitoInfra
- API service provided by twitterapi.io