Gary: a voice agent that chases unpaid invoices
An AI phone agent for New Zealand small businesses, from empty repository to live product in four weeks.
Product
gogary.co.nzScope
Product design, full stack build, infrastructure, compliance
Timeline
Four weeks to a live, multi-tenant product
The problem
Small businesses do the work, send the invoice, and wait. Emailing a reminder is easy, so everyone does it. Almost nobody picks up the phone, and the phone is where the answers come out: the invoice went to the wrong person, it was never received, it is disputed, or it is simply forgotten.
Gary makes that call. It is a polite check-in, not a demand, and it reports what happened so the owner can act on it.
What we built
A multi-tenant SaaS product with a voice pipeline at its centre. The business connects its accounting system once, approves who may be called, and reads the results.
- Connect Xero. The business links its accounting org through an OAuth integration, and invoices sync on a schedule.
- Find and approve. Gary flags overdue invoices and holds them behind calling rules: business hours, do-not-call lists, amount thresholds, and a human approval step.
- Write the script. An LLM, routed through OpenRouter, drafts a call script tuned to the invoice and the business's tone.
- Make the call. An ElevenLabs conversational agent rings the customer over a Twilio number, opening with a recording disclosure.
- Handle the reply. Gary stores the recording and transcript, classifies the outcome, and triggers the follow-up: a resend, a calendar booking, or another number to try.
- Show the value. A dashboard tracks average days to payment and invoice collection rate over time, so the owner can see what changed.
Architecture
Backend
Django and Django REST Framework on Python, with Celery and Redis running the sync, call, and follow-up jobs. PostgreSQL holds the data, with an organisation key on every business row and tenant scoping enforced in the ORM layer.
Frontend
TypeScript and React with server-side rendering, a component library driven by design tokens, and a typed API contract generated from the backend's OpenAPI schema. Every page and component has a story and a visual regression snapshot.
Voice pipeline
ElevenLabs Conversational AI drives the call over a Twilio number, with the script generated per invoice through OpenRouter. Recordings go to object storage; transcripts and outcomes are scored and stored against the invoice.
Infrastructure
One repository, one infrastructure blueprint. Managed hosting for compute and data, staging and production environments, CI on every push, and uptime and error monitoring wired in from the first week.
Compliance built into the code
Automated collection calls are regulated in New Zealand. The rules are not a policy document sitting beside the product; they are gates in the calling path, and a call cannot go out without passing all of them.
- A recording disclosure in the agent's opening line
- Calling-hours limits, enforced server-side
- A per-organisation do-not-call and opt-out list, checked before every call
- A human approval step before the first call to any customer
- An audit log of every action that touches a customer
Security and data policies were written alongside the build, not after it: access control, incident response, data retention, and vendor management, aligned to SOC 2 expectations.
How we worked
Outside-in, test first. Every change starts at the boundary, an endpoint test or a component test, then builds inward. Business rules live in the model and service layer, not the view, so they can be tested without a browser or a phone line.
AI-accelerated development did the volume work: over a thousand commits in four weeks, each one reviewed, tested, and merged through CI. Claude ran inside the delivery loop, writing tests and implementations against the repository's own documented rules, which is how a single engineer shipped a product this size in a month.
Errors are loud by design. A failed sync never looks like an empty result, no completion marker is written for work that did not happen, and a broken integration surfaces in the user interface rather than in a log nobody reads. That rule came from a real defect: a silent failure in the accounting sync that read as a healthy sync of an organisation with no invoices.
Stack
Python, Django, Celery, Redis, PostgreSQL, TypeScript, React, ElevenLabs, Twilio, OpenRouter, Claude, Xero, and managed hosting on Render.
Want something like this built?
We build production web and AI applications for startups and small businesses. Tell us what you are trying to ship.