Skip to content
opsveraopsvera
Engineering
2026-07-28 · 3 min read

Idempotency is the boring feature that makes agents trustworthy

Why "can this create the same order twice" is the first question worth asking any vendor, and what a real answer looks like.

Every demo you will see this year shows the happy path. A document arrives, the agent reads it, the record appears in the system. Impressive, and almost irrelevant — because the happy path is not where automation hurts you.

It hurts you the second time.

The question that separates a demo from a system

Ask any vendor this: if the same purchase order arrives twice, what happens?

Documents arrive twice constantly, and almost never because anything went wrong. A supplier resends because they did not get an acknowledgement. Someone forwards the original into the shared inbox so a colleague can see it. A retry fires after a timeout, when the write had already landed. A sync job replays a window of messages after a brief outage.

None of that is exotic. It is a normal Tuesday in an operations inbox.

If the answer involves a person noticing, the system is not safe. It is safe right up until the day somebody is on holiday.

What idempotency actually means here

An idempotent operation produces the same result however many times you apply it. Written down like that it sounds like a maths definition with no bearing on your accounts payable process. In practice it is the difference between an agent you can leave running and one you have to supervise.

Concretely: the agent computes a stable key for every input before it does anything with it. Not a hash of the whole file, which changes when a mail server re-encodes an attachment. Something durable that identifies the business event — the message id, the supplier's own document reference, the invoice number and vendor together.

Then, before any write, it checks whether that key has already been processed. If it has, the correct behaviour is to do nothing and say so.

An agent that quietly does nothing, and tells you it did nothing, is worth more than one that quietly does something twice.

Where the naive version breaks

Most first attempts check for duplicates by searching the target system. Does an order already exist for this reference? If not, create one.

That works until two copies arrive close together. Both check, both find nothing, both create. The window is small — often under a second — and it is exactly the window a resend-after-timeout lands in.

The fix is not a longer check. It is making the key itself the thing that enforces uniqueness, at the layer that can actually guarantee it: a unique constraint in the database, so the second write fails as a matter of physics rather than as a matter of timing. The agent catches that failure and treats it as success, because the desired end state — one order — already holds.

What to ask a vendor about duplicates

  1. 01What exactly is the key, and what happens if the sender changes the subject line
  2. 02Where is uniqueness enforced — application code, or a database constraint
  3. 03What does the agent do when it detects a duplicate, and where is that recorded
  4. 04What happens if the write succeeds but the acknowledgement is lost

That last one is the interesting case, and the one most systems get wrong. If a write lands and the response never comes back, the agent does not know whether it succeeded. Retrying is unsafe unless the operation is idempotent. Not retrying risks losing the work. With a stable key, the retry is free: it either completes the write or discovers it was already done.

Why this is the first question, not a detail

Reliability engineering has a rhythm to it. You handle the happy path, then the error path, then the ambiguous path — the one where you genuinely cannot tell what happened. Most of the cost lives in the third.

Back-office automation has skipped that rhythm for years, because the tools were built to demo well rather than to run unattended. The result is a category full of systems that work beautifully until the first duplicate, and then produce a problem that is worse than the manual process they replaced: a wrong quantity on a real order, found weeks later by someone reconciling a statement.

We build the key and the constraint before we build the extraction. It is the least impressive part of the work and the reason anything else is safe.

It is not a setting

One more thing worth checking. If duplicate protection appears in a configuration screen as a toggle, it was added afterwards, and there will be paths around it. It should be a property of how writes happen at all — something you cannot turn off, because nothing in the system knows how to write any other way.

Boring, invisible when it works, and the only reason you can stop watching.