Aradus Field Guide

Two essays: what Aradus does, in four layers, and a month inside one customer's account.

What Aradus does

Every company that moves physical goods runs on two kinds of information. There is the record: an order was placed, an invoice was issued, a container was booked. And there is the traffic: the emails, PDFs, WhatsApp messages, phone calls and portal screens through which the record gets made and kept up to date. ERPs are good at the record. Nobody is good at the traffic. It is read by people, one message at a time, and typed into the record by hand.

Aradus exists to do the traffic. That is the company in one sentence. A manufacturer or a distributor keeps its ERP, or its spreadsheet if it has no ERP, and we sit in front of it reading what arrives, deciding what it means, and either doing the next thing or asking a person. The stated scope in the repo is procure-to-pay, order-to-cash and the logistics between them. Financially we stop at matching an invoice against an order and a receipt, and auditing freight bills. We do not do accounting.

Once you see it that way, the pieces in the codebase stop looking like a list of features and start looking like layers of one machine.

The first layer is the edge: how traffic gets in and out. Email through Outlook and Resend, WhatsApp through Twilio, voice calls, uploads, and portal scraping for tracking. Each of these is a door, and each door today has its own little room behind it where it keeps what came through.

The second layer is reading. This is the document pipeline. A PDF arrives and the pipeline works out what it is, splits it if it is several things stapled together, and pulls the fields out: invoice number, lines, totals, the counterparty. It is the part of the system that turns pixels into candidate facts. I say candidate on purpose. The pipeline is not allowed to be sure. Its output is a proposal with a confidence, and the design we have been working on for the past week is mostly about making that honest: proposals are written down and left as written, a person or a policy decides, and only the decision becomes a fact.

The third layer is deciding and acting. This is the workflow engine, the Automations graphs, the Command Center. When the pipeline says "this looks like the second version of invoice 4471 from the same supplier," a workflow raises a version review, an operator picks the right one, and something downstream happens. When a shipment's ETA slips, a notification goes out. The workflow layer is where a tenant's own rules live: who approves what, when to escalate, what counts as a duplicate.

The fourth layer is memory, and it gets the least attention relative to what it is worth. What did we decide, on what evidence, and what rule came out of it. This is what Pallet calls their Enterprise Memory Layer and markets as the moat, and they are right to. An ERP will happily tell you what an order says. It cannot tell you that the supplier's invoices come in two flavours, that this customer signs off artwork by marking up a screenshot, or that a particular carrier's emails are trustworthy about vessels and useless about dates. Every human intervention is a rule waiting to be written down. The system that writes them down and applies them next time is the one customers cannot leave.

Edge Outlook, Resend, Twilio WhatsApp, voice, uploads, carrier feeds Reading document pipeline: classify, split, extract, then proposals with confidence Deciding Automations graphs, Command Center, thresholds Memory decisions, evidence, rules, pinned versions written last ERP the record, written last
Four layers sit between incoming messages and the ERP, which is written last and stays the record.

Now the workflows, placed on those layers.

Document intake and invoice versioning are layer two feeding layer three, for ITCC. Supplier invoices arrive by email, get read, get compared with earlier versions, and a person resolves the difference in the Command Center. This is the most mature path in the system and the one with paying traffic.

Shipment tracking is a layer-one door (carrier feeds, the bill of lading, the vessel fallback for small carriers) feeding a layer-four memory that we happened to build properly: observations and a reducer. More on that in a moment.

Document generation is layers three and two run backwards. A loading list goes in, a packing list and a commercial invoice come out. IMP uses it. It is the only place where we produce documents rather than read them.

Freight quotes, bookings and requests are layer three with a thin layer two: structured forms more than messy traffic.

Order confirmation, the thing we are about to build for IMP, is interesting because it touches every layer at once and it sits at the hinge of the business. IMP is a trader. A customer orders branded cans; IMP orders printed sheets from one supplier; the goods go straight through. Nothing can be ordered from the supplier until the customer has confirmed the artwork on every line. So order confirmation is where order-to-cash hands off to procure-to-pay, and it is the step Sari spends two hours on per order and gets wrong at ten thousand dollars a time. It needs the doors (WhatsApp for Sari, email for his customers), the reading layer (which brand is this file, what did the customer say), the deciding layer (send, remind, escalate, convert, approve the PO), and above all the memory: which exact version the customer approved, and the rule that came out of every question we had to ask him.

Which brings me to your question, and it deserves a straight answer: why do shipments have observations and a reducer, while orders get a row that gets overwritten?

Because shipments hurt first. A shipment is the one object in the system whose truth is told to us by several outside sources that disagree and keep changing their minds: the bill of lading says one date, the carrier feed says another, an operator overrides it after a call, the feed comes back a week later with what actually happened. The old system stored one ETA and let each source overwrite the last, and that produced actual incidents: a refresh from the BL wiping out an operator's correction. So when the greenfield design was written, tracking got the careful treatment. Write every statement down, leave it as written, compute the current state with a function whose rules are versioned.

BL says 10th feed says 12th operator says 11th reducer v3 rules: feed > document, actual > expected, operator edits survive refresh current state: departed 12th
Three sources report different dates for one shipment. A versioned reducer decides the current state from ranked rules.

Orders did not get that treatment because, at the time, an order looked like a different kind of thing. It gets placed once, from a document, and then it is done. Its facts do not drift. Nobody was emailing us about orders. So the design treated an order as something the pipeline creates, not something the world keeps reporting on.

That assumption just broke. Karam's carrier email is a report about a shipment, fine, but the supplier who pushes a lead time out a week is a report about an order. Sari's customer confirming line three by phone is a report about an order. A forwarded artwork file is a report about a brand. The moment messages become a first-class input rather than an attachment carrier, every object acquires the property shipments already had: outside sources assert things about it, over time, with different reliability. The discrepancy in the design is not a mistake so much as a fossil. The data model records which problem was painful when it was drawn.

The fix is the obvious one and it is the direction you have been pushing: the observation-and-reducer pattern is how any object in the system should absorb the world's reports about it, shipments included. A supplier email is one observation about an order's promised date, ranked below a signed confirmation and above nothing. The reducer per attribute says which wins. And the review gate in front of it says when a person should look.

Compressed: Aradus reads the traffic so the record stays true, and remembers how it decided so it does not have to ask twice. The document pipeline is the reading. The workflows are the deciding. The observations are how the record stays true when the world keeps talking. Order confirmation is the first feature that needs all of it for one customer, on one order, with money on the line. That is why it is the right thing to build next, and why it is going to be harder than it looks.

A month at Zaytoun Foods

Let me invent a customer and run a month of their life through Aradus. I'll pick a business shaped so that every workflow we have gets touched once, and I'll assume you know software but nothing about how goods move.

The company. Zaytoun Foods LLC, Dubai. Twelve employees. Two things going on under one roof.

They make date syrup and tahini. Some of it sells under their own label. Most of it sells as private label: a supermarket chain in Riyadh wants the same tahini in a jar that says "Al-Tamimi Select," so Zaytoun prints the chain's artwork on the label and ships it. Private label is where the money is, and where the mistakes are, because the jar carries someone else's brand.

To make anything they buy glass jars and lids from one supplier, Camlica Cam in Izmir, Turkey. Jars arrive by sea in containers, roughly one a month.

They sell finished goods two ways: to the Gulf chains by truck, and to distributors in Kenya and Tanzania by sea, in their own containers.

They have a small ERP for stock and invoices, and a shared mailbox, ops@zaytoun.ae, that three people read. Their customers and suppliers talk to them by email, WhatsApp and phone, in about that order of volume. Before Aradus, the three people spent most of their day copying things from those channels into the ERP and chasing people who had not replied.

Here is what a month looks like with Aradus in front of the ERP. I'll name the people: Layla runs operations, Omar does purchasing, and Hana does export documents.

W1 W2 W3 W4 PO + freight quotes then booking invoice CC-8812 v1 auto-approved v2 +$210, version review rule saved vessel: BL vs feed, carrier email, port change + ETA Al-Tamimi photo order, confirm quantities, order confirmation loop loading list, packing list + commercial invoice any week: Oman inquiry, auto-reply
Four weeks at Zaytoun Foods, each column showing that week's episodes, with one message that can arrive any week.

Week 1: Omar orders jars. Omar decides they need 40,000 jars. In the old world he emails Camlica a purchase order he typed by hand. Now he creates the purchase order in Aradus (or in the ERP, which syncs it), and Aradus sends it from Zaytoun's own address. Nothing clever yet. What matters is that Aradus now knows a PO exists: 40,000 jars, model J-370, at $0.21, expected in six weeks. That expectation is the first fact about this order.

Omar also needs a container from Izmir to Jebel Ali. He raises a freight request in Aradus: one 40-foot container, ready date, ports. Aradus sends it to three forwarders Zaytoun uses. Two reply by email with a price, one replies by WhatsApp with a photo of a rate sheet. Each reply is a message that arrives through a door, gets read by the pipeline, and becomes a freight quote with a number on it and a link back to the email or photo it came from. Omar picks one, and that becomes a freight booking. Three documents that used to be four emails and a spreadsheet are now three rows with their evidence attached.

Week 2: the invoice arrives, twice. Camlica ships the jars and emails the invoice as a PDF: CC-8812, 40,000 jars, $8,400. The mail hits ops@zaytoun.ae. Aradus reads it before anyone else does.

What "reads it" means, precisely: the email is a delivery. The PDF is an artifact, stored once by the hash of its bytes. The pipeline asks what this artifact is and proposes "commercial invoice, 97% confident." That passes Zaytoun's threshold, so a document is born as an invoice. The pipeline then proposes each field: invoice number CC-8812, seller Camlica Cam, forty thousand of J-370 at $0.21, total $8,400, each proposal tagged with where on the page it came from. The seller resolves to the supplier record because "Camlica Cam San. ve Tic. A.S." is an alias Omar confirmed months ago. Nothing in the ERP is touched yet. These are proposals.

Now the three-way match. Aradus has the PO (40,000 at $0.21), it has this invoice, and when the container is unloaded it will have the receipt (how many jars actually arrived). All three agree, so the invoice is approved for payment without a person looking, because Zaytoun's policy says "auto-approve when PO, invoice and receipt agree within 1%." The invoice is written to the ERP as payable. Layla sees it in a list of things done, and nobody had to touch it.

Four days later a second email arrives from Camlica: "Revised invoice attached, please disregard the previous one." Same number, CC-8812. The total is now $8,610: a $210 pallet charge was added. This is the case the invoice-versioning workflow exists for. The pipeline reads the new PDF, sees the same invoice number from the same supplier, and instead of creating a second invoice it proposes "this is version 2 of CC-8812." The workflow raises a version review in the Command Center: side by side, the only difference is a new line, and the body of the email said "disregard the previous one." Layla clicks once: accept version 2. The ERP invoice is updated to $8,610, the old version is kept in history, and the three-way match runs again. It now fails by $210, over the 1% threshold, and the invoice goes back to needs approval. Omar looks, sees a pallet charge that was in the PO's small print, approves it, and ticks "save as rule: pallet charges from Camlica up to $250 are acceptable." Next month the same thing will not ask.

Notice what happened at every step. A message arrived. The pipeline proposed. A rule or a person decided. The ERP was written last. And a rule came out of the intervention.

Week 3: the ship. The container is on a vessel called MSC Adriana. The bill of lading, which arrived as another PDF from the forwarder, says departure March 10, arrival March 24. Aradus created a shipment from that document and started tracking it against the carrier's own data feed.

The feed says departure March 12. The BL says March 10. Which is right? This is where the observations and reducer pattern earns its keep. Aradus does not overwrite anything. It records two observations: "BL says departed 10th," "carrier feed says departed 12th." A rule says the carrier's feed outranks a document about dates, so the shipment's current state shows the 12th, and if you ask why, the answer is those two rows and that rule.

Then a carrier email arrives at ops@: "Due to congestion at Jebel Ali, MSC Adriana will now discharge at Khalifa Port, ETA March 27." This is the case Karam raised. The email body has no attachment. The pipeline reads the body, resolves "MSC Adriana" and the container number in the text to Zaytoun's one open shipment, and proposes two observations: destination port changed to Khalifa, ETA March 27. A carrier email is trusted about routing, so the port change auto-applies. The ETA moves as an expected date and a notification goes to Layla and Omar, because Zaytoun's rule says "tell me when an inbound container slips by more than two days." The trucking booking from the port has to change, and Layla changes it. In week 4 the feed reports the vessel actually berthed at Khalifa on the 28th. That is an actual date and it wins over every expected one.

Week 3, in parallel: the private-label order. Al-Tamimi, the Riyadh chain, sends an order by WhatsApp to Layla's number: a photo of a handwritten list. Three products, quantities, and "new label for the tahini, file attached." A PDF of the label follows.

The pipeline reads the photo. It proposes a sales order with three lines, at 82% confidence on the quantities because the handwriting is bad. Zaytoun's threshold for creating an order from a photo is 95%, so this one waits. Layla gets a message: "Order from Al-Tamimi, three lines, please confirm quantities." She fixes one digit and confirms. The order exists. This is the back-and-forth case: for a customer who sends clean spreadsheets the same step would have created the order with nobody involved.

Now order confirmation, the flow we are building. Zaytoun cannot print labels until Al-Tamimi confirms the artwork for each line. Two of the three lines match brands already in the library: "Al-Tamimi Select Date Syrup 500ml" and "Al-Tamimi Select Tahini 350g," each pinned to a specific approved version. The third line says "tahini, new label," and the PDF that followed is the candidate for it.

Aradus reads the label PDF. Text in the artwork says "Al-Tamimi Select Tahini 350g." Visually it is 94% similar to the current version of that brand. The origin is Al-Tamimi's own WhatsApp number. Three signals agree: this is a new version of the tahini label. It is saved as version 4, version 3 stays in history, and Layla gets a receipt: "Replaced Al-Tamimi Select Tahini 350g v3 with v4." Layla's rulebook said auto-replace when the three signals agree, so nobody compared files. A customer who wants to approve every version would set that rule to require approval on every version.

The pack goes out to Al-Tamimi's buyer by email, since the chain has not opted into WhatsApp from Zaytoun: previews of all three labels, one link per line. Zaytoun's rulebook for this customer says remind every two days, escalate to the category manager after two reminders, a marked-up screenshot counts as sign-off. Day two, no reply, a reminder goes. Day four, the buyer replies: "Syrup and tahini 350 confirmed. The date syrup 1L, please move the barcode to the back." The pipeline reads that as three verdicts: two confirmed, one rejected with an instruction. The two confirmed lines are pinned. The rejected line waits for Zaytoun's designer, who uploads version 2 of the 1L label; the loop sends only that line back out. Day six, "1L confirmed." Every line is pinned to a version the customer said yes to, and each yes points at the exact words in the exact email that said it.

Only now does production get its work order, and the label print run is released. If the barcode had been in the wrong place on 20,000 labels, that is the ten-thousand-dollar mistake this exists to prevent.

candidate label origin content visual agree? yes auto-replace + receipt no one-tap question pack out per line reminder every 2 days reply verdicts per line: confirmed, or rejected + instruction re-send only rejected line all pinned each line, one exact version print run released
Order confirmation: a candidate label passes three signals before it auto-replaces a version, and every confirmed line ends pinned to one exact version.

Week 4: the export shipment. The Kenya distributor's order is ready. Hana has a loading list: which pallets, which products, which lot numbers, weights. She needs a packing list and a commercial invoice in the exact format Kenyan customs and the distributor's bank expect, and a certificate of origin request. This is document generation, the one place Aradus writes documents instead of reading them. Hana uploads the loading list, Aradus produces the packing list and commercial invoice from it, she checks the totals against the order, and sends. The bill of lading comes back from the forwarder a few days later, is read like any other BL, and the outbound shipment is tracked to Mombasa the same way the jars were tracked in.

Any week: the stranger. An email arrives at ops@ from someone in Oman: "Do you sell tahini in Muscat, and what is your price per carton?" Zaytoun does not sell direct in Oman, they have a distributor there. The pipeline reads the intent as a price inquiry from a non-customer, and the workflow replies with the Oman distributor's contact details, from a template Layla approved once. No human reads it. The email is kept, in case the stranger turns out to matter.

What accumulated. By the end of the month Zaytoun's memory in Aradus holds: an alias for Camlica's legal name, a rule about their pallet charges, a rule that carrier emails may change a port but not a confirmed arrival, a threshold for photo orders from Al-Tamimi, that customer's reminder and escalation contacts, the fact that marked-up screenshots count for them, and four versions of a tahini label, with the current one pinned to a signed-off order. None of that is stored in the ERP. All of it makes next month shorter. That is the layer the ERP cannot offer and the reason a customer who has used Aradus for a year does not switch.

tag entry alias Camlica Cam legal name resolved to one supplier alias rule pallet charges from Camlica up to $250 auto-approve rule carrier feed outranks documents on port and date threshold photo orders from Al-Tamimi require 95% confidence contact Al-Tamimi reminder every 2 days, escalate after 2 contact Al-Tamimi screenshot with markup counts as sign-off pin three private-label lines pinned to signed-off versions
What accumulated at Zaytoun Foods in one month: aliases, rules, a threshold, contact preferences, and the pins that keep each line tied to one version.

Where each workflow sat: the doors were the shared mailbox, two WhatsApp numbers, and the carrier feed. Reading was every PDF, photo and email body turned into proposals with evidence. Deciding was the thresholds, the version review, the three-way match, the confirmation loop and the auto-reply. Memory was the rules and pins that came out of every place a person had to touch it. The ERP was written last in each case, and stayed the record.