Build apps that interact with X.com (Twitter).
Overview
This guide shows you how to build an app that uses the X.com integration to post tweets, read timelines, and interact with the X API.
Prerequisites
Users running your app need:
- An X Developer account with OAuth 2.0 configured
X_CLIENT_IDandX_CLIENT_SECRETsecrets configured in Settings- X.com integration connected (OAuth authorized)
ā See X.com Integration Setup for user setup instructions
App Configuration
inf.yaml
Declare the X.com capabilities your app needs:
yaml
1name: my-x-app2description: Posts tweets using AI3category: social4 5requirements:6 integrations:7 - key: x.tweet.write8 description: Post tweets to X.com9 10 - key: x.tweet.read11 description: Read tweet data12 optional: true13 14 - key: x.dm.write15 description: Send direct messages16 optional: true17 18resources:19 gpu:20 count: 021 ram: 200022 23python: "3.11"Available Capabilities
| Capability | Description | Scopes Granted |
|---|---|---|
x.tweet.read | Read tweets | tweet.read, users.read |
x.tweet.write | Post tweets | tweet.read, tweet.write, users.read |
x.user.read | Read user profiles | users.read |
x.follow.read | Read followers/following | follows.read, users.read |
x.follow.write | Follow/unfollow users | follows.write, users.read |
x.dm.read | Read direct messages | dm.read, users.read |
x.dm.write | Send direct messages | dm.write, users.read |
x.like.read | Read liked tweets | like.read, users.read |
x.like.write | Like/unlike tweets | like.write, users.read |
Environment Variables
When your app runs, these environment variables are injected:
| Variable | Description |
|---|---|
X_ACCESS_TOKEN | OAuth 2.0 access token (auto-refreshed) |
X_ACCESS_TOKEN_EXPIRES_AT | Token expiry time (RFC3339 format) |
App Code
inference.py
python
1import os2import tweepy3from inferencesh import BaseApp, BaseAppInput, BaseAppOutput4from pydantic import Field5 6class AppInput(BaseAppInput):7 text: str = Field(description="Tweet text to post")8 9class AppOutput(BaseAppOutput):10 tweet_id: str = Field(description="ID of the posted tweet")11 tweet_url: str = Field(description="URL of the posted tweet")12 13class App(BaseApp):14 client: tweepy.Client = None15 16 async def setup(self, metadata):17 """Initialize the X.com client with OAuth 2.0 token."""18 access_token = os.environ.get("X_ACCESS_TOKEN")19 20 if not access_token:21 raise ValueError("X_ACCESS_TOKEN not found. Is the X.com integration connected?")22 23 # Create client with OAuth 2.0 user context24 self.client = tweepy.Client(bearer_token=access_token)25 26 metadata.log("X.com client initialized")27 28 async def run(self, input_data: AppInput, metadata) -> AppOutput:29 """Post a tweet."""30 metadata.log(f"Posting tweet: {input_data.text[:50]}...")31 32 # Post the tweet33 response = self.client.create_tweet(text=input_data.text)34 35 tweet_id = response.data["id"]36 tweet_url = f"https://x.com/i/web/status/{tweet_id}"37 38 metadata.log(f"Tweet posted: {tweet_url}")39 40 return AppOutput(41 tweet_id=tweet_id,42 tweet_url=tweet_url43 )44 45 async def unload(self):46 """Cleanup."""47 self.client = Nonerequirements.txt
code
1tweepy>=4.14.0Examples
Post a Tweet
python
1# Simple tweet2response = self.client.create_tweet(text="Hello from my AI agent! š¤")3 4# Tweet with media (requires media upload first)5media = self.client.media_upload("image.png")6response = self.client.create_tweet(7 text="Check out this image!",8 media_ids=[media.media_id]9)10 11# Reply to a tweet12response = self.client.create_tweet(13 text="Great point!",14 in_reply_to_tweet_id="1234567890"15)16 17# Quote tweet18response = self.client.create_tweet(19 text="This is so true š",20 quote_tweet_id="1234567890"21)Read Tweets
python
1# Get a specific tweet2tweet = self.client.get_tweet(3 id="1234567890",4 tweet_fields=["created_at", "public_metrics"]5)6 7# Get user's recent tweets8tweets = self.client.get_users_tweets(9 id="user_id",10 max_results=10,11 tweet_fields=["created_at", "public_metrics"]12)13 14# Search tweets15tweets = self.client.search_recent_tweets(16 query="AI agents",17 max_results=1018)User Operations
python
1# Get user info2user = self.client.get_user(username="elonmusk")3 4# Get followers5followers = self.client.get_users_followers(6 id="user_id",7 max_results=1008)9 10# Follow a user (requires x.follow.write)11self.client.follow_user(target_user_id="user_id")Direct Messages
python
1# Send a DM (requires x.dm.write)2self.client.create_direct_message(3 participant_id="user_id",4 text="Hello!"5)6 7# Get DM conversations (requires x.dm.read)8conversations = self.client.get_direct_message_events()Error Handling
python
1import tweepy2 3async def run(self, input_data: AppInput, metadata) -> AppOutput:4 try:5 response = self.client.create_tweet(text=input_data.text)6 return AppOutput(tweet_id=response.data["id"], ...)7 8 except tweepy.TweepyException as e:9 if "duplicate" in str(e).lower():10 raise ValueError("This tweet was already posted")11 elif "rate limit" in str(e).lower():12 raise ValueError("Rate limit exceeded. Try again later.")13 else:14 raise ValueError(f"X.com API error: {e}")Rate Limits
X.com has strict rate limits. Common limits for the free tier:
| Endpoint | Limit |
|---|---|
| Post tweet | 50 per 24 hours |
| Read tweets | 100 per 15 minutes |
| User lookup | 100 per 15 minutes |
Your app should handle rate limit errors gracefully.
Testing Locally
- Set up the X.com integration in Settings
- Export the token for local testing:
bash
1# Get your token from the integration (one-time for testing)2export X_ACCESS_TOKEN="your-token-here"3 4# Run locally5infsh run --input-file input.jsonDeploy
bash
1infsh deployWhen users run your app:
- If they haven't configured X.com ā prompted to set up
- If configured ā app runs with their X.com credentials
- Tokens auto-refresh ā no manual token management needed
Next Steps
- X.com Integration Setup ā User setup guide
- Extending Apps ā Full app development guide
- API & SDK ā Run your app programmatically