Post, reply, quote, and interact with X (Twitter) using the X API v2
X Tool enables agents to post content, reply to posts, create quote posts, manage polls, upload media, and interact with X (formerly Twitter) using the official X API v2.
from praisonai_tools import post_to_x# Simple postresult = post_to_x("Shipping a new feature today! 🚀")print(f"Posted: {result['url']}")
2
Function Helper
from praisonai_tools import post_to_x, reply_to_x, quote_x_post# Post with mediapost_result = post_to_x("Check out this image!", media_paths=["image.jpg"])post_id = post_result['data']['id']# Reply to postreply_to_x(post_id, "Great update!")# Quote tweetquote_x_post(post_id, "This is exactly what we needed!")
3
Agent Usage
from praisonaiagents import Agentfrom praisonai_tools import post_to_xagent = Agent( name="social_poster", llm="gpt-4o-mini", instructions="When asked to post on X, call post_to_x and return the URL.", tools=[post_to_x],)agent.start('Post on X: "Just deployed our latest feature!"')
from praisonai_tools import XToolx_tool = XTool( api_key="your_api_key", # Optional if env var set api_key_secret="your_api_secret", # Optional if env var set access_token="your_access_token", # Optional if env var set access_token_secret="your_access_secret" # Optional if env var set)
from praisonai_tools import post_to_x# Basic text postresult = post_to_x("Hello X! 👋")print(f"Post URL: {result['url']}")
from praisonai_tools import post_to_x# Post with imageresult = post_to_x( text="Check out our new feature! 🚀", media_paths=["screenshot.png"])print(f"Posted with media: {result['url']}")
from praisonai_tools import post_to_x, reply_to_x# Create threadmain_post = post_to_x("🧵 Thread about AI agents: 1/3")reply_1 = reply_to_x( main_post['data']['id'], "AI agents can automate social media posting... 2/3")reply_2 = reply_to_x( reply_1['data']['id'], "The future is autonomous content creation! 3/3")
from praisonai_tools import post_to_x# Create pollresult = post_to_x( text="What's your favorite AI model? 🤖", poll_options=["GPT-4", "Claude", "Gemini", "Llama"], poll_duration_minutes=1440 # 24 hours)
from praisonaiagents import Agentfrom praisonai_tools import post_to_x, reply_to_x, search_xagent = Agent( name="social_manager", llm="gpt-4o", instructions="""You manage social media presence on X. - Post engaging content - Reply to mentions - Share updates about our products""", tools=[post_to_x, reply_to_x, search_x])# Schedule postsagent.start("Post about our new AI feature launch")
from praisonaiagents import Agentfrom praisonai_tools import search_x, reply_to_xsupport_agent = Agent( name="support_bot", instructions="""Monitor mentions and provide helpful responses. Be professional and solution-oriented.""", tools=[search_x, reply_to_x])# Monitor and respondsupport_agent.start("Check for mentions of our brand and respond helpfully")
from praisonaiagents import Agentfrom praisonai_tools import search_x, quote_x_post, post_to_xcurator = Agent( name="content_curator", instructions="""Find and share interesting tech content. Add thoughtful commentary when quoting posts.""", tools=[search_x, quote_x_post, post_to_x])curator.start("Find and share interesting AI news with commentary")
OAuth 1.0a provides full posting capabilities, while app-only bearer tokens are read-only.
# ✅ Use OAuth 1.0a for posting x_tool = XTool( api_key="key", api_key_secret="secret", access_token="token", access_token_secret="token_secret")
Handle Rate Limits Gracefully
Implement exponential backoff to handle rate limits (300 posts per 15 minutes).
import timefrom praisonai_tools import post_to_xdef post_with_retry(text, max_retries=3): for attempt in range(max_retries): try: return post_to_x(text) except Exception as e: if attempt < max_retries - 1: time.sleep(2 ** attempt) # Exponential backoff else: raise
Manage Character Limits
Split long content into threaded posts for better readability.
from praisonai_tools import post_to_x, reply_to_xdef safe_post(text, max_chunk=270): if len(text) <= 280: return post_to_x(text) # Split into thread; each chunk leaves room for " N/M" suffix chunks = [text[i:i+max_chunk] for i in range(0, len(text), max_chunk)] total = len(chunks) first = post_to_x(f"{chunks[0]} 1/{total}") prev_id = first['data']['id'] for i, chunk in enumerate(chunks[1:], start=2): reply = reply_to_x(prev_id, f"{chunk} {i}/{total}") prev_id = reply['data']['id'] return first
Secure Credential Management
Store credentials in environment variables rather than hardcoding them.