# Agent 2 — Mail Generator Agent

**Build Priority:** 2
**Time to Build:** 1–2 days
**Impact:** ⭐⭐⭐⭐⭐ — Direct mail IS the funnel
**Cost/Month:** $1–2/letter (Lob)

## What It Does

Takes the Lead Finder's scored list and auto-generates personalized direct mail letters. Populates the four template variants (from `direct-mail-templates.md`) with each property's specific data.

## Inputs

- Scored lead CSV from Agent 1
- Owner name, property address, neighborhood, bedroom count, AirDNA revenue range
- Template selection: which variant per lead (A/B/C/D)

## Outputs

- Personalized letter for each lead (PDF, ready to print and mail)
- Postcard front/back designs with dynamic QR codes
- Printing queue file for Lob or PostGrid (automated mail APIs)

## Mail API Options

| Service | Cost/Letter | Best For |
|---------|------------|----------|
| Lob | ~$1.50 | Full automation — API sends physical mail |
| PostGrid | ~$1.00 | Similar, cheaper at scale |
| Handwrytten | ~$3–5 | Handwritten-style notes (Variant D) |
| Canva API + local print | $0.50 + stamp | Manual fulfillment, cheapest |

## Tech Stack

- **Template Engine:** Jinja2 (Python) — fills variables into template strings
- **PDF Generation:** WeasyPrint or ReportLab
- **Mail API:** Lob Python SDK (auto-sends physical mail)
- **QR Codes:** qrcode Python library → links to personalized landing page
- **Scheduling:** Runs after Agent 1 completes (chained cron)

## How to Build

```python
class MailGeneratorAgent:
    def select_variant(self, lead):
        """Pick best template variant based on lead profile"""
        if lead['score'] > 70: return 'A'   # Revenue-focused
        elif lead['is_absentee']: return 'B' # Hassle-free
        elif lead['score'] > 40: return 'D'  # Neighbor note
        else: return 'C'                     # Postcard

    def generate_qr(self, lead_id, landing_url): ...
    def render_letter(self, lead, variant): ...
    def send_via_lob(self, lead, rendered_html): ...
    def run_campaign(self, leads_csv_path): ...
```

## Integration

**Schedule:** After Agent 1 completes (using context_from Agent 1's job_id)
**Or:** "every Monday at 10am" if Agent 1 runs at 9am
