A request for a price on a single industrial part arrives by email before seven in the morning. Someone has to work out who makes it, work out which of thousands of suppliers stocks it, write to each of them, wait, chase the ones who go quiet, read every reply including the ones that arrive as a PDF, and turn all of it into one price with a margin on it. In one measured three month stretch that inbox took 5,678 emails and 3,141 of them were requests for a quote.
Manufacturers and suppliers are counted from the catalogue the system runs on. The parts figure is the company's own, stated in a planning meeting. The daily average is measured across 65 working days of the live inbox, 4 January to 4 April 2026, and the busiest single day in that window took 177.
A quote desk that reads the inbox, does the legwork, and stops at every point where a person should decide. Claude classifies each email as a request, a supplier reply, a purchase order, a shipping notice or something to ignore. It reads the parts out of the request, matches each one to a manufacturer through an exact name, then a list of known aliases, then a fuzzy search, and works out which suppliers are worth asking. It drafts one email per supplier, combining several parts into a single message so nobody gets four emails in a morning, and it strips the customer's identity out before anything goes out.
Nothing sends without somebody pressing send. That was a design rule from the first day, because the system this replaced had lost the sales team's trust, and one of them had gone back to keeping the whole thing in a spreadsheet of their own.
The chasing is where the time actually went. Quiet suppliers are followed up on day three, five and seven, capped so nobody is pestered, with a rule that pads over the weekend so a reminder lands on a Wednesday morning rather than a Saturday. Every pending chase cancels itself the moment that supplier replies, which is the direct fix for a previous system that kept sending duplicates and damaged the relationships it was meant to manage.
The rule that shaped everything else: a deterministic shell around a probabilistic core. Claude handles reading, matching, drafting and judgement. Ordinary code handles the pricing arithmetic, the lead time calculation, the status of a quote, who is allowed to do what, and the guard that stops anything sending itself. Nothing that has to be exactly right is left to a model.
Each stage below is what the system does on its own. Where a person has to decide, the stage says so, and those are the only points at which anything leaves the building.
Please quote the following for delivery to the Lima plant.
Material 58502001, seal kit, qty 4.
Material 39886727, gearbox, qty 1.
Material 31511534, drive belt, qty 12.
A cron job on Railway pulls the shared mailbox through Microsoft Graph, the Microsoft API for reading company email, every couple of minutes. Nothing is forwarded and nobody changes their habits: the request arrives exactly where it always arrived.
The system has a start date, so on its first run it does not chew through five thousand historical emails looking for work that was finished months ago.
| From | Subject | Read as |
|---|---|---|
| Customer | RFQ, 4 line items | Quote request |
| Supplier | RE: your enquiry 0581 | Supplier reply |
| Customer | PO 4500219933 | Purchase order |
| Unknown | Increase your reach | Ignore |
Every message is classified against a written rulebook: a request for a price, a supplier's reply, a purchase order, a shipping notice, or nothing to do with us. Only the first four create work.
The rest is dismissed in bulk. In the measured three month window, 11% of everything in that inbox was spam, and a person had been opening all of it.
| Part | Description | Qty | State |
|---|---|---|---|
| 58502001 | Seal kit | 4 | Read |
| 39886727 | Gearbox | 1 | Read |
| 31511534 | Drive belt | 12 | Read |
| 77120044 | Coupling | 1 | Qty assumed |
The request's own table is read into one quote and one line for each part: the material number, the description, the manufacturer as the customer wrote it, the quantity, the unit and the delivery plant.
Where a quantity is missing the system assumes one and marks the line as assumed, so the person checking sees an assumption rather than a number that looks confirmed.
Customers do not write manufacturer names the same way twice. The match runs exact first, then against a list of known aliases, then as a fuzzy search over a trigram index, which is a Postgres feature for finding near-misses in text.
This is the step the previous system got wrong at scale. When the catalogue was rebuilt, 60% of the old vendor references turned out to point at nothing.
A part with a supplier already agreed for that exact item goes to that supplier. Otherwise the manufacturer's preferred supplier is used. Failing both, the system widens to everyone who has ever supplied that manufacturer.
Most parts never reach the third tier, which is what makes the whole thing quick: 1,636 of the manufacturers in the catalogue already have a preferred supplier attached.
Good morning,
Could you quote the following, with lead time and availability.
1 gearbox, manufacturer part as listed. 12 drive belts.
Delivery to the American Midwest.
Claude drafts the enquiry. Several parts going to the same supplier are combined into one message, so a supplier who could receive four separate emails receives one.
The customer's identity is stripped out. A supplier learns what is needed and when, and nothing about who is buying.
This is the first of the two points where a person decides. Nothing has ever sent itself.
| Supplier | Asked | Next chase | State |
|---|---|---|---|
| Supplier A | Mon | Replied Tue | Cancelled |
| Supplier B | Mon | Thu, day 3 | Queued |
| Supplier C | Mon | Wed, padded | Queued |
| Supplier D | Mon | Third and last | Final |
Day three, day five, day seven, capped so nobody is pestered. A padding rule moves anything that would land at the weekend, so a reminder arrives on a Wednesday morning when it can be acted on.
The moment a supplier replies, every chase queued for them cancels itself. The system this replaced kept sending, and the damage it did to supplier relationships is the reason this rule is written down rather than assumed.
| Supplier | Unit price | Lead time | Arrived as |
|---|---|---|---|
| Supplier A | $412.00 | 14 days | Email body |
| Supplier B | $389.50 | 28 days | PDF attachment |
| Supplier C | $401.75 | 10 days | PDF attachment |
| Supplier D | No stock | Email body |
A reply is matched back to its quote by reference, then by the email thread, then by the sender's domain against open lines, then by the part number itself. Several routes, because suppliers reply in whatever way suits them and a reply that cannot be matched is a reply somebody has to find by hand.
Claude reads price, currency, lead time, availability and any conditions out of the message. Where the quote arrives as a PDF attachment, it reads the PDF by vision rather than asking anyone to retype it.
// Margin is on the SELLING price, not a markup on cost. // These are different numbers and the difference is the margin. customerUnitPrice = vendorUnitPrice / (1 - margin) // Which margin, in order of precedence: // 1. a price set by hand on this line // 2. an override on this line // 3. an exception recorded for this manufacturer // 4. the house default // Lead time: the supplier's own days, plus a buffer, // never below the floor, plus more if they ship from abroad. customerLeadTimeDays = max(FLOOR, vendorDays + BUFFER + overseas)
Every reply is kept. One is selected, and the database itself enforces that only one can be selected per line, so two people cannot quietly disagree.
The margin is applied on the selling price rather than as a markup on cost, which are different numbers and the difference is the whole margin. Lead time takes the supplier's own figure, adds a buffer, and never quotes below a floor. A quote in another currency carries a buffer against the exchange rate moving.
Puppeteer renders the customer's quote as a branded PDF. That is the second point where a person decides, and then it goes.
It runs against the live inbox with the inside sales team using it, in a deliberate soft launch rather than a switch thrown for everyone at once. The work that used to be a morning of writing to suppliers and copying numbers out of their replies now arrives as a drafted set of emails and a filled comparison, with a person deciding twice and the system doing the rest.
The tool and test counts are counted from the source. The cost is the client's own measured figure for one round of enquiries. The build this replaced had reached 548 formula columns across 26 tables and became unusable at around thirty live quotes, which is the comparison that matters and is recorded in the project's own technical notes.
This page once carried claims that described the work inaccurately. They came down in an audit of our own copy, and each one went back up only when its numbers could be traced to something measured. A case study you cannot check is worth nothing to you, and one that turns out to be wrong costs us more than it ever earned.