All postsArchitecture
Data Contracts for ERP Exports
An AI model will read a changed data file without complaint, which is exactly why it must never be the thing that checks data coming in from another system. The written agreement we check every delivery against: shape, meaning, completeness, timing and owner, with a failed delivery held back whole instead of repaired, and an agreement that later becomes the brief for replacing the system.
The match rate of a finance workflow fell sharply one Monday morning, and nothing had failed. A weekend update to the ERP, the company's core business system, had switched the date format in one export file from day-first to month-first. The file covered the first nine days of March, so every date still read as valid. Just wrong. Invoices were matched against goods receipts from the wrong month, at full speed.
Past the twelfth, rows would have failed and someone would have looked within minutes. The silent version needed a calendar coincidence, and across enough files and upgrades, such coincidences stop being rare. The fix took an hour. Finding it took most of a day, because nothing in the design assumed a file could change its meaning without changing its shape.
Every AI workflow depends on data nobody promised to keep stable. The ERP can't sign an agreement, so we write one and enforce it on every delivery. Ian Robinson described consumer-driven contracts on Martin Fowler's site in 2006: the side using the data states what it relies on, and the sender tests against it. An old ERP runs nobody's tests, so the receiving side enforces alone, and must pick a part strict enough to do it.
AI models are too forgiving to be the check
AI models cope with a renamed column or a new date format. At a system boundary, that's a liability. Ordinary code that meets a changed file stops, and someone looks. A model gives a plausible answer and moves on, and the error surfaces weeks later, when the books are checked, far from its cause. So the entry point is the least forgiving part of the system. A model may read a document's content; it doesn't decide what an export's columns mean.
Jon Postel's 1980 rule, be liberal in what you accept, suits free text. Between systems, as Martin Thomson and David Schinazi showed in RFC 9413 (2023), a tolerant receiver hides the sender's mistakes until they become the format. An AI model is the most tolerant receiver ever put to work: every ERP change becomes a format only it understands, until it misunderstands one.
What the agreement covers
Most teams write down the first of these five and forget the rest.
Shape. Fields, types, mandatory values, one date format, a declared decimal separator and sign convention.
Meaning. What each field represents, per source: whether "posting date" is the document date or the entry date in this market; whether credit notes arrive negative or positive with a document type. Same shape, different meaning: that's where multi-market data breaks.
Completeness. How many records should arrive and what they add up to, with totals from outside the export, such as the ERP's own open-items report or the bank statement's totals. A delivery perfect in shape and missing a hundred rows is the most dangerous kind, so we keep this check even for sources that "never lose rows". They all do, on a day nobody is looking.
Timing. When it lands, which period it covers, what happens to records entered after the cut-off. Reading before the warehouse records its receipts creates exceptions that are really lateness.
Ownership. Who approves a change to the export, and how we hear. Without it, the agreement is read only after the incident.
In practice it's one versioned page per export.
Hard checks stop, soft checks raise a hand
Shape and completeness are hard checks: a failed delivery goes no further. For meaning we add two softer ones.
The first compares each delivery with recent weeks: share of credit notes, spread of amounts, number of distinct suppliers, how dates fall across the month. The date switch left a fingerprint: read day-first, every March date landed on the third of some month, because the day field held the month number. A check on the spread of days would have flagged the first file before a single match. Since real business changes move these numbers too, they don't stop a delivery; they put a named person in front of it.
The second is a handful of known records, checked every run. If a known supplier's known invoice suddenly reads a different date or amount, the meaning has changed though the shape hasn't.
A failed delivery is held back whole
The agreement is code. A failed delivery isn't partly processed or repaired by guesswork, however obvious the fix: silent obvious fixes turn one wrong assumption into a month of wrong entries. It's held back with a reason, and a named person is told. A held delivery costs an hour; a misread one costs days and, in finance, a correction trail the auditors will ask about.
Holding back also moves the cost of a change to whoever can prevent it. If the receiving side quietly absorbs changes, nobody upstream learns an upgrade broke something, and the next one does the same. We report held deliveries to each export's owner monthly. The number falls once changes start arriving with notice.
The cost: one bad row holds up hundreds of good ones. We accept that for anything that writes to the accounts. Read-only uses, like a dashboard or a work queue, may reject single rows, as long as they're counted against the control totals.
Every source gets its own agreement
When we connected four European markets for Bredent Medical, each on Dynamics 365 or an older system, there was no single ERP agreement. One connecting layer sat in front of all four, with an agreement per source and a mapping per market into one shared model that stayed trustworthy as each market kept changing. Every new market is a new source and should arrive with its agreement.
Bank statement files (MT940, ISO 20022 camt.053) need an agreement per bank and account type too: their references and dates decide matching quality, and banks change field usage as they switch formats.
Changes run in parallel and are tested with broken files
A planned change follows the parallel change pattern Danilo Sato described on Martin Fowler's site in 2014: new and old run side by side through a month-end, then the old one goes. A change that can't run in parallel starts with the strictest hold-back setting.
Each agreement ships with good sample files and deliberately broken ones: a renamed field, a changed date format, missing rows, a wrong total. The check must accept the first and reject all the second, on every change. Before an ERP upgrade, the client's team runs a test export through it and knows within minutes what breaks.
We also agree one line with the client's IT and ERP partner: a change to an export that feeds a workflow goes through the same change process as the workflow.
The agreement outlives the ERP
Most of our clients will replace or upgrade their ERP within a few years. The hardest part is learning which fields, meanings and schedules every downstream process relies on. With these agreements, that list exists, tested and versioned. The agreement written to protect one AI workflow becomes the migration specification, and the broken-file tests become the acceptance tests for the new system's exports.
Most of what makes an AI workflow reliable happens before the model sees anything. An agreement doesn't stop exports changing. It makes the change loud, and loud failures get fixed in an hour. Silent ones get found by the auditor.