We are building a product copy generator that replaces rigid mail-merge templates with an adaptive LLM agent. If you currently maintain hundreds of Mad Libs-style content strings, this tutorial gives you a working replacement in under fifty lines of Python.
What you'll need
- Python 3.10 or newer
pip install openai- An Oxlo.ai API key from https://portal.oxlo.ai
Step 1: Model the traditional pipeline
First, we implement the old approach so we have a baseline to beat. Traditional generation uses string templates with conditional blocks. The result is repetitive and breaks when the input does not match the expected shape.
from dataclasses import dataclass
@dataclass
class Product:
name: str
category: str
audience: str
key_feature: str
price_tier: str
def traditional_template(p: Product) -> str:
template = (
f"Introducing the {p.name}, the perfect {p.category} for {p.audience}. "
f"Featuring our signature {p.key_feature}, it delivers unmatched value. "
)
if p.price_tier == "budget":
template += "Affordable quality without compromise."
elif p.price_tier == "premium":
template += "Premium craftsmanship for the discerning buyer."
else:
template += "Great product for everyday use."
return template
# Example
product = Product(
name="AeroGlide X1",
category="running shoe",
audience="marathon runners",
key_feature="carbon-fiber plate",
price_tier="premium"
)
print(traditional_template(product))
Step 2: Set up the Oxlo.ai client
We use the OpenAI SDK as a drop-in client for Oxlo.ai. I am using Llama 3.3 70B because it follows system instructions tightly for structured commercial copy.
from openai import OpenAI
client = OpenAI(
base_url="https://api.oxlo.ai/v1",
api_key="YOUR_OXLO_API_KEY" # from https://portal.oxlo.ai
)
Step 3: Write the agent system prompt
Instead of concatenating strings, we give the model a role, constraints, and audience context. The LLM reasons about tone and emphasis rather than blindly filling slots.
SYSTEM_PROMPT = """You are a senior product copywriter.
Write one paragraph of marketing copy for the product described by the user.
Rules:
- Adapt tone to the audience and price tier. Do not mention the price tier explicitly.
- Highlight the key feature naturally, not as a fill-in-the-blank.
- Keep output under 75 words.
- Do not use clichés like 'unmatched value' or 'perfect choice'."""
Step 4: Build the LLM generation function
This function replaces the template. It serializes the product dataclass into a brief and sends it to Oxlo.ai. Because the model understands context, it handles edge cases that would require dozens of new template branches.
def generate_copy(product: Product) -> str:
user_message = (
f"Product: {product.name}\n"
f"Category: {product.category}\n"
f"Audience: {product.audience}\n"
f"Key feature: {product.key_feature}\n"
f"Positioning: {product.price_tier}"
)
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
temperature=0.7,
max_tokens=150,
)
return response.choices[0].message.content.strip()
# Test
print(generate_copy(product))
Step 5: Batch process with adaptive formatting
Traditional pipelines need a new template for every category. Here we feed a mixed list of products to the same function. The LLM adjusts voice automatically: technical for developers, playful for kids, restrained for enterprise. This is where request-based pricing helps. On Oxlo.ai, each API call costs the same flat rate regardless of how long the product brief is, so long-context SKUs do not blow up the bill the way token-based pricing would.
products = [
Product("DevStack Pro", "IDE plugin", "backend engineers", "zero-config CI/CD", "premium"),
Product("BubbleBot", "STEM toy", "children ages 6-9", "modular soap-bubble labs", "budget"),
Product("AuditShield", "compliance SaaS", "fintech CISOs", "real-time GDPR mapping", "enterprise"),
]
for p in products:
copy = generate_copy(p)
print(f"--- {p.name} ---")
print(copy)
print()
Run it
Save the full script as content_agent.py and run:
python content_agent.py
Example output:
--- AeroGlide X1 ---
Engineered for marathon runners, the AeroGlide X1 pairs a responsive carbon-fiber plate with a featherweight upper that disappears over 26.2 miles. Every stride feels propulsive without sacrificing cushioning.
--- DevStack Pro ---
DevStack Pro plugs directly into your workflow, shipping code through zero-config CI/CD pipelines while you focus on logic, not YAML. Built for backend teams who treat infrastructure as a last resort.
--- BubbleBot ---
BubbleBot turns bath time into a science lab. Kids snap together modular bubble wands, mix solutions, and discover surface tension through play. Messy hands, bright minds.
--- AuditShield ---
AuditShield maps GDPR requirements to your live infrastructure in real time, giving fintech CISOs an always-current compliance posture without the quarterly scramble for evidence.
Notice how the LLM shifted from technical density to playful rhythm to enterprise formality, all from the same prompt. A template system would need three separate files and conditional logic to achieve that.
Wrap up
You now have a working content generation agent that replaces brittle templates with adaptive LLM reasoning. Two concrete next steps: wire the generate_copy function into a FastAPI endpoint so your CMS can call it, or add a second Oxlo.ai pass using Qwen 3 32B to translate the same copy into other languages without maintaining separate template sets.
Top comments (0)