TL;DR

  • → LLM summarises your data; AgentGen formats it as a styled, downloadable PDF
  • → Works as a tool in LangChain, OpenAI, AutoGen, or any HTTP-capable framework
  • → 2 tokens per page (~$0.03). No monthly fee — buy once, use whenever

AI Agent PDF Report Generation

The classic AI agent limitation: it can analyse your data beautifully, but all you get back is a wall of text. AgentGen fixes that. Your agent summarises the data, AgentGen renders it as a branded, structured PDF — delivered as a CDN link in the same conversation turn.

The two-stage architecture

1

LLM stage

Claude or GPT-4o reads raw metrics, writes an executive summary, and identifies highlights and concerns.

2

Render stage

A Python template maps the structured output to styled HTML. AgentGen converts it to a PDF via headless Chrome.

Step 1 — LLM analysis

import json
from langchain_anthropic import ChatAnthropic

llm = ChatAnthropic(model="claude-opus-4-6", temperature=0.2)

def analyse_metrics(raw_metrics: list[dict]) -> dict:
    """Ask Claude to interpret the numbers and return structured analysis."""
    response = llm.invoke(
        f"""Analyse these metrics and return JSON with:
- "summary": 2-3 sentence executive overview (use specific numbers)
- "highlights": list of 2-3 positive trends
- "concerns": list of 1-2 areas needing attention

Metrics: {json.dumps(raw_metrics, indent=2)}

Return only valid JSON."""
    )
    return json.loads(response.content)

Step 2 — Build the report HTML

def build_report_html(title: str, week: str, metrics: list, analysis: dict) -> str:
    def card(m):
        color = "#16a34a" if m["change_pct"] >= 0 else "#dc2626"
        arrow = "↑" if m["change_pct"] >= 0 else "↓"
        return f"""
          <div style="background:white;border:1px solid #e5e7eb;border-radius:10px;
                      padding:20px;flex:1;min-width:140px">
            <p style="margin:0 0 6px;font-size:11px;color:#9ca3af;text-transform:uppercase">{m['label']}</p>
            <p style="margin:0 0 4px;font-size:26px;font-weight:800">{m['value']}</p>
            <p style="margin:0;font-size:13px;font-weight:600;color:{color}">
              {arrow} {abs(m['change_pct']):.1f}% vs last week
            </p>
          </div>"""

    cards = "".join(card(m) for m in metrics)
    highlights = "".join(f"<li style='color:#166534;margin-bottom:4px'>{h}</li>"
                         for h in analysis["highlights"])
    concerns = "".join(f"<li style='color:#991b1b;margin-bottom:4px'>{c}</li>"
                       for c in analysis["concerns"])

    return f"""<!DOCTYPE html>
    <html><head><meta charset="UTF-8"></head>
    <body style="margin:0;padding:36px;background:#f9fafb;
                 font-family:'Helvetica Neue',Arial,sans-serif">
      <div style="background:linear-gradient(135deg,#1e1b4b,#3730a3);border-radius:12px;
                  padding:28px 32px;color:white;margin-bottom:24px">
        <h1 style="margin:0 0 4px;font-size:22px;font-weight:800">{title}</h1>
        <p style="margin:0;opacity:.7;font-size:13px">Week ending {week}</p>
      </div>
      <div style="background:white;border:1px solid #e5e7eb;border-radius:10px;
                  padding:20px;margin-bottom:20px">
        <p style="margin:0 0 8px;font-size:11px;color:#9ca3af;text-transform:uppercase">
          Executive Summary</p>
        <p style="margin:0;line-height:1.7;color:#374151">{analysis['summary']}</p>
      </div>
      <div style="display:flex;gap:12px;flex-wrap:wrap;margin-bottom:20px">{cards}</div>
      <div style="display:flex;gap:12px">
        <div style="flex:1;background:#f0fdf4;border:1px solid #bbf7d0;border-radius:10px;padding:16px">
          <p style="margin:0 0 8px;color:#15803d;font-size:11px;text-transform:uppercase;font-weight:600">
            Highlights</p>
          <ul style="margin:0;padding-left:18px">{highlights}</ul>
        </div>
        <div style="flex:1;background:#fef2f2;border:1px solid #fecaca;border-radius:10px;padding:16px">
          <p style="margin:0 0 8px;color:#dc2626;font-size:11px;text-transform:uppercase;font-weight:600">
            Watch</p>
          <ul style="margin:0;padding-left:18px">{concerns}</ul>
        </div>
      </div>
    </body></html>"""

Step 3 — Render to PDF and return the link

import os, requests

def generate_report(title: str, week: str, raw_metrics: list[dict]) -> str:
    analysis = analyse_metrics(raw_metrics)
    html = build_report_html(title, week, raw_metrics, analysis)

    r = requests.post(
        "https://www.agent-gen.com/api/v1/generate/pdf",
        headers={"X-API-Key": os.environ["AGENTGEN_API_KEY"], "Content-Type": "application/json"},
        json={"html": html, "format": "A4",
              "margin": {"top": "10mm", "bottom": "10mm", "left": "10mm", "right": "10mm"}},
        timeout=30,
    )
    r.raise_for_status()
    return r.json()["url"]

# Example
url = generate_report(
    title="AgentGen — Weekly Report",
    week="March 2, 2026",
    raw_metrics=[
        {"label": "Active Users", "value": "12,847", "change_pct": 8.3},
        {"label": "Revenue",      "value": "$48,200", "change_pct": 12.1},
        {"label": "Churn",        "value": "2.1%",    "change_pct": -0.4},
    ],
)
print(url)  # https://cdn.agent-gen.com/output/abc123.pdf

Automate with a cron job

Run this pipeline every Monday morning with GitHub Actions, Railway, or Vercel Cron. Fetch last week's data, call generate_report(), and Slack the PDF link to your team — all without touching a design tool.

A two-page report costs 4 tokens (~$0.06). For a 10-person team that's under $4/year in generation costs.

Where teams use this pattern

Internal reporting

Weekly executive summaries, sales snapshots, support metrics, and KPI packs are good fits because the narrative changes each period while the layout stays consistent.

Customer-facing reports

Agencies and SaaS teams use the same pattern for branded client deliverables where the model writes the summary but the PDF still needs a polished layout.

Ready to automate your reports?

50 free tokens on signup — enough for 12 full reports before you spend anything.