Most invoice automations I see in here are parsers: read the PDF, pull the fields, drop it in a sheet. I built a chaser instead, the follow-up side: who to chase, when, and how hard. The split: 1. Ingest: (Gmail + Airtable + Claude Haiku 4.5). The owner forwards an invoice, Haiku reads the PDF and the fields land in Airtable. Bad scans or missing fields get flagged for review instead of guessed at, and duplicates attach to the existing record rather than making a second one. 1. Decide and draft (a daily cron): This is the important one, and it has no LLM in the decision. A deterministic state machine looks at each overdue invoice (client tier, days overdue, history, how many chases already went out) and returns exactly one action: chase, wait, or escalate. Only after that does an LLM draft the wording, tone-matched to the situation. The model writes the email. It never decides whether to send. 3. Send (one-click approval): The owner approves in Airtable, n8n sends via Gmail with the invoice PDF attached. On every send it also grabs that email's Message-ID and stores it, which matters for the next part. 4. Understand replies (Gmail trigger): When the client writes back, this workflow works out which invoice the reply belongs to and what it means (payment, promise to pay, dispute, question, or unrelated), updates the status, and drafts a response for approval. One note on that first step: parsing an emailed PDF is just one way in. The same pipeline could pull invoices straight from a Xero or QuickBooks API instead of reading a PDF. I started with email because it works for anyone, whatever they invoice with. The part that took the most fiddling was step 4: matching a reply back to the right invoice. I do it by email header, not by AI. When workflow 3 sends a chase,it stores that email's RFC Message-ID. When a reply comes in, workflow 4 matches its In-Reply-To and References headers against the stored ID. Two things I learned the hard way: - Gmail's send response does not hand you the real Message-ID. You have to make a second call to fetch the sent message and read the header off it.