Social media monitoring at scale means reading thousands of noisy posts and finding the few that actually matter. In this guide we will build a lightweight Python agent that ingests a feed of posts, classifies sentiment, detects urgent issues, and drafts response suggestions using an LLM. We will run it on Oxlo.ai so the cost per analyzed post stays flat regardless of thread length. See https://oxlo.ai/pricing for current plan options.
What you'll need
- Python 3.10 or newer
- An Oxlo.ai API key from https://portal.oxlo.ai
- The OpenAI SDK:
pip install openai
Step 1: Configure the Oxlo.ai client
We will use the OpenAI SDK as a drop-in replacement pointing at Oxlo.ai. I keep my key in an environment variable so it does not end up in git.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key=os.getenv("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)
Step 2: Define the system prompt
The system prompt is the monitor's instruction manual. It tells the model how to score sentiment, detect urgency, and format output as JSON.
SYSTEM_PROMPT = """You are a social media monitoring analyst. For each post you receive, analyze it and return a JSON object with exactly these keys:
- sentiment: one of "positive", "neutral", "negative", or "urgent_negative"
- topics: an array of up to three topics mentioned
- urgent: boolean, true only if the post describes an outage, security breach, legal threat, or severe customer blocker
- summary: a one-sentence summary of the post
- suggested_reply: a brief, professional reply if sentiment is negative or urgent_negative, otherwise null
Rules:
- Be concise.
- If the post is just spam or unrelated to tech products, set sentiment to "neutral" and topics to [].
- Output ONLY valid JSON. Do not wrap it in markdown fences."""
Step 3: Analyze a single post
This function takes a post dictionary, builds the user message, and calls Llama 3.3 70B on Oxlo.ai. I parse the JSON response and return a structured dict.
import json
def analyze_post(post):
user_message = f"""Platform: {post['platform']}
Author: {post['author']}
Content: {post['content']}"""
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
)
raw = response.choices[0].message.content.strip()
# Some models emit markdown fences; strip them if present
if raw.startswith("
```"):
raw = raw.split("```
")[1].replace("json", "").strip()
return json.loads(raw)
Step 4: Build the ingestion loop
Real feeds arrive as arrays. Here is a mock list of posts representing a brand mention stream. We iterate through them, call the analyzer, and collect results.
MOCK_FEED = [
{
"id": "post_001",
"platform": "twitter",
"author": "dev_user_42",
"content": "AcmeCloud dashboard has been down for 20 minutes. Can't deploy. This is blocking our release."
},
{
"id": "post_002",
"platform": "reddit",
"author": "sre_kai",
"content": "Just migrated our entire infra to AcmeCloud. The new CLI is a huge upgrade. buttery smooth so far."
},
{
"id": "post_003",
"platform": "twitter",
"author": "random_bot",
"content": "Click here for free crypto!!! Not affiliated with AcmeCloud but check my bio!!!"
},
{
"id": "post_004",
"platform": "linkedin",
"author": "cto_maria",
"content": "Disappointed that AcmeCloud removed the audit log API without warning. Compliance team is not happy."
},
]
results = []
for post in MOCK_FEED:
try:
analysis = analyze_post(post)
analysis["post_id"] = post["id"]
analysis["platform"] = post["platform"]
results.append(analysis)
print(f"Analyzed {post['id']}: {analysis['sentiment']}")
except Exception as e:
print(f"Failed on {post['id']}: {e}")
Step 5: Filter and alert on urgent mentions
Monitoring is useless without action. We scan the results for urgency, print alerts to stdout, and write the full report to a JSONL file for downstream tools.
# Alert on urgent items
urgent = [r for r in results if r.get("urgent") is True]
for item in urgent:
print(f"\nALERT on {item['platform']} | {item['summary']}")
print(f"Suggested reply: {item['suggested_reply']}\n")
# Persist everything
with open("monitoring_report.jsonl", "w") as f:
for r in results:
f.write(json.dumps(r) + "\n")
print(f"Wrote {len(results)} records to monitoring_report.jsonl")
Run it
Place all the code above into a single file named social_monitor.py, export your key, and run it.
export OXLO_API_KEY="sk-oxlo.ai-..."
python social_monitor.py
Expected output looks like this:
Analyzed post_001: urgent_negative
Analyzed post_002: positive
Analyzed post_003: neutral
Analyzed post_004: negative
ALERT on twitter | AcmeCloud dashboard outage is blocking a customer release.
Suggested reply: We are aware of the dashboard issue and our team is actively investigating. We will post updates every 15 minutes at status.acmecloud.io. Thank you for your patience.
Wrote 4 records to monitoring_report.jsonl
Wrap-up and next steps
This agent gives you a deterministic cost per post because Oxlo.ai charges by the request, not by the token count. That matters when you start feeding it long Reddit threads or multi-ticket conversations. A concrete next step is to replace MOCK_FEED with real streaming input from the X API or Reddit API. Another is to run this script on a schedule with cron or as a lightweight queue worker that pushes alerts into Slack instead of stdout.
Top comments (0)