·10 min read
How to Build an Invoicing Agent with GPT-4o and AgentGen
Last Updated: March 2026
TL;DR
- GPT-4o collects invoice details in conversation using function calling
- AgentGen renders the HTML template to a polished PDF via headless Chrome
- The user gets a CDN download link in the same conversation turn — 2 tokens (~$0.03)
What we're building
A conversational invoicing agent. The user says something like: "Invoice Acme Corp, $5,000 for consulting, due April 15" — and the agent asks any missing questions, then produces a professional PDF invoice and returns the download link.
Setup
pip install openai requests python-dotenv
You need an OpenAI API key and an AgentGen API key. Get your AgentGen key free — new accounts get 50 tokens.
Step 1 — The invoice HTML template
def build_invoice_html(data: dict) -> str:
rows = "".join(
f"""<tr>
<td style="padding:8px 0;border-bottom:1px solid #f3f4f6;color:#374151">
{item["desc"]}
</td>
<td style="padding:8px 0;text-align:right;border-bottom:1px solid #f3f4f6">
{item["qty"]}
</td>
<td style="padding:8px 0;text-align:right;font-weight:600;border-bottom:1px solid #f3f4f6">
${item["qty"] * item["unit_price"]:.2f}
</td>
</tr>"""
for item in data["line_items"]
)
subtotal = sum(i["qty"] * i["unit_price"] for i in data["line_items"])
return f"""<!DOCTYPE html>
<html><head><meta charset="UTF-8"></head>
<body style="font-family:'Helvetica Neue',sans-serif;padding:48px;color:#111;max-width:680px">
<div style="display:flex;justify-content:space-between;align-items:start;margin-bottom:40px">
<div>
<h1 style="margin:0 0 4px;font-size:28px;font-weight:800">INVOICE</h1>
<p style="margin:0;color:#6b7280">#{data["number"]}</p>
</div>
<div style="text-align:right">
<p style="margin:0;font-weight:600">{data["issuer"]}</p>
<p style="margin:0;color:#6b7280;font-size:14px">{data["date"]}</p>
</div>
</div>
<p style="color:#6b7280;font-size:13px;margin-bottom:4px">Bill to</p>
<p style="font-size:18px;font-weight:700;margin:0 0 32px">{data["client"]}</p>
<table style="width:100%;border-collapse:collapse;margin-bottom:24px">
<thead>
<tr style="border-bottom:2px solid #e5e7eb">
<th style="text-align:left;padding-bottom:8px;font-size:12px;color:#9ca3af;text-transform:uppercase">Description</th>
<th style="text-align:right;padding-bottom:8px;font-size:12px;color:#9ca3af;text-transform:uppercase">Qty</th>
<th style="text-align:right;padding-bottom:8px;font-size:12px;color:#9ca3af;text-transform:uppercase">Amount</th>
</tr>
</thead>
<tbody>{rows}</tbody>
</table>
<div style="display:flex;justify-content:flex-end">
<div style="min-width:200px">
<div style="display:flex;justify-content:space-between;padding:6px 0;color:#6b7280;font-size:14px">
<span>Subtotal</span><span>${subtotal:.2f}</span>
</div>
<div style="display:flex;justify-content:space-between;padding:12px 0 0;font-size:20px;font-weight:800;color:#4f46e5;border-top:2px solid #e5e7eb;margin-top:6px">
<span>Total</span><span>${subtotal:.2f}</span>
</div>
</div>
</div>
<p style="margin-top:40px;color:#9ca3af;font-size:12px">
Payment due: {data["due_date"]} · Thank you for your business.
</p>
</body></html>"""
Step 2 — The AgentGen tool function
import os, json, requests
def create_invoice(
client: str,
number: str,
date: str,
due_date: str,
issuer: str,
line_items: list[dict],
) -> dict:
"""Render an invoice PDF and return a download URL. Cost: 2 tokens."""
html = build_invoice_html({
"client": client, "number": number,
"date": date, "due_date": due_date,
"issuer": issuer, "line_items": line_items,
})
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"},
timeout=30,
)
r.raise_for_status()
return {"pdf_url": r.json()["url"]}
Step 3 — Define the OpenAI tool schema
tools = [{
"type": "function",
"function": {
"name": "create_invoice",
"description": (
"Generate a professional PDF invoice and return a download URL. "
"Call this once you have all required invoice details."
),
"parameters": {
"type": "object",
"properties": {
"client": {"type": "string", "description": "Client or company name"},
"number": {"type": "string", "description": "Invoice number, e.g. INV-001"},
"date": {"type": "string", "description": "Invoice date, e.g. March 2, 2026"},
"due_date": {"type": "string", "description": "Payment due date"},
"issuer": {"type": "string", "description": "Your name or company name"},
"line_items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"desc": {"type": "string"},
"qty": {"type": "number"},
"unit_price": {"type": "number"},
},
"required": ["desc", "qty", "unit_price"],
},
},
},
"required": ["client", "number", "date", "due_date", "issuer", "line_items"],
},
},
}]
Step 4 — The agent loop
from openai import OpenAI
client = OpenAI()
def run_invoicing_agent(user_message: str) -> str:
messages = [
{
"role": "system",
"content": (
"You are an invoicing assistant. Collect all required invoice details from "
"the user (client name, services, amounts, due date, your name/company), "
"then call create_invoice to generate the PDF. "
"If any details are missing, ask for them before generating."
),
},
{"role": "user", "content": user_message},
]
while True:
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto",
)
msg = response.choices[0].message
if msg.tool_calls:
messages.append(msg)
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = create_invoice(**args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result),
})
else:
return msg.content
# Run it
print(run_invoicing_agent(
"Invoice Acme Corp $5,000 for API consulting, due April 15. My name is Yair Levi."
))
# → "Here's your invoice: https://cdn.agent-gen.com/output/abc123.pdf
# Invoice #INV-001 · Acme Corp · Due April 15, 2026 · $5,000.00"
Cost
Each invoice costs 2 tokens (~$0.03 at Growth tier). The GPT-4o API call is a few cents on top. Total round-trip is under 3 seconds.
Get started free → — 50 tokens on signup, enough for 25 invoices to test your workflow.
Ready to start generating?
Create a free account and generate your first PDF or image in minutes.
Get started free