We are building a structured content generator that turns a one-line topic into a blog outline, a social thread, and a newsletter draft. It is for technical marketers and developer advocates who need consistent first drafts without worrying about prompt length driving up inference costs.
What you'll need
- Python 3.10 or newer.
- The OpenAI SDK:
pip install openai - An Oxlo.ai API key from https://portal.oxlo.ai
Because Oxlo.ai uses flat per-request pricing, you can load a long style guide into the system prompt and still pay the same cost as a short ping. See https://oxlo.ai/pricing for plan details.
Step 1: Set up the client
Create a file named content_generator.py and initialize the client. Oxlo.ai is fully OpenAI SDK compatible, so the only difference is the base URL and your Oxlo.ai API key.
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
Step 2: Design the system prompt
The system prompt defines the persona and the exact output format. Keeping it in a constant makes it easy to iterate without touching business logic.
SYSTEM_PROMPT = """You are a senior technical content strategist.
Given a topic and a target audience, produce three deliverables:
1. BlogOutline: A bulleted outline with a headline, 3-5 H2 sections, and a one-sentence takeaway for each.
2. SocialThread: A 5-tweet thread. Mark each tweet with "Tweet N:".
3. Newsletter: A 150-word email intro that hooks the reader and links to the blog post.
Write in a clear, direct style. Avoid fluff."""
Step 3: Build the generation function
Wrap the API call in a function that accepts a topic and an audience. I use llama-3.3-70b because it handles long instructions and structured creative tasks reliably on Oxlo.ai.
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
SYSTEM_PROMPT = """You are a senior technical content strategist.
Given a topic and a target audience, produce three deliverables:
1. BlogOutline: A bulleted outline with a headline, 3-5 H2 sections, and a one-sentence takeaway for each.
2. SocialThread: A 5-tweet thread. Mark each tweet with "Tweet N:".
3. Newsletter: A 150-word email intro that hooks the reader and links to the blog post.
Write in a clear, direct style. Avoid fluff."""
def generate_package(topic: str, audience: str) -> str:
user_message = f"Topic: {topic}\nAudience: {audience}"
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
)
return response.choices[0].message.content
if __name__ == "__main__":
print(generate_package("Zero-downtime database migrations", "senior backend engineers"))
Step 4: Enforce structure with JSON mode
Parsing free text in a pipeline is fragile. Oxlo.ai supports JSON mode, so we can request valid JSON and unpack it in Python. Update the prompt to request JSON, then add response_format to the call.
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
SYSTEM_PROMPT = """You are a senior technical content strategist.
Given a topic and a target audience, produce a JSON object with exactly these keys:
- blog_outline: An array of objects, each with "headline", "sections" (array of strings), and "takeaway".
- social_thread: An array of exactly 5 strings, each under 280 characters.
- newsletter: A string containing a 150-word email intro.
Write in a clear, direct style. Avoid fluff."""
def generate_package(topic: str, audience: str) -> dict:
user_message = f"Topic: {topic}\nAudience: {audience}"
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
response_format={"type": "json_object"},
)
return json.loads(response.choices[0].message.content)
if __name__ == "__main__":
package = generate_package("Zero-downtime database migrations", "senior backend engineers")
print(json.dumps(package, indent=2))
Step 5: Batch process a content calendar
Most teams do not publish once. They plan a week or month ahead. Because Oxlo.ai bills per request instead of per token, running this script against twenty topics with long system prompts costs the same as twenty minimal prompts. Loop over a list and write each package to its own JSON file.
import json
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
SYSTEM_PROMPT = """You are a senior technical content strategist.
Given a topic and a target audience, produce a JSON object with exactly these keys:
- blog_outline: An array of objects, each with "headline", "sections" (array of strings), and "takeaway".
- social_thread: An array of exactly 5 strings, each under 280 characters.
- newsletter: A string containing a 150-word email intro.
Write in a clear, direct style. Avoid fluff."""
def generate_package(topic: str, audience: str) -> dict:
user_message = f"Topic: {topic}\nAudience: {audience}"
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
response_format={"type": "json_object"},
)
return json.loads(response.choices[0].message.content)
CALENDAR = [
("Zero-downtime database migrations", "senior backend engineers"),
("Introduction to eBPF", "platform engineers"),
("Testing microservices with contract tests", "staff engineers"),
]
os.makedirs("output", exist_ok=True)
for topic, audience in CALENDAR:
slug = topic.lower().replace(" ", "-").replace(",", "")[:40]
data = generate_package(topic, audience)
with open(f"output/{slug}.json", "w") as f:
json.dump(data, f, indent=2)
print(f"Wrote output/{slug}.json")
Run it
Save the final script as content_generator.py, set your key, and run it.
export OXLO_API_KEY="sk-oxlo.ai-..."
python content_generator.py
Example output for the first topic:
Wrote output/zero-downtime-database-migrations.json
And the file contents:
{
"blog_outline": [
{
"headline": "Zero-Downtime Database Migrations: A Practical Playbook",
"sections": [
"Expand/contract pattern for schema changes",
"Backfilling data without locking tables",
"Feature flags to toggle between old and new queries",
"Rollback strategies and health checks"
],
"takeaway": "You can ship schema changes during business hours if you separate deployment from activation."
}
],
"social_thread": [
"Most teams still do database migrations at 2 AM because they fear downtime. That is a process smell, not a technical law.",
"The expand/contract pattern lets you add a new column or table long before you switch reads and writes to it.",
"Backfills should run in batches. A single UPDATE on millions of rows will lock your table and wake up your on-call.",
"Use feature flags to route traffic gradually. If latency spikes, flip the flag off. No rollback script needed.",
"Migrations are just deploys. Treat them with the same CI, reviews, and canary standards as application code."
],
"newsletter": "This week we are dismantling the myth that database migrations require maintenance windows. I walk through the expand/contract pattern, batched backfills, and feature-flagged cutovers that let you ship schema changes on a Tuesday afternoon. If your team still schedules downtime for ALTER TABLE, this one is for you."
}
Next steps
Swap in qwen-3-32b if you need the same pipeline in Chinese, Spanish, or German. Or try kimi-k2.6 if you want the model to reason through source material before drafting the outline. If you are generating thousands of packages a month, Oxlo.ai's request-based pricing means your cost stays flat regardless of how much context you add. Check https://oxlo.ai/pricing to see which tier fits your volume.
Top comments (0)