Social Media Manager AI Agent
Why This Matters
Social media management demands consistent brand voice, optimal timing, and data-driven strategy across multiple platforms. Manual management of Twitter, LinkedIn, and Instagram accounts is unsustainable at scale. An AI agent automates content creation, scheduling, and engagement tracking while maintaining brand consistency, transforming social media from a time-consuming task into a strategic asset.
Real-World Analogy
Think of a Social Media Agent as a newsroom editor-in-chief. Just as an editor coordinates writers, ensures consistent editorial voice, schedules publication times, and tracks readership metrics, this agent orchestrates content across platforms—adapting each piece for its audience while maintaining the brand's identity and maximizing reach.
What is a Social Media Agent?
Social media agents automate content creation, scheduling, and engagement across platforms. They maintain brand voice consistency, optimize posting times, track performance metrics, and generate data-driven content strategies. Effective agents learn from engagement data to continuously improve content quality and posting strategies.
Project Overview
We will build a social media agent that:
- Generates platform-specific content (Twitter, LinkedIn, Instagram)
- Maintains consistent brand voice across posts
- Schedules posts for optimal engagement times
- Tracks post performance and engagement
- Researches trending hashtags and topics
- Generates content calendars
Expected outcome: An agent that manages a complete social media presence.
Difficulty: Advanced (requires understanding of social media APIs, content strategy, and analytics)
Architecture
Tools & Setup
| Tool | Version | Purpose |
|---|---|---|
| Python | 3.11+ | Core language |
| openai | 1.0+ | LLM backbone |
| tweepy | 4.0+ | Twitter API |
| schedule | 1.2+ | Post scheduling |
| pandas | 2.0+ | Analytics |
| httpx | 0.27+ | Async HTTP |
Step 1: Environment Setup
python -m venv venv
source venv/bin/activate
pip install openai tweepy schedule pandas httpx
export OPENAI_API_KEY="sk-your-key"
Step 2: Content Generator
import json
import logging
from typing import Any, Dict, List, Optional
from openai import AsyncOpenAI
logger = logging.getLogger(__name__)
class ContentGenerator:
"""Generate platform-specific social media content with brand voice."""
CHAR_LIMITS: Dict[str, int] = {
"twitter": 280,
"linkedin": 3000,
"instagram": 2200,
}
def __init__(self, model: str = "gpt-4o", api_key: Optional[str] = None):
self.client = AsyncOpenAI(api_key=api_key)
self.model = model
async def generate_post(
self,
topic: str,
platform: str,
brand_voice: str,
tone: str = "professional",
include_hashtags: bool = True,
) -> Dict[str, Any]:
"""Generate a single platform-specific post."""
limit = self.CHAR_LIMITS.get(platform, 280)
prompt = f"""Create a {platform} post about: {topic}
Brand voice: {brand_voice}
Tone: {tone}
Character limit: {limit}
Include hashtags: {include_hashtags}
Platform-specific rules:
- Twitter: Concise, punchy, use threads for longer content
- LinkedIn: Professional, thought leadership, include CTA
- Instagram: Visual-focused, emoji-friendly, strong hashtag game
Return JSON:
{{
"content": "the post text",
"hashtags": ["list of hashtags"],
"best_posting_time": "suggested time",
"engagement_prediction": "high|medium|low"
}}"""
try:
response = await self.client.chat.completions.create(
model=self.model,
messages=[
{"role": "system", "content": "You are an expert social media copywriter."},
{"role": "user", "content": prompt},
],
temperature=0.7,
)
return json.loads(response.choices[0].message.content)
except (json.JSONDecodeError, IndexError) as e:
logger.warning(f"Failed to parse response: {e}")
return {
"content": response.choices[0].message.content,
"hashtags": [],
"best_posting_time": "09:00",
"engagement_prediction": "medium",
}
except Exception as e:
logger.error(f"Content generation failed: {e}")
raise
async def generate_content_calendar(
self,
topics: List[str],
brand_voice: str,
days: int = 7,
) -> List[Dict[str, Any]]:
"""Generate a content calendar spanning multiple days."""
calendar = []
platforms = ["twitter", "linkedin", "instagram"]
for day in range(days):
for i, topic in enumerate(topics[: len(platforms)]):
platform = platforms[i % len(platforms)]
post = await self.generate_post(topic, platform, brand_voice)
calendar.append({"day": day + 1, "platform": platform, "topic": topic, **post})
return calendar
Step 3: Brand Voice Manager
from typing import Dict, List, Optional
class BrandVoiceManager:
"""Manage brand voice profiles for consistent content generation."""
def __init__(self):
self.voices: Dict[str, str] = {}
def add_voice(self, brand_name: str, description: str) -> None:
self.voices[brand_name] = description
def get_voice(self, brand_name: str) -> str:
return self.voices.get(brand_name, "Professional and helpful")
def create_voice_profile(
self,
brand_name: str,
values: List[str],
tone: str,
do_s: List[str],
dont_s: List[str],
) -> str:
profile = f"""Brand: {brand_name}
Tone: {tone}
Values: {', '.join(values)}
Do: {'; '.join(do_s)}
Don't: {'; '.join(dont_s)}"""
self.voices[brand_name] = profile
return profile
Step 4: Platform Integration and Scheduler
from typing import Dict, Optional
import asyncio
import tweepy
class TwitterClient:
"""Async Twitter/X API client for posting and engagement."""
def __init__(
self,
api_key: str,
api_secret: str,
access_token: str,
access_secret: str,
):
self.client = tweepy.Client(
consumer_key=api_key,
consumer_secret=api_secret,
access_token=access_token,
access_token_secret=access_secret,
)
async def post_tweet(self, content: str, hashtags: Optional[List[str]] = None) -> Dict:
text = content
if hashtags:
tag_str = " ".join(f"#{t.strip('#')}" for t in hashtags[:5])
if len(text) + len(tag_str) + 1 <= 280:
text = f"{text}\n\n{tag_str}"
try:
response = self.client.create_tweet(text=text)
return {"success": True, "tweet_id": response.data["id"]}
except Exception as e:
logger.error(f"Tweet failed: {e}")
return {"success": False, "error": str(e)}
async def get_mentions(self, count: int = 10) -> list:
try:
me = self.client.get_me()
response = self.client.get_users_mentions(
me.data.id,
max_results=count,
tweet_fields=["text", "created_at"],
)
return [
{"id": m.id, "text": m.text, "created_at": m.created_at}
for m in (response.data or [])
]
except Exception as e:
logger.error(f"Mentions fetch failed: {e}")
return []
import schedule
import time
from typing import Callable
from datetime import datetime
class PostScheduler:
"""Schedule and manage social media posts."""
def __init__(self):
self.scheduled_posts: list = []
def schedule_post(self, post: Dict, post_time: str, callback: Callable) -> None:
self.scheduled_posts.append({
"post": post,
"time": post_time,
"callback": callback,
"status": "scheduled",
})
schedule.every().day.at(post_time).do(self._execute_post, post, callback)
def _execute_post(self, post: Dict, callback: Callable) -> None:
result = callback(post.get("content", ""), post.get("hashtags", []))
post["status"] = "posted" if result.get("success") else "failed"
post["result"] = result
def get_optimal_times(self) -> list:
return ["09:00", "12:00", "17:00", "20:00"]
def run_pending(self) -> None:
schedule.run_pending()
def get_scheduled(self) -> list:
return self.scheduled_posts
Step 5: Analytics and Agent
from typing import Any, Dict, List, Optional
from datetime import datetime
import pandas as pd
class AnalyticsTracker:
"""Track and analyze social media post performance."""
def __init__(self):
self.posts: List[Dict] = []
def record_post(self, post: Dict, platform: str) -> None:
post["platform"] = platform
post["posted_at"] = datetime.now().isoformat()
post["metrics"] = {"likes": 0, "shares": 0, "comments": 0, "impressions": 0}
self.posts.append(post)
def update_metrics(self, post_id: str, metrics: Dict) -> None:
for post in self.posts:
if post.get("id") == post_id:
post["metrics"].update(metrics)
break
def get_performance(self, platform: Optional[str] = None) -> Dict:
posts = [p for p in self.posts if not platform or p.get("platform") == platform]
if not posts:
return {"total_posts": 0}
total_metrics = {"likes": 0, "shares": 0, "comments": 0, "impressions": 0}
for post in posts:
for key in total_metrics:
total_metrics[key] += post.get("metrics", {}).get(key, 0)
avg_metrics = {k: v / len(posts) for k, v in total_metrics.items()}
engagement_rate = (
(total_metrics["likes"] + total_metrics["shares"] + total_metrics["comments"])
/ max(total_metrics["impressions"], 1)
* 100
)
return {
"total_posts": len(posts),
"total_metrics": total_metrics,
"avg_metrics": avg_metrics,
"engagement_rate": engagement_rate,
}
class SocialMediaAgent:
"""Orchestrate social media operations across platforms."""
def __init__(self, model: str = "gpt-4o", api_key: Optional[str] = None):
self.generator = ContentGenerator(model, api_key)
self.brand_voice = BrandVoiceManager()
self.analytics = AnalyticsTracker()
self.scheduler = PostScheduler()
async def create_post(
self,
topic: str,
platform: str,
brand: str = "default",
tone: str = "professional",
) -> Dict:
voice = self.brand_voice.get_voice(brand)
return await self.generator.generate_post(topic, platform, voice, tone)
async def schedule_post(self, post: Dict, platform: str, time: str) -> None:
self.scheduler.schedule_post(post, time, lambda c, h: {"success": True})
self.analytics.record_post(post, platform)
async def generate_calendar(
self,
topics: List[str],
brand: str = "default",
days: int = 7,
) -> List[Dict]:
voice = self.brand_voice.get_voice(brand)
return await self.generator.generate_content_calendar(topics, voice, days)
def get_analytics(self, platform: Optional[str] = None) -> Dict:
return self.analytics.get_performance(platform)
Mathematical Foundation
Optimal Posting Time:
Finds the time slot that maximizes total engagement across historical posts.
Engagement Rate:
Measures what percentage of viewers engage with content.
Content Performance Score:
Where are configurable weights balancing engagement, reach, and sentiment.
Performance Considerations
| Metric | Latency | Cost | Accuracy |
|---|---|---|---|
| Content generation | 3-8s per post | $0.01-0.03 per post | High with brand voice |
| Hashtag research | 2-5s | $0.01 per query | Medium |
| Analytics computation | <1s | Free (local) | Exact |
| Scheduling overhead | <100ms | Free | High |
| Full calendar generation | 30-60s | $0.10-0.20 | High |
Security Considerations
- Store API keys in environment variables, never in code
- Use OAuth 2.0 for platform authentication
- Implement rate limiting to avoid API bans
- Validate all generated content before auto-posting
- Monitor for brand-damaging content in generated output
- Log all automated actions for audit trails
- Use separate credentials per brand account
Interview Q&A
Q1: How does the agent maintain brand voice consistency across different topics?
The BrandVoiceManager stores a structured voice profile (tone, values, do's, don'ts) injected into every content generation prompt. The LLM receives this profile as system context, ensuring all generated content adheres to the same voice regardless of topic.
Q2: What is the trade-off between posting frequency and content quality?
Higher frequency increases visibility but risks audience fatigue. Platform-specific optimal frequencies: Twitter 3-5 posts/day, LinkedIn 1-2 posts/day, Instagram 1 post/day. Monitor engagement rate—if it declines, reduce frequency.
Q3: How do you handle platform-specific character limits?
The generate_post method includes the character limit in the prompt and validates output length. For Twitter (280 chars), generate threads for longer content. Pre-validate content length before publishing.
Q4: How does hashtag research improve reach?
Use a mix: 2-3 high-volume hashtags (>1M posts) for reach, 3-5 medium-volume (100K-1M) for relevance, and 2-3 niche (<100K) for targeted visibility. Avoid banned or spammy hashtags.
Q5: How would you implement A/B testing for content?
Generate two variations, schedule both to similar time slots, track engagement per variant. After statistical significance (100+ impressions per variant), declare a winner and use that style for future content.
Q6: How do you handle negative comments and engagement?
Detect negative sentiment in mentions using sentiment analysis. For mild negativity, generate empathetic responses. For severe negativity or spam, flag for human review. Never argue or delete legitimate criticism.
Q7: What metrics matter most for LinkedIn vs Twitter?
LinkedIn: impressions, click-through rate, and comments (engagement depth). Twitter: retweets, quote tweets, and reply threads (virality). Weight these differently per platform in the Content Performance Score.
Q8: How would you scale this for managing multiple brand accounts?
Add brand_id to all methods. Store profiles in a database. Use separate API credentials per brand. Implement queue-based scheduling to prevent rate limits. Add role-based access control.
Common Pitfalls & Solutions
| Pitfall | Solution |
|---|---|
| Content sounds robotic | Fine-tune with brand voice examples; use few-shot prompting |
| Low engagement | A/B test content formats; analyze top-performing posts |
| API rate limits | Batch operations; use queues; respect platform limits |
| Scheduling conflicts | Implement content calendar validation; prevent overlap |
| Brand voice drift | Regular audits; maintain voice profile documentation |
| Hashtag saturation | Mix high, medium, and niche hashtags; avoid banned tags |
| Negative engagement | Sentiment monitoring; human review for severe cases |
| Cross-platform duplication | Adapt content per platform; never copy-paste directly |
Knowledge Check
Q1: What is the recommended posting frequency for LinkedIn? A) 5-10 posts/day B) 1-2 posts/day C) 1 post/week D) No limit
Answer
B) 1-2 posts/day. LinkedIn's algorithm favors quality over quantity.Q2: What does the engagement rate formula measure? A) Total followers B) Percentage of viewers who engage C) Posts per day D) Revenue per post
Answer
B) Percentage of viewers who engage with content.Q3: How many hashtags should a typical Instagram post include? A) 1-2 B) 5-8 C) 10-15 D) 30
Answer
C) 10-15. Best balance of reach and relevance without appearing spammy.Q4: What is the primary purpose of the brand voice profile? A) Increase API costs B) Ensure consistent tone and style C) Reduce posting frequency D) Track analytics
Answer
B) To ensure consistent tone and style across all content.Q5: When should the agent flag content for human review? A) Never B) When sentiment is negative or engagement prediction is low C) Always D) Only for Twitter
Answer
B) When sentiment is negative or engagement prediction is low.Q6: What does the optimal posting time formula maximize? A) Follower count B) Total engagement across historical posts C) Revenue D) API efficiency
Answer
B) Total engagement across historical posts.Summary with Key Takeaways
- Brand voice management ensures consistency across all content and platforms
- Platform-specific optimization maximizes engagement per platform's unique algorithm
- Data-driven scheduling finds optimal posting times based on historical performance
- Analytics tracking enables continuous content improvement through measurable feedback
- Content calendars provide strategic overview and prevent ad-hoc posting
- Hashtag research balances reach (high-volume) with relevance (niche) for maximum discovery