Addaly is in open beta. Things will change, and AI answers can be wrong — check anything that matters.

Build the boring version first

Agents and Automation · lesson 8 of 8 · 9 min

A real task

A building-supplies business in Lagos receives about sixty supplier invoices a month as PDF attachments. Someone opens each one and retypes eight fields into a spreadsheet. It takes four hours a month and the errors are silent until reconciliation.

The tempting design: an agent with an email tool, a PDF tool and a Sheets tool, told "keep the invoice sheet up to date."

Don't. Here is the design that survives.

The pipeline

1. Trigger — new email arriving in a labelled inbox. Deterministic. Gmail push, n8n, Zapier, whatever you already run.

2. Filter — is there a PDF attachment under 10 MB from a known supplier domain? Deterministic. An if statement. Everything else goes to a human folder, unopened.

3. Extractone model call. PDF in, strict JSON out:

json
{
  "supplier": "string",
  "invoice_number": "string",
  "date": "YYYY-MM-DD",
  "currency": "NGN | USD | EUR",
  "subtotal": 0.00, "tax": 0.00, "total": 0.00,
  "line_items": [{ "description": "string", "qty": 0, "unit_price": 0.00 }]
}

4. Validate — deterministic, and this step is where the reliability actually comes from:

python
assert round(subtotal + tax, 2) == round(total, 2)
assert sum(li.qty * li.unit_price for li in line_items) == subtotal
assert date <= today and date > today - 400_days
assert invoice_number not in already_seen
assert supplier in known_suppliers

Five lines of arithmetic catch most of what the model gets wrong on this task, and they cost nothing.

5. Route — passes → append the row. Fails → a review queue showing the PDF and the extracted JSON side by side, with the failed assertion named.

6. Report — a weekly summary of what went to review and why, so nobody has to watch it to trust it.

Count the model calls. One. Everything else is a workflow. This is the shape of almost every automation that is still running six months later.

Keep a golden set

Before you change the prompt, the model, or anything else: take thirty real invoices, hand-check the correct answer for each, and store them. Every change re-runs against those thirty. Without this you are not improving the system, you are moving it around and hoping.

Thirty is enough to notice a regression. It is not enough to certify anything, and that is fine — you are catching the change that took totals from 94% to 71%, which is the failure that actually happens.

So when is an agent the right answer?

Use a script or workflow when:

  • the steps are the same every time, even if there are thirty of them
  • you can write the validation
  • a wrong answer costs money or is hard to undo
  • somebody will eventually ask you to explain why it did what it did

Use an agent when all three hold:

  • the number and order of steps genuinely depends on what it finds partway through
  • you can afford to be wrong sometimes, or a human reviews the output
  • there is a cheap, independent check on the result

That third condition is the one people skip, and it is what makes agents work at all. "Independent" means the check does not come from the same model that produced the answer. Arithmetic that must balance. A record that must exist. Code that must compile and pass tests — which is precisely why coding agents work better than most other agents, and it is not because code is easy.

The honest closing position

Models keep getting better, and each improvement multiplies through the chain, which is real and worth having. What does not change is the arithmetic: chained steps compound, self-assessment is not measurement, and irreversible actions stay irreversible.

So build the boring version first. One model call in the middle of a deterministic pipeline, with a validator, a queue, and a golden set. Measure it. Then add autonomy at exactly the points where the boring version demonstrably cannot reach — and no further.

Before you move on

On the invoice pipeline, extraction gets totals right 94% of the time. Two proposals: (a) wrap extraction in an agent loop that re-reads the PDF and self-corrects, or (b) add the arithmetic check and route mismatches to a human queue. Why is (b) the better way to catch wrong totals?

Pick the one you would defend. Nobody sees your answer.

No ads. No data sale. No public scores on people. Ever.

© 2026 Addaly