Head of AI, Air & LCL Forwarding at Maersk · Amsterdam
I build AI into operations that can’t afford to be wrong.
I write the agents, the data underneath them, and the gates in front of them. When something doesn’t work, I want to know why before I make the model smarter.
What actually changed
The numbers I use to decide whether something worked.
44% of the unit's bookings now come through the booking automation I built
Up from ~13%. It is now the unit's #1 digital channel, ahead of the company website, its system integrations, and Alibaba's marketplace.
Auto-rating adoption scaled from 14% to a peak of 80%
Automated pricing across the air & LCL freight unit, phased by confidence band and gated on override rate. This is the line that returned $11M EBIT.
Pricing agents cut quote turnaround from 45 minutes to 4
The agents sit on the live quoting path. A quote leaves without a person touching it only inside the confidence band the override rate has already cleared. Everything outside the band still goes to a person.
Drove platform growth at Blibli
A travel SaaS platform for corporate, agency and retail clients. Over the same period users went from 135K to 165K.
Customer names and internal system names are withheld.
How AI gets adopted, or doesn’t
How automated pricing went from 14% to a peak of 80% adoption.
The situation
We'd shipped automated pricing across Maersk's air and LCL freight business. It cut quote time from 45 minutes to 4. And almost nobody wanted to use it. Adoption stalled at 14%. Worse, operations teams were overriding 18% of the quotes we were calling high confidence. So before we touched the model, I wanted to know why.
What I found
The consensus was that the model was hallucinating and we needed a better one. It wasn't. The same physical lane existed three different ways across our source systems. There was no canonical lane-and-commodity entity, and no controlled vocabulary connecting commodity codes to surcharge rules. So it retrieved the wrong surcharge and reasoned flawlessly over it.
The obvious fix
The obvious move was to swap in a newer model, tune the prompts and train the users. I stopped that. If the model was reasoning correctly over bad data, a smarter model would just be wrong faster, and more training would only teach people to distrust it more efficiently.
What worked
I halted the rollout and fixed the knowledge layer first. I defined a canonical lane-plus-commodity entity with a controlled vocabulary, and reconciled the master data behind the rate lookup. Then I put an eval gate in front of it: shadow-mode replay against known-good quotes, and nothing went live until accuracy cleared the floor. Override on high-confidence quotes fell from 18% to ~4% in one sprint. After that I widened the rollout region by region, through super-users their own teams already trusted.
What I learned
Adoption reached a peak of 80%, worth ~$11M EBIT on the pricing line. Same model, same features. The model was not the problem. The representation underneath it was. I have now seen that failure with lanes, with customers, with commodities and with flight milestones. Different entity, same problem. So I look for it before I change the model: where do two systems describe the same thing differently?
The biggest thing I shipped
Touchless Booking Platform
Maersk Email-to-Booking Automation
Most LCL bookings used to arrive as an email with attachments and get keyed in by hand. I built the pipeline that reads the email, extracts the documents, resolves the customer, lane and commodity, and creates the booking in the system of record.
Why I built it
~94% of LCL bookings were keyed in by hand from emails and attachments. The plan on the table was to move that typing to a cheaper keying centre. Whoever automates booking entry owns the data it creates.
What I built
Outcome
#1 digital booking channel | 44% of bookings (from ~13%)
Code I wrote
Public projects and production code. The numbers are there because I don’t expect you to take my word for it.
Ladder
Let an agent show its work before it changes anything.
Ladder runs the agent's real tool against a copy of the application's state. You see the proposed changes as a diff, remove anything you do not want, and then the same tool runs for real against what remains. The agent gets back an account of what landed and why the rest did not.
Nothing real moves. What the tool would do becomes a diff: how many records, how much money, how much of it cannot be undone.
FreightBench
Not all AI errors cost the same.
I wanted a benchmark that counted a missing value and a confident wrong value separately, so I wrote one. It generates its own corpus, and each document carries one named fault, so a failure reports by cause: a seaport confused with the airport of the same city, a weight given in pounds, a correction buried in a forwarded thread. No model has been run through it yet. The harness, the corpus generator and 40 tests are public.
A null routes the booking to a person. A confident wrong value goes straight through and surfaces when somebody is invoiced for it.
Airline Milestone Agent
Maersk internalCatches impossible flight milestones before customers do.
Production code at Maersk that grades carrier milestone updates before they reach the shipment record. An adapter per carrier, a guard that rejects any milestone contradicting one already recorded, and a golden set that measures each carrier's accuracy in probe mode before anyone switches it on. It also settled a long-running argument about whether the system of record stores local time or UTC.
Internal code, so there is nothing to open.
Physics alone could not settle it, and I tried first. Only a carrier publishing both readings decides it.
Where the number was mine
Three corrections I filed on my own work, each before anyone else found it.
The 32% cut
Three agent business cases were heading into a Friday sign-off. All three rested on one time study, and all three assumed that every activity happens on every shipment. Nobody had written that assumption down, so nobody had tested it.
I queried the production system of record: 12,005 air shipments from one month, checked across two databases. The lowest real occurrence rate was 1.0%. The highest was 94.2%.
Then I built the correction to run against my own case. Where the log understated work that physically happened, I applied a floor. One pickup-side step was logged on 40.9% of shipments. It had physically happened on 68.2% of them. Four activities I could not measure I left at 100%, so the bias stayed against me.
My agent's entitlement per shipment came back a third lower. I sent it to the study's owner before the number went to sign-off.
The study was not wrong. I was using its number too casually.
The gate that passed itself
A customer's live performance dashboard refreshes on a schedule with nobody watching. I built a gate in front of the publish step so a bad payload could not reach the customer. On its first real test, coverage had fallen to 78.7%. The gate tripped and refused to publish. Correct.
Then the retry passed. The script overwrote the local payload before the gate ran, so the second attempt compared the new payload against itself. The fix was ordering: a tripped gate now restores the previous payload before anything else happens.
The first publish went out with the gate effectively neutralised.
The eleven-day write
An agent I wrote reads flight milestones from carriers we do not control and records them against the shipment. One consignment matched on every identity signal: airwaybill, route and pieces. It scored high confidence and wrote an arrival eleven days before the departure already on file.
The reason it got through was my own design. Temporal sanity only ever compared a proposal against estimates, never against an actual already recorded, and eleven days sat inside the tolerance. I found it, blocked auto-apply on any proposal contradicting a recorded actual, and wrote the reason into the pull request.
This is the part that is easy to get wrong, and I got it wrong first.
High confidence and a wrong write are not opposites.
About

In 2021 we put an early GPT assistant in front of real customers at Navan. It was accurate, and users still escalated to humans. They didn’t ask “is it right?”. They asked “why should I believe it?”. That question has stuck with me.
Most of what I have built since is about the gap between a system being capable and someone trusting it enough to let it touch production. That is why I care about gates, evaluation sets, rollback and slow rollouts. The model is one part of the system, and usually not the part that decides whether it gets used.
The same booking automation that reached near-universal adoption in Sweden sat near zero in Hong Kong until local super-users made the case themselves. Trust does not globalize.
There are two things I am not satisfied with yet. The model under my agents is somebody else’s and I do not retrain it; I harvest failures into a golden set and move the thresholds and guards around it. And my entity resolution is code, not an ontology a domain expert can edit without a deploy. I know how I would like to change the second one. I just have not built it.
Outside the day job I write code, with Claude Code as my pair programmer. This site, Ladder and FreightBench were all built that way. At work the habit became The Build Log, a weekly AI newsletter for 100+ PMs. The point of it is not to teach people about AI. It is to get them building with it.
Experience
Where I have worked, and what I changed there.
Head of AI, Forwarding (Air & LCL)
A.P. Moller Maersk
- Built a touchless booking platform instead of moving the manual keying offshore. It now creates 44% of the unit's bookings, up from ~13%, and is the unit's #1 digital channel
- Scaled automated pricing on an eval-gated rollout from 14% to a peak of 80% adoption, worth $11M EBIT
- Shipped a file-compliance agent that reads the invoice and packing list and writes the reference numbers into the system of record. It inserted the right commercial-invoice reference on 98% of shipments in the June 2026 window
- Put pricing and quoting agents on the live quoting path. Quote turnaround went from 45 minutes to 4
- Retained a ~$15M ARR account at renewal: ETA accuracy at the final port went from 1% to 92%, and milestone timeliness from 47.7% to 70%
- Run six AI product lines with five product managers and ~40 cross-functional colleagues. Their work delivered $22M gross profit in Air and $4M EBIT in LCL
Senior Product Manager - Experience
Navan (formerly TripActions)
- Launched a GPT-powered customer assistant that resolved queries without a human agent. It saved $1.2M a year, and CSAT went up
- Redesigned the agent workflows around it. Handling time fell 10%, worth $1M a year
- Folded 4 legacy communication systems into one CX platform. That cut $2.64M a year in infrastructure cost
- Grew the product organisation from 1 to 3 scrum teams
Senior Product Manager - Travel SaaS
Blibli (via Coviam)
- Delivered a SaaS travel platform with 137% revenue growth
- Grew the user base from 135K to 165K, up 22%
- Packaged one platform for retail, corporate and agency demand on supply from 101 airline APIs and 3.6M+ accommodations
Senior Product Manager - Core Platform
Wipro Technologies
- Built Way2Go, an enterprise SaaS travel and expense platform, from nothing to 50K active users and 600+ trips a day
- Ran a 24-person product and engineering group through engineering managers and a UX lead who were my direct reports
- Set the architecture direction and sat on the hiring panel for the engineers, the product manager and the designer
Technical Product / Program Manager
SITA
- Delivered IATA-regulated Passenger Name Record migrations at a 0.02% rejection rate. Regulated data, fixed external deadlines, no silent failures
Get in touch
Email me about the builds above, AI in operations, or something you're trying to ship.

Harsh Puri
Head of AI, Forwarding (Air & LCL) at Maersk
I put software into operations that run on other people’s hands. Pickup vans and airlines we do not employ, and a system of record that has to end up correct or the money does not move.