Build an AI Email Generator
This part applies part 15's on-brand generation techniques to a genuinely distinct, real output format — email, where structure (a real subject line, a real, concise body, a clear call to action) matters as much as tone. The real use case: GreenDesk's sales team following up with actual, real leads.
The real, complete email generator
# email_generator.py
import json
from shared.ai_client import get_client
from style_guide import STYLE_GUIDES
def generate_follow_up_email(lead: dict) -> dict:
client = get_client()
response = client.messages.create(
model="claude-sonnet-5",
max_tokens=512,
system=(
f"Write a real, personalized follow-up email for a "
f"GreenDesk sales lead.\n\n{STYLE_GUIDES['greendesk']}\n\n"
f"Keep the body under 120 words. Include ONE clear call "
f"to action. Respond with ONLY valid JSON in this exact "
f'format: {{"subject": "...", "body": "..."}}'
),
messages=[
{
"role": "user",
"content": (
f"Lead name: {lead['name']}\n"
f"Company: {lead['company']}\n"
f"Team size: {lead['team_size']}\n"
f"Interest: {lead['interest']}"
),
}
],
)
return json.loads(response.content[0].text)A real, concrete example
real_lead = {
"name": "Priya",
"company": "Northwind Studios",
"team_size": "35",
"interest": "requested a demo of task automation features",
}
email = generate_follow_up_email(real_lead)
print(email["subject"])
print(email["body"])Real, expected output:
Subject: "Following up on your GreenDesk demo request"
Body: "Hi Priya, following up on your interest in GreenDesk's task
automation for Northwind Studios. With a 35-person team, automation
usually saves real, meaningful coordination time. Want to grab 15
minutes this week to see it applied to your actual workflow?"Notice the real, specific personalization — team size and stated interest both directly shape the email's actual content, not just a name inserted into an otherwise generic template.
This is a genuinely different, real value proposition than a traditional mail-merge template — a template can insert a name and company, but it can't naturally weave in "35-person team" as a real, relevant reason automation matters to that specific lead. That kind of contextual, real personalization is exactly what makes this genuinely worth building with an LLM rather than simpler, existing tools.
Real, structured JSON output, and why it matters here specifically
return json.loads(response.content[0].text)This directly extends part 14's structured-output technique — requesting real JSON with subject and body as separate real fields, rather than one undifferentiated block of text, is what lets this function's output drop directly into a real email-sending function (send_email(to=lead["email"], subject=email["subject"], body=email["body"])) without any manual parsing.
A real, important safeguard: human review before sending
def generate_and_queue_for_review(lead: dict) -> None:
email = generate_follow_up_email(lead)
save_to_review_queue(lead_id=lead["id"], subject=email["subject"], body=email["body"])
# a real, human sales rep reviews and approves before it actually sendsThis is a real, deliberate design choice, not an oversight — an AI-generated email making a real, incorrect claim about GreenDesk's actual features, or landing with an off tone for a specific real prospect, is a genuinely more consequential mistake than an internal summary or draft blog post, since it's sent directly, externally, under the company's real name. A queue-for-review step, rather than fully automated sending, is the honest, calibrated safeguard for this specific, higher-stakes real use case.
Batch generation for a real list of leads
def generate_emails_for_leads(leads: list[dict]) -> list[dict]:
return [
{"lead_id": lead["id"], **generate_follow_up_email(lead)}
for lead in leads
]This directly mirrors part 10's translate_catalog() batch pattern — the same real principle of processing a full, real list of items rather than only handling one at a time, genuinely necessary the moment this tool needs to serve GreenDesk's actual, full pipeline of real leads rather than a single example.
Next: building a real AI code explainer with Python — a genuinely technical use case, explaining real code rather than generating marketing or support content.