Skip to content

elizaos-plugins/plugin-twitterapi-io

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

@elizaos/plugin-twitterapi-io

Twitter data access for elizaOS agents without requiring login credentials.

Why This Plugin Exists

Traditional Twitter/X integrations require users to provide their own Twitter account credentials, which creates several problems:

  1. Account Risk: Using personal accounts for scraping can lead to rate limits or bans
  2. Credential Management: Storing Twitter passwords and handling 2FA is complex and risky
  3. 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)

Installation

# The plugin is part of the elizaOS monorepo
# Add to your character's plugins array:
plugins: ['@elizaos/plugin-twitterapi-io']

Configuration

Set your API key in .env:

# Get your key at https://twitterapi.io
TWITTER_API_IO_KEY=your_api_key_here

Why Graceful Degradation?

The plugin is designed to load even without an API key. This is intentional because:

  1. Developer Experience: Developers can include the plugin in their character config without immediately needing an API key
  2. Production Flexibility: In production, some agents may need Twitter access while others don't
  3. 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 false from validate() so the LLM won't try to use them
  • Warning logs explain how to enable the plugin

Available Actions

SEARCH_TWITTER

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_TWITTER_USER_INFO

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_USER_TIMELINE

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_USER_MENTIONS

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..."
       ...

Programmatic Usage

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
  });
}

API Client Methods

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

Advanced Search Syntax

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

Architecture

Why This Structure?

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:

  1. Testing the client without mocking elizaOS runtime
  2. Reusing the client in other contexts
  3. 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

Why Caching?

The client implements in-memory caching because:

  1. Rate Limit Protection: Reduces API calls for repeated queries
  2. Response Time: Cached responses return instantly
  3. 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.

Why Retry Logic?

API calls include retry logic with exponential backoff because:

  1. Network Reliability: Transient failures are common
  2. API Stability: Even reliable APIs have occasional hiccups
  3. User Experience: Silent retry is better than immediate failure

Default: 3 attempts with exponential backoff (1s, 2s, 4s delays).

Testing

# 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 set

Why Conditional Integration Tests?

Integration 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

Troubleshooting

Plugin loaded but actions not available

Check logs for:

[TwitterAPI.io] API key not provided - service loaded but not functional

Solution: Set TWITTER_API_IO_KEY in your .env file.

API returns 401 Unauthorized

Your API key is invalid or expired.

Solution: Get a new key at twitterapi.io.

Rate limit errors

You've exceeded your API quota.

Solution:

  1. Upgrade your twitterapi.io plan
  2. Implement request throttling in your agent

License

MIT - See LICENSE file in the elizaOS repository.

Credits

About

twitterapi.io plugin

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors