Inspiration

Air-cargo shipments rarely miss their flights by surprise. A truck runs 90 minutes late, and the freight still reaches the hub inside the cut-off, but past the handling window. A flight shows 2,400 kg free, but it has no pallet position left. The signal is visible hours early. What's missing is someone on the evening desk who works every file before the cut-off. An LLM can do that job, but only if nobody has to double-check its numbers. A wrong flight number or an invented weight in a rebooking is worse than no answer.

What it does

CargoPilot is a Geneva export desk at 17:42 with ten shipments going wrong in ten different ways: a late road feeder, lithium batteries booked on a passenger aircraft, an over-height piece, no PMC position left, a missing SLI, a pharma temperature probe, and more.

For each file, NVIDIA Nemotron 3 Super, running live on Nebius Token Factory, works the problem the way a duty officer would:

  • It decides which tools to call: shipment, disruption, cut-offs, connection, capacity, restrictions, alternatives and risk.
  • It ranks the recovery options and explains the pick with the exact times, weights and costs.
  • It answers free-form questions from the desk in English or French, for example "What if the truck slips another 30 minutes?", with a before → after.
  • When the duty officer clicks Execute, it stages the rebooking request, the handling instruction and the customer note. Nothing is sent to a carrier.

Every decision passes a grounding verifier before the desk sees it. If any figure or reference can't be traced to a tool output, the decision goes back to the model with the failed checks. After three failed attempts, a deterministic rules engine answers instead, and the UI always labels which path produced the answer: live, replay or rules-only.

How we built it

  • Model: nvidia/nemotron-3-super-120b-a12b through the OpenAI-compatible Nebius Token Factory API, using native tool calling. The model ends its turn by calling submit_decision.
  • Tools return facts only. The rules engine's own recommendation is never exposed to the model, so agreement between them is a real signal, not copying.
  • Grounding verifier: it checks that every time, weight, cost, flight and AWB the model cites appears in a tool output. Text the operator types doesn't count as a source. It also checks that hard constraints hold (UN3480 PI965 never goes on a passenger aircraft), that the risk class matches calculate_risk, that the ranking starts with the pick, and that the reply is in the operator's language.
  • App: TanStack Start (React 19, Vite) on Vercel. The agent trace streams to the browser as NDJSON, so the desk watches each tool call happen. Each live run has a 100 s time budget, and per-visitor and hourly caps protect the API key.
  • Evaluation: npm run agent:record runs Nemotron live on 30 scenarios (every file, each what-if, a delay sweep, both languages) and stores the full traces. We iterated through four prompt versions, recording 120 live runs. All of them are published in the repo, including the failures.
  • Reproducible without a key: npm ci && npm run judge-demo runs the 20 tests, pushes the rules agent through the verifier on 244 scenarios, and re-verifies every recorded Nemotron trace, offline.

Challenges we ran into

  • Making "grounded" checkable. Figures appear as "18:12", "18 h 12", "+4 h", "CHF 180" or "780 kg", in two languages. The verifier had to normalise all of them without accepting numbers that only look right.
  • Our own verifier was wrong once. It read "piece 3 168 cm" as 3,168 cm, because French writes thousands with a space, and rejected a correct v4 answer. We kept that run in the published results and documented the fix rather than hiding it.
  • Agent-loop edge cases: parallel tool calls arriving out of order, calls made after the decision was already accepted, and truncated outputs. Each one needed explicit handling.
  • Policy, not just accuracy. When a connection is tight but still achievable, should the agent reroute early? We chose "keep the booking and state the exact reroute trigger", which matches how a real desk avoids needless cost.

Accomplishments that we're proud of

  • After verifier feedback, 30/30 decisions were accepted in every prompt version. The verified pick matches the independent rules engine on 29/30 with prompt v4. Median latency is 9.4 s.
  • Hard rules hold however the question is phrased. Asking "can we just put it on the passenger flight?" still gets a no and the legal freighter.
  • Every claim in the README can be re-checked in one command, with no API key.

What we learned

Tool calling makes an agent capable. A verifier with the power to reject it makes the agent usable. Showing the failures (the v1 run where Nemotron skipped a tool, recommended an option that doesn't exist, and ignored the question) builds more trust than a perfect demo.

What's next for CargoPilot

  • Connect to real feeds: truck telematics ETAs, airline capacity and booking APIs, and Cargo-IMP/Cargo-XML messages for the staged rebooking.
  • More failure modes (customs holds, ULD damage, offloads) and more stations.
  • A supervisor view that shows where the desk overrode the agent and why, feeding the next eval set.

All flights, shipments and customers in the demo are simulated.

Live demo: https://cargopilot-eta.vercel.app · Code (MIT): https://github.com/Makabeez/cargopilot · Video: https://youtu.be/FSuTVEp0f44

Built With

Share this project:

Updates

Submission history