Multi-Branch AI Messenger Chatbot
An AI chatbot handling customer inquiries and bookings across multiple branches of a motorcycle service business, built as a router with specialist sub-agents rather than one monolithic bot.
Branches fielding inquiries by hand, with replies taking hours and no consistent coverage.
A multi-branch service business was losing sales to slow replies. Inquiries arrived on Messenger at all hours, staff answered them by hand between other work, and response times stretched into hours. By the time someone replied, the customer had often gone elsewhere.
Rather than one bot trying to do everything, I built a Master Router Agent that classifies each incoming conversation and dispatches it to a specialized sub-agent: parts and compatibility lookup, pricing, order status, or general inquiry. Each sub-agent has a narrower job and its own context boundaries, which makes it far more accurate than a single catch-all prompt.
Context is passed between agents using thread identifiers, so a specialist picking up a conversation gets the relevant history without reprocessing everything. Retrieval-augmented generation (RAG) over a Supabase pgvector store grounds answers in real product and compatibility data instead of letting the model guess. The system routes between model tiers based on task complexity, keeping cost proportional to difficulty: the cheap model handles the high-frequency classification and routing path, the larger model is reserved for the calls that genuinely need reasoning over messy input, and Claude handles the long-context work. The rule is the smallest model that clears the accuracy bar for that step, not one model for the whole system.
The part that bites you in production is payload shape. Meta's webhook does not send one structure: a plain text message, a photo, a video and a sticker or emoji each arrive shaped differently, and those shapes change when Meta updates the API. Any handler that assumes the structure it saw yesterday will break on a customer sending a photo instead of a sentence. So the ingestion layer validates message type before routing and handles each type explicitly, rather than reaching for a field that may not be there.

