The Client
A logistics company serving both business and consumer customers, shipping domestically and internationally. Its support queue is dominated by a handful of request types — where is my package, what will this shipment cost, schedule a pickup, my delivery arrived damaged — each of which requires looking up or changing real operational data.
The Problem
Logistics support isn't a conversation problem — it's an action problem. "Where is SHP-2024-091834?" needs a live tracking lookup. "How much to ship 15 kg to London?" needs a rate calculation with customs and documentation fees. A chatbot that can only talk sends every one of these to a human anyway, adding a frustrating extra step instead of removing one.
The Solution
We built the agent around LLM tool-calling over a real function library: the model decides which operation the customer needs, calls it with validated parameters, and presents the result as a rich response card — a tracking timeline, an itemized quote, a pickup confirmation.
tracking — live shipment status with timeline and delay banners
rates — domestic + international quotes (tax, customs, documentation)
pickup — schedule pickups with service-area validation
accounts — balance, invoices, recent shipments
issues — damage/loss claims with case tracking
escalations — automatic human handoff on refund requests and high-severity issues
- Rich chat UI with five response card types and quick actions — answers you can read at a glance, not walls of text
- Deterministic fallback router: if the LLM is unavailable, rule-based routing keeps every core flow working
- Input validation and error handling around every tool, so the model can never write bad data
- Damage claims auto-escalate to humans with full conversation context attached
- Works across B2B and B2C account types with per-account context
The Stack
A React + Tailwind chat front end over an Express agent backend. The agent layer supports Claude and OpenAI tool-calling interchangeably, with the rule-based router as a zero-dependency fallback. Operational data lives in SQLite via Node's built-in driver — the entire system deploys as a single container.
The Outcome
The routine 80% of support traffic — tracking, quotes, pickups, account questions — resolves instantly and correctly without a human touching it, while the genuinely hard cases arrive at the support team pre-triaged with full context. And because of the fallback router, an LLM outage degrades the experience instead of taking support offline. Try the live demo below.