Field Stories10 min read

Forty Freight Quote Requests Before 9 a.m.

By Ergini, Software & AI Developer

A composite story. The company and the people in it are invented. The problem, the rules and the system are real, and the full blueprint is in the use case library.

TL;DR

A composite story: a 30-person road freight forwarder near Nuremberg gets forty-odd spot quote requests by email before 9 a.m., in four languages, and loses loads it answers late while the desk clears the easy ones first. The agent I would build reads each request into shipment fields, asks customers for anything missing, and prices the lane with the desk's own margin table in code. Reps approve drafts in Teams, key accounts, dangerous goods, cold loads and new customers always go to a person, and every outcome is logged.

11:40, Thursday: "schon vergeben"

The reply lands in the quote mailbox at 11:40, nine minutes after the quote went out. It is two lines long, from Heike, who books transport for a packaging manufacturer in Fürth:

Danke, ist schon vergeben. Beim nächsten Mal gerne etwas schneller. Gruß, Heike

Thanks, already placed. A bit faster next time. Marek, the rep who sent the quote, reads it, sighs and archives it. He does not record the loss anywhere, because there is nowhere to record it. By Friday the load will exist in no report and in nobody's memory.

The forwarder is invented: 30 people outside Nuremberg, full loads and groupage between Germany, Poland, Italy and Czechia, and a sales desk of four. The morning is not. Anyone who has worked a road freight quote desk has lived it, and the only way to see where it went wrong is to walk it backwards.

Walking the morning back to 07:14

11:31. Marek sends the quote. It is a good quote: twelve Euro pallets, not stackable, 4.8 loading meters, a fair price for the lane, valid for 48 hours.

10:50. He opens Heike's email for the first time. He checks the consignee against last month's order, converts the pallets into loading meters, opens CarLo to see what the lane cost the last four times, checks Timocom for where the market is this week, adds the margin Heike's company usually gets and writes the reply. Forty minutes, with two phone calls and a carrier problem in the middle.

09:05. The desk has cleared what it calls the quick ones: complete requests from customers it knows, on lanes it runs every week. Heike's was complete too. But it said Verona, and Italy is Giulia's, and Giulia is off on Thursdays. So it waited for whoever got to it.

07:14. Heike's email arrives, three lines, nothing missing: 90763 Fürth nach 37135 Verona, 12 EUR-Pal. nicht stapelbar, 6,1 t, Ladung Freitag. It is one of forty-one requests that land in the shared mailbox before nine, and one of the few that needs no question at all. Heike sent the same three lines to two other forwarders. The first acceptable price came back at 08:20, and it got the load.

Nobody at the desk was slow. They were doing what a busy desk does with forty-one emails: the easy ones first.

The easy ones are not that easy. A British customer writes "can you do the usual to Poznań next week?", which names a city and nothing else. A Polish dispatcher types a postcode without its dash. One customer needs a tail-lift and calls it a Hebebühne, another writes winda, a third sponda idraulica. A PDF transport order arrives as an attachment with no text in the email at all. A shipper sends an Excel sheet with thirty lanes from a tender and a deadline on Monday. And the same request often arrives three times: to the shared address, then to Marek directly, then as a chase after lunch.

Each one is retyped by hand. The requests that need real judgment, a new customer, a dangerous goods load, a lane nobody has run before, get the tired end of the day. And almost nobody writes down which quotes were lost, or to what price.

The one number nobody has

Sabine, who runs the desk, books a call and shares her screen. The mailbox has 212 unread emails, and she wants to know whether AI can answer them.

Before we talk about AI at all, I ask for a week of quote requests exported from the mailbox with their timestamps, the quotes that went back, and what happened to each one afterwards. She can give me the first two by Monday. The third does not exist. The desk knows roughly how many quotes it sends. It cannot say how many it wins, on which lanes, or how much the hour of the reply matters. Heike's load is not a statistic. It is an archived email.

So the first thing the system will do, before it answers anything, is remember. Every request gets a record: when it arrived, when the quote went out, at what price, and what the customer said next. That alone would tell Sabine something she has been guessing for years.

Then I ask for the pricing rules. They live partly in an Excel file with a tab per customer tier and partly in Sabine's head: "never under this per loading meter to Italy", "the Czech lanes get the fuel floater, always". Before any code is written, those become one table she controls. Half-joking, she asks whether the AI could also decide what to charge. It will not. That is the one job it never gets.

The model reads, the table prices

The system is one agent with a small set of tools, and the line between them is the whole design. The model reads and writes language. Everything that is arithmetic or policy is code it calls but cannot change.

A Microsoft Graph subscription on the quote mailbox picks up each new email, including forwards from the reps' own inboxes and PDF transport orders. The model reads it into fixed shipment fields: origin and destination, dates, pallet type and count or loading meters, weight, stackability, ADR details, temperature range, a tail-lift. It does not translate first. The fields are the same in Polish, German, Italian and English, so it reads each language straight into them.

Then code takes over. Postcodes are geocoded and checked against each country's format. Pallets become loading meters, 0.4 per Euro pallet loaded lengthwise and 33 to a full trailer. The customer is identified from the sender's domain and the TMS. The price is built from CarLo's lane history, Timocom data where the subscription offers an interface, distance and tolls for the route a truck actually drives, and Sabine's table: the tier margin, the floor, the fuel floater, the supplements, a validity period.

Here is Heike's Thursday email, replayed through it:

In the emailWhat the system makes of itDone by
90763 Fürth nach 37135 VeronaBoth postcodes valid for their country; truck route and tolls from the routing APIModel reads, code checks
12 EUR-Pal. nicht stapelbar12 Euro pallets, not stackable: 4.8 loading meters, groupage rather than a full loadModel reads, code converts
6,1 t, Ladung Freitag6,100 kg against the desk's own loading-meter factor; Friday resolved to a dateCode
The senderKnown customer, tier B, lane run eleven times this year, account owner GiuliaCode, from the TMS
The priceLane cost basis plus the tier B margin, above the floor, fuel floater applied, valid 48 hoursCode
Send or draftRoutine, but the agent is in its first weeks: German draft to the desk queue in Teams, lane history attachedCode, by rule
The replyApproved with one click, sent in Heike's thread, restating every fieldMarek

The draft would be waiting before Marek finished his first call. Because the reply restates the shipment, any misreading surfaces in Heike's inbox, not on a loading dock. The full design, including the tools the agent calls, is in the blueprint for a freight quote desk.

Which Frankfurt?

Before anything reaches a customer, the week Sabine exported is replayed through the agent, request by request, and its fields, questions and prices are laid next to what the desk actually sent. Most of it matches. The misses are the useful part.

A Polish customer asks for a price to Frankfurt. The first version reads Frankfurt am Main, because that is what a geocoder returns first. The customer meant Frankfurt (Oder), on the Polish border, several hundred kilometers and a very different price away. So a new rule goes in: a place that matches more than one location becomes a question to the customer, never a guess.

The replay finds smaller things too. The postcode check rejects a Polish postcode typed without its dash, which is still valid. Three copies of one request, to the shared address, to Marek and as a chase, produce three drafts, so requests are now fingerprinted on lane, date and quantity within a time window and merged into one. And on one afternoon the Timocom data behind a price is older than Sabine's limit, so the rule becomes: stale market data means a draft, never an automatic send.

What it may send without asking

Autonomy is granted per kind of request, and each kind earns it separately. Questions go out on their own from the first day, in the customer's language and thread, because asking for a postcode commits nothing. Routine quotes for known customers start as drafts. Once a request type has had its drafts sent unchanged for about four weeks, it may send within value and margin limits that Sabine sets and can tighten in minutes.

Some kinds never get there, by design. A customer's first shipment on a lane stays a draft, with the lane history attached. Key accounts go to their owner, every time. For dangerous goods the agent extracts the UN number, class and packing group, and for cold loads the temperature range, then hands over, because vehicle, driver certification and price are a qualified dispatcher's call.

New customers get the most suspicion, because freight fraud tends to start with a plausible first-time shipper. The agent checks the VAT number through VIES, the age of the email domain, free-mail addresses and the company registry, and then a person approves the account and its credit terms before any truck moves. Every quote the agent prepares says plainly that an automated assistant prepared it, and names the person who checked it whenever one did.

The next Thursday at 07:14

Heike writes again, same three lines, a different Friday. Giulia is still off on Thursdays, but it no longer matters who owns Italy. The email is read the minute it lands, the draft sits in the desk queue with the lane history beside it, and Marek approves it between two calls. The quote is in Heike's inbox while she is still waiting for the other two forwarders.

Forty-odd requests still land before nine. The difference is which ones wait. The routine ones stop waiting, so the reps' mornings go to the requests that need them: the new customer who has to be checked, the ADR load, the tender sheet with thirty lanes. And on Friday afternoon Sabine can open the log and see what she could only guess before: which lanes the desk wins, which it loses, at what price, and whether the hour of the reply had anything to do with it.

When a customer writes "schon vergeben" now, it is not archived. It is an outcome, classified and written back against the quote, next to the time it took.

If your mailbox looks like Sabine's

If you are a US truckload broker working in English on DAT rates, buy one of the products built for you, such as Vooma, HappyRobot or Parade. A build makes sense for European road forwarders whose requests arrive in several languages and whose TMS is CarLo, Transporeon, CargoWise or similar. The TMS stays the system of record, and the agent sits in front of it, so the extraction and the pricing rules stay yours if the vendor ships something better later.

It is usually a single-purpose build on the AI agent development page, and the price depends mostly on how open your TMS is, how many languages and formats arrive, and how many pricing rules still need to become a table. The full blueprint has the tools, the failure modes and the questions to ask your TMS vendor. If invoices and complaints share the quote address, shared inbox triage sorts them out first, and the email automation guide goes deeper into the inbox side.

Frequently asked questions

Can AI answer freight quote requests automatically?

Yes, for routine requests from known customers, inside limits you set. The agent reads the request in the language it arrives in, asks the customer for anything missing, and calls pricing rules written in code. It sends on its own only when customer, lane and value fall inside those limits. Key accounts, dangerous goods, temperature-controlled loads and new customers always go to a person.

How does an AI agent read quote requests in German, Polish and Italian?

It extracts rather than translates. Postcodes, dates, pallet type and count, stackability, weight, ADR details and a tail-lift are the same fields in every language, so the model reads each email straight into a fixed schema. Code then checks postcodes against each country's format and converts pallets to loading meters, and the reply restates the shipment so a misreading shows up before a truck is booked.

Who sets the price when an AI agent quotes freight?

Your pricing table does. The agent looks up lane history in the TMS, market data where your freight exchange subscription offers an interface, and distance and tolls from a routing API. Code then applies the customer's tier margin, the floor, the fuel surcharge and supplements. The model never proposes a number, and the desk lead changes margins and limits without touching the agent.

What does it take to build a freight quote agent?

Usually a single-purpose AI agent build, scoped around your TMS. The biggest cost drivers are how open the TMS is (an API, a readable database or only exports), how many languages and formats arrive, including PDF transport orders and Excel tender sheets, and how complex the pricing rules are. A week of real requests, replayed through the extraction, shows early whether it fits.