Skip to content
ub3r.io

Chatbot Conversation Architecture · Chapter 2 · 14 min

Build a booking bot

Wire a small state machine to mx.bot and walk a simulated user through a booking.

Setting up the interaction

The foundation of a responsive bot is the message handler registered with the system via mx.bot.onMessage(handler), which fires for every incoming communication. To interact back with the user, you rely on mx.bot.reply(text) to send responses from your code. Simulating user interactions for testing is straightforward using mx.bot.receive(text), which allows you to programmatically script entire dialogue sequences. This setup provides the perfect environment for rapid development and testing of complex flows. By using these core methods, you can build a robust interface between your logic and the user.

Playground· A booking bot on mx.bot
output

Waiting for output…

Structuring the message handler

Your message handler should perform three distinct operations to process an incoming message successfully. First, it must interpret the raw text into a formal event that your system understands. Second, it uses that event to advance the state machine to the appropriate next state. Finally, it constructs and sends a reply tailored to the user's current situation, ensuring the dialogue feels coherent. This structured approach ensures that each step of the processing pipeline is clear and maintainable. Separation of duties within the handler makes debugging much easier when unexpected inputs occur.

Designing for future growth

Maintaining this clear separation between interpretation, state transition, and response construction is crucial for long-term scalability. By isolating these concerns, you gain the flexibility to add new conversational features, like changing a booking, without having to overhaul your existing logic. This modular design pattern is exactly what prevents technical debt from accumulating as your chatbot expands. A well-designed bot can grow significantly in complexity while remaining remarkably simple to understand for new engineers.

Building a bot is an iterative process that requires constant feedback and refinement. As you add new features, you should continuously evaluate whether your current architecture still supports your goals. If you find that adding a new state or transition is becoming difficult, it might be time to refactor your core logic. Keeping your bot's design clean and modular ensures that you can move quickly and respond to user needs effectively.

typescript
interface BotState {
  step: 'idle' | 'booking' | 'confirming';
  data: { date?: string; time?: string };
}
const handleMessage = (msg: string, state: BotState) => {
  const event = parseMessage(msg);
  const nextState = transition(state, event);
  return generateReply(nextState);
};

Validation and edge cases

When asking for specific data like time, you must handle various user formats such as "3pm", "15:00", and "15h" gracefully. If parsing fails, your system should stay in the current state and re-prompt the user with a helpful, clear example. Avoid the trap of repeating the exact same prompt more than twice; instead, refine your wording or offer a menu of options. Consistent validation logic ensures that your bot only proceeds when it has high-quality data that it can actually use.

Effective bot design is mostly about how you handle the moments when things go wrong. Your validation logic must be robust, and your error messages should always guide the user back to the correct path. By consistently managing state and validation, you build a bot that feels smart, helpful, and reliable to your end users. The goal is to minimize user frustration by being clear, concise, and helpful at every step of the interaction.

Discussion (3)

AT
Aiko Tanaka · 2026-10-05

Clear and opinionated. One nit: worth mentioning clock skew between producer and consumer when choosing the tolerance window.

ue
ub3r editors · 2026-10-12

Good point — we're adding a short section on this in the next revision.

SO
Samuel Okafor · 2026-10-06

The callout about alerting on queue age instead of depth changed how we page people. Thank you.