How we process vendor invoices the moment they arrive

Invoices show up in the inbox whenever vendors feel like sending them, and every one asks for the same routine. Open the PDF. Note who sent it, how much, and what the lines are. Find the purchase order. Make sure it isn't a copy of something you've already logged. Confirm the price matches the deal. That's about five minutes of close reading per invoice, and those five minutes are exactly where double bills and inflated prices sneak past. Not because anyone is sloppy, but because no one can hold every past invoice and every open PO in their head on a busy afternoon.
So an agent on Machine does it for us. Every 15 minutes it looks in the inbox, reads each new invoice, checks it against our POs and the payables ledger, and posts it in Slack for approval, with a flag if it's a duplicate, an overcharge or has no PO. It keeps the books. It doesn't pay.
The problem
On its own, an invoice tells you nothing beyond a total. You only know if it's correct by holding it up against records kept somewhere else: the PO that approved the spend, the agreed price, and every earlier invoice from the same vendor in the ledger. Someone working through a stack by hand covers the obvious questions (does a PO exist, does the total look sane). The checks that really catch trouble, such as a vendor sending last month's bill again or nudging a line item up a few percent, are the first to go when the inbox is full and the day is nearly over.
Popular shortcuts don't solve it. Paying whatever comes in catches nothing at all. Reviewing in a monthly batch does find duplicates and overcharges, but only later, and sometimes after the money has left. Neither tests each invoice against all the POs and all the past invoices the minute it lands.
What we built
A timer on Machine fires every 15 minutes, and each time it opens a fresh session: a new cloud computer (a sandbox) with no memory of the previous run. That's on purpose, because the payables ledger in Google Sheets is the record. The agent checks a Gmail label for new invoice emails and pulls the vendor, amount and line items out of each attachment. It compares them with the known POs and earlier invoices tracked in the sheet, flags any duplicate, overcharge or missing PO, and writes every invoice into the ledger. Then the batch goes to Slack, where a person approves it. Scheduling a payment or marking anything as paid is never part of the agent's job.
How it works
Start clean every 15 minutes
A cron trigger (a timer) wakes the agent every 15 minutes, and each wake-up creates a brand-new session in its own sandbox. The agent keeps nothing in its own head between runs. The Google Sheets ledger provides the continuity instead: each run reads it first, so duplicates and overcharges are always judged against one shared record.
Hand it your payables rulebook
The way we read, match and flag invoices is written down as a skill, a playbook loaded into each session. It defines what a duplicate is, how far a line item may stray from the agreed price before it's an overcharge, and what to do when there's no PO to match. So every invoice is held to one standard, rather than whatever seems sensible that day.
Connect the inbox, the ledger and Slack
The agent uses connectors: scoped connections to your tools, with keys held on the server so the model never handles a raw token. Through them it can:
- Read Gmail: fresh invoice emails, attachments included, in the label it watches.
- Read the Google Sheet and add rows to it: the POs and ledger it checks against, plus a new row for each invoice it logs.
- Post in Slack: the processed batch, clean and flagged alike, ready for sign-off.
Keep money movement with people
The agent writes exactly two things: new rows in the payables ledger and a Slack message. It can't reach any payment system, and nothing in its instructions lets it schedule an invoice or mark one paid. A person always does that, even when the match is perfect. Credentials are stored encrypted in the Secrets Manager and only handed to the agents you grant them to.
Approve the batch in Slack
The result: every 15 minutes, new invoices are already read, matched and logged before anyone opens Slack. Each is labelled clean, duplicate, overcharge or missing PO, with links to the PO and any earlier invoice it relates to. Someone reviews the batch and approves payment through your normal payables process. The agent's work stops at the Slack message.
The pattern
A cron every 15 minutes opens a fresh session, and the Google Sheet ledger acts as its memory. Through connectors the agent reads Gmail, matches each invoice against POs and earlier invoices, logs everything in the sheet and posts the batch to Slack. A person, never the agent, schedules a payment or marks one paid.
Guardrails
Payables is where a slip costs actual money, so the agent's reach is kept small:
- Isolation. Each run gets its own sandbox. The session can reach only Gmail, the payables sheet and Slack, and nothing else leaves it.
- Scoped secrets. The Gmail, Sheets and Slack credentials are stored encrypted in the Secrets Manager, delivered into the sandbox when the run starts, and only handed to the agents you grant them to.
- No payment action, ever. There's no connector, tool or instruction that lets the agent schedule a payment or mark an invoice paid. Clean or flagged, every invoice goes to a person for that call.
- Flag, don't discard. Duplicates, overcharges and invoices without a PO get logged and flagged in the ledger. None are quietly dropped, and none are approved automatically.
- Everything is code. The matching rules, the skill and the permissions for each system are files in your repo. They're versioned, and you change them through a reviewed change request, not a dashboard toggle.
The outcome
The five minutes of careful reading each invoice used to wait for now happen on their own, four times an hour, against the full ledger history instead of someone's memory. Invoices that once reached the payment step without a proper check now arrive flagged, with the clashing PO or earlier invoice already linked. And the decision to pay hasn't moved an inch: a person still makes it.
More use cases
How we answer GDPR data-subject requests before the deadline
Our Machine agent checks each GDPR access or deletion request, finds the person's data across our product database, builds the report well within the SLA and hands it to legal before anything is sent.

How we keep our docs matching what the code does
Once a day a Machine agent reads every commit merged since its last pass, finds the doc pages those changes made wrong, rewrites them and sends you one pull request to review.

How we test every pull request without lifting a finger
Our Machine QA agent works with GitHub and our test environment. For each pull request it checks out the branch, runs the tests, tries the change for real, and posts what it found.
Put your first agentto work today.
- SSO
- RBAC
- Governed agents
- Full audit trail