← All posts
·8 min read

Building an Invoice Generator with an AI Agent

Imagine telling your AI assistant: "Generate an invoice for Acme Corp, $5,000 for consulting, due March 15." — and getting back a professional PDF download link. That's what we're building in this tutorial.

Architecture

The system has three parts:

  1. A conversational LLM that collects invoice details
  2. A create_invoice tool that templates and renders the PDF
  3. AgentGen API to perform the actual HTML → PDF conversion

Defining the tool schema

const tools = [{
  name: 'create_invoice',
  description: 'Generate a professional PDF invoice and return a download URL.',
  input_schema: {
    type: 'object',
    properties: {
      client_name: { type: 'string', description: 'Client or company name' },
      invoice_number: { type: 'string' },
      due_date: { type: 'string', description: 'ISO date YYYY-MM-DD' },
      line_items: {
        type: 'array',
        items: {
          type: 'object',
          properties: {
            description: { type: 'string' },
            quantity: { type: 'number' },
            unit_price: { type: 'number' },
          },
        },
      },
      currency: { type: 'string', default: 'USD' },
    },
    required: ['client_name', 'invoice_number', 'due_date', 'line_items'],
  },
}]

Implementing the tool handler

async function handleToolCall(toolName, input) {
  if (toolName !== 'create_invoice') return null

  const total = input.line_items.reduce(
    (sum, item) => sum + item.quantity * item.unit_price, 0
  )

  const html = buildInvoiceHtml({ ...input, total })

  const res = await fetch('https://www.agent-gen.com/api/v1/generate/pdf', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.AGENTGEN_API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      html,
      format: 'A4',
      margin: { top: '15mm', bottom: '15mm', left: '15mm', right: '15mm' },
    }),
  })

  const { url } = await res.json()
  return { pdf_url: url, total }
}

Running the agent loop

async function runInvoiceAgent(userMessage) {
  const messages = [{ role: 'user', content: userMessage }]

  while (true) {
    const response = await anthropic.messages.create({
      model: 'claude-opus-4-6',
      max_tokens: 1024,
      tools,
      messages,
    })

    if (response.stop_reason === 'tool_use') {
      const toolUse = response.content.find(b => b.type === 'tool_use')
      const result = await handleToolCall(toolUse.name, toolUse.input)

      messages.push(
        { role: 'assistant', content: response.content },
        { role: 'user', content: [{ type: 'tool_result', tool_use_id: toolUse.id, content: JSON.stringify(result) }] }
      )
    } else {
      return response.content[0].text
    }
  }
}

Result

Running runInvoiceAgent("Invoice Acme Corp $5000 consulting due March 15") produces:

I've generated your invoice. Download PDF
Invoice #001 · Acme Corp · Due March 15, 2026 · Total: $5,000.00

The whole round-trip takes under 3 seconds and costs 2 tokens (~$0.03 at Growth tier).

Get started — you can have this running in an afternoon.

Ready to start generating?

Create a free account and generate your first PDF or image in minutes.

Get started free