AI & automation8 min read · Updated 8 September 2026

Automate Invoice Intake Without Sending Anything to the Cloud

Invoice processing is the textbook case for a local agent: repetitive, rule-heavy, arithmetic-critical, and full of data you would rather not hand to a third party.

Automate Invoice Intake Without Sending Anything to the Cloud

Supplier invoices are the most common thing people want to automate and the most common thing they should not hand to a cloud service. They contain your suppliers, your prices, your margins and your payment terms, and they arrive as PDFs that need reading rather than parsing.

This walkthrough builds the smallest honest version: read from a folder, extract fields, verify the arithmetic in a deterministic engine rather than a model, and escalate anything that does not add up. It is deliberately not a system that pays invoices.

The shape

Local invoice intake: a watched folder feeds extraction, arithmetic verification against the purchase order, then either a booked entry or a human review queueINBOX, EXTRACT, ARITHMETIC, MATCH PO, DECIDE, BOOKED, REVIEW. folder → extract; extract → calc (totals); extract → po (supplier); calc → decide; po → decide (variance); decide → booked (clean); decide → human (anything odd).totalssuppliervariancecleananything oddINBOXwatched folderEXTRACTfields · linesARITHMETIClocal engineMATCH POfrom memoryDECIDErulesBOOKEDwith evidenceREVIEWa person
Note where the arithmetic sits: in its own box, off the model’s path. The model reads the document; it never decides what the total is.

The skill

One SKILL.md, with the rules that matter written as instructions the model cannot talk itself out of. The three constraints at the bottom are the difference between something you can defend to an auditor and something you cannot.

skills/invoice-intake/SKILL.md
---name: "Invoice Intake"slug: "invoice-intake"version: "2026.1"triggers: ["invoice", "supplier", "bill", "racun"]moduleType: "calc"domains: ["admin", "finance"]outputSchema: type: object required: [supplier, netMinor, vatMinor, grossMinor, verdict] properties: supplier: { type: string } invoiceNo: { type: string } netMinor: { type: integer } vatMinor: { type: integer } grossMinor: { type: integer } verdict: { type: string, enum: [book, review] } reason: { type: string }---Read one supplier invoice from the workspace and return the fields above.Hard rules:- Amounts are integers of the smallest currency unit. Never emit a float.- Do not compute or check any total yourself. Call the calculation tool and use what it returns, including for the VAT line.- If the arithmetic does not reconcile, if the supplier is unknown, or if any required field is missing or ambiguous, return verdict: review with a reason. Never guess a value to make the document balance.
  • integers only
  • arithmetic delegated
  • "review" is a first-class outcome

Run one through

Start with dryRun: true. It routes the message and performs the calculation without calling a model at all, which is exactly what you want while you are still checking that the maths is right.

processing one invoice
# the file is inside fsRoot; anything outside it is refused$ curl -s -X POST http://127.0.0.1:18790/tools/run \>   -H "Authorization: Bearer $(cat ~/.clerq/gateway-token)" \>   -H "Content-Type: application/json" \>   -d '{"tool":"fs.read","input":{"relativePath":"inbox/2026-09/INV-4471.txt"}}'{"path":"/Users/you/clerq-workspace/inbox/2026-09/INV-4471.txt","bytes":2184,…}$ curl -s -X POST http://127.0.0.1:18790/task \>   -H "Authorization: Bearer $(cat ~/.clerq/gateway-token)" \>   -H "Content-Type: application/json" \>   -d '{"message":"process invoice INV-4471","dryRun":true}'{"dryRun":true,"matchedSkill":"invoice-intake", "calculation":{"netMinor":120000,"vatMinor":30000,  "grossMinor":150000,"engine":"local"}, "llm":{"called":false,"reason":"dryRun"}}# a document that does not reconcile does not get booked$ curl -s -X POST http://127.0.0.1:18790/task -H "Authorization: Bearer $(cat ~/.clerq/gateway-token)" \>   -H "Content-Type: application/json" -d '{"message":"process invoice INV-4472","dryRun":true}'{"verdict":"review","reason":"gross 1512.00 != net 1200.00 + vat 300.00"}

What to keep a person for

  • Anything that does not reconcile. No exceptions, no tolerance band that quietly swallows small errors.
  • New suppliers. First invoice from anyone is a review, always. This is also the control that catches invoice fraud.
  • Payment itself. Extraction and checking can be automated; authorising money leaving the company should not be.
  • Anything the model flagged as ambiguous. A skill that never returns "review" is not being honest with you.

If you have not run the agent yet, start with the quickstart. Before you point it at real invoices, read how to secure it — this is the tutorial where it starts touching documents that matter.

Key takeaways

  • Invoices are a strong local-agent case: repetitive, rule-heavy, arithmetic-critical, commercially sensitive.
  • The model reads the document; a deterministic engine does every calculation. Never blur that line.
  • Amounts are integers of the smallest currency unit, end to end. Floats belong nowhere near money.
  • "Review" must be a first-class outcome, and new suppliers should always land in it.
  • Automate extraction and checking. Do not automate paying.

Frequently asked questions

Can it read PDFs, not just text?

The built-in fs.read tool reads UTF-8 text. For PDFs you add an extraction step in front of it — locally, with something like a local OCR or PDF text layer extractor — so the document still never leaves the machine.

How accurate is the extraction?

Accurate enough to be useful and never accurate enough to trust unattended, which is why the design routes anything doubtful to a person. Measure it on your own invoices before you decide the volume you are comfortable with.

Can this post entries into our accounting system?

Technically yes, through an allow-listed HTTP call. Whether it should is a different question — most teams start with the agent producing a reviewed batch that a person imports, and only automate the write once the review queue has been boring for a few months.

Want one of these built for your own workflow?

OpenClerq is open source and yours to run. If you would rather not build the module yourself, tell us what the work actually looks like and we will scope one — or tell you honestly that an off-the-shelf tool does it better.

Describe the workflow

A couple of sentences is enough to get a straight answer.

  • Fixed-scope quote — no obligation
  • Reply within 1 business day

By sending this, you agree that we may contact you about this inquiry.

Prefer to talk first? Reach us directly:WhatsApp+44 7400 733 299Contact page
private AI deployment

About the author

Paxa Media

Written by the Paxa Media delivery team — the same developers, marketers and strategists who build these systems for clients. We are a technology company based in Rijeka, Croatia, and we publish the real numbers we quote rather than "it depends".

Why you can trust this

  • Builds and operates the systems described here — websites, web and mobile apps, automation and integrations
  • Delivered by an in-team staff in Rijeka, Croatia; no outsourced or resold work
  • Price ranges published here are the ranges we actually quote

Keep reading

All tutorials
AI & automation

Write Your First OpenClerq Skill: One Markdown File

A skill is a Markdown file with frontmatter. Here is the smallest one that does something useful, and how to check the routing actually works.

CRM & systems

Business Process Automation: From Spreadsheet Chaos to a System

Every growing business hits the point where spreadsheets and manual steps start dropping the ball. Automation is how you turn that chaos into a reliable system.

AI & automation

How to Secure a Local AI Agent: Token, Loopback, File Roots, Allow-Lists

"It runs locally" is not a security model. Four controls decide what an agent on your machine can actually reach — and all four have sensible defaults you should still check.