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
LLM stage
Claude or GPT-4o reads raw metrics, writes an executive summary, and identifies highlights and concerns.
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.pdfAutomate 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.