EDI Copilot
Redaction design · Agent refusal · Supply chain EDI
A compliance check that took up to fifty minutes, done in eight.
EDI CopilotThen I handed my own redacted file to a stronger model and asked it to name the customer. It did.
- Up to 6× faster
- 30 to 50 minutes by hand, 8 with the tool(Client-stated and measured)
- 2,375 values masked, 0 sent
- swapped out before the prompt exists(Measured)
- 6 of 8 stages call no model
- by rule, not by prompt(Measured)
- Status
- A live pilot on a deployed server. Full rollout waits on client approval and resource allocation.
- My role
- Every architecture, redaction, evaluation and product decision. I wrote none of the code by hand.
The six decisions
- 01
I decided what the AI is never allowed to see, before I built anything.
A leaked customer name here is not a bug, it is a breached contract. So I made exposure structurally impossible rather than unlikely. Every sensitive value in both files becomes a token before the prompt is assembled, and six of the eight stages never call a model at all.
Result: 7,724 differences analysed, 2,375 confidential values masked, none of them sent(Measured).
- UploadHuman
- ParseNo model call
- CompareNo model call
- MaskBoth documents are tokenized before the prompt is assembledNo model call
- ApproveNothing is sent until a person approves the exact payloadHuman, mandatory
- AnalyzeOne prompt contract, rows in batches of twentyThe only model stage
- UnmaskLocally, against a mapping the model never seesNo model call
- ReviewHuman
Barred, permanently, by rule
- Delimiter detection
- Parsing
- Difference classification
- Barcode validity
No model anywhere in these. Barcode validity is checksum arithmetic. Unmasking runs locally against a mapping the model never sees.
- 02
I masked by pattern first, and it broke my own model's input.
My first pass hid anything shaped like a code. "or" is Oregon, "in" is Indiana, so both vanished from the rulebook's own sentences, taking the structure the model needed with them. The verdicts got worse. I now mask by position in the record, never by how a string looks.
Result: the last commit in the entire product repository is that fix(Measured). Over-masking is not caution, it is a quieter way to be wrong.
- 03
I attacked my own redaction with a stronger model, and it won.
Barcodes look like ordinary numbers, so my first pass left them alone. One product barcode can re-identify an entire anonymous file. I only found that by attacking my own work, and the attack won.
Result: barcodes are now caught by checksum arithmetic, not by appearance(Measured). I ran it late because I was confident, which is the exact condition under which you should run it early.
- Raw, on the hostStays on the hostN1STMEGA MART STORES
The file as it arrives. This state never leaves the building.
- Masked, as the model sees itSent to the modelN1ST[PARTY_NAME_1]
Tokenized before the prompt is assembled, and the same value gets the same token across the whole document rather than only where it changed.
- Restored, after the answer comes backStays on the hostN1STMEGA MART STORES
Unmasked locally, against a mapping the model never sees.
- 04
I made silence produce a refusal instead of a guess.
The dangerous verdict is not a wrong one. It is a confident pass on a rule nobody checked. So a pass only stands if it quotes the passage permitting it, and code downgrades any pass it cannot verify.
Result: three categories of difference are settled before the model is ever called(Measured). This sends more rows to a person than a looser system would. That is the price of never turning silence into false certainty.
- valid_per_guidelinesexplicitly permitted, and here is the passage
- no_action_requiredstructural or mechanical, settled without the model
- clarification_requireda specific question would settle it
- rejectthe rulebook forbids this, and here is the passage
- needs_business_reviewthe rulebook is silent, so a human decides An uncited pass is downgraded to here
The downgrade only ever moves toward caution. reject and clarification_required are never touched, and nothing is ever moved up the ladder.
- 05
I deleted the confidence score I had already shipped.
The first result screen showed a verdict and a confidence label. Watching analysts work, "medium" changed nobody's behaviour. It performed nuance while sending the reviewer back into the spec to find the rule anyway, so the screen had added a step, not removed one. I cut it, and two other controls with it.
Result: three shipped features removed(Measured). Calibration is provenance, not confidence. Show the receipt, not the score.
The confidence label
Confidence: mediumRemoved.
Nobody could act differently on it, and it sat beside an already probabilistic verdict.
The verdict override
Override verdict ▾Removed.
Read as a duplicate of the reviewer disposition control beside it.
The per-row verdict badge
BREAKS THE RULESRemoved.
A top-level count, not a marker that belongs on every row.
- 06
I wrote none of the code, then audited it as though a stranger had.
A planning model turns one decision at a time into a brief; a coding agent executes it. Then I audited the result as if it were someone else's. It caught my own README claiming a safety feature that did not exist, and an audit trail whose fingerprint did not match what had been sent.
Result: both fixed, out of 12 briefs and one working day of commits(Measured). The scarce skill is the governance, not the code.
What changed
| By hand(Client-stated) | With the system | |
|---|---|---|
| One document | 30 to 50 minutes | 8 minutes(Measured) |
| Confidential data | kept AI out entirely | masked on the host, never sent(Measured) |
| A pass verdict | the analyst's memory of a 200-page rulebook | a quoted passage, or no pass(Measured) |
3,000 hours a year handed back(Projected), on the client's own planning volume. A second projection runs 17× higher(Projected) on assumed volume alone. It is in the long version, because quietly picking the bigger number is how figures like these stop being believed.
What this does not claim
- There is no accuracy measurement, and I will not imply one. No answer key, no precision, no recall. Five human overrides across 7,724 differences(Measured) is a usage signal, not a quality score. Anyone quoting it as accuracy should be asked for the answer key. I do not have one.
- One model stage, not one model call. Rows go out in batches of twenty(Measured). An earlier draft of mine said "exactly one call." That was wrong, and it sounded better than the truth.
- The leak scan is a check, not a guarantee. A heuristic tuned for one transaction set, and its badge says so.
- The pilot counts are one snapshot, dated 26 June 2026(Measured).
The long version · about 15 minutes
The full redaction design, the refusal policy, the audit that caught my own false claim, and what I still cannot measure. Where I would want an evaluation team to spend their time.
Read the long version
Next case study
Chalkline
It read the lesson correctly and then made a video with none of it in. My automated check passed it, and so did a person, in seventy seconds. Both of those gates were redesigned because of it.
Read it