Skip to main content
Level: Intermediate · Tags: WhatsApp, Support, Handoff Features shown: human handoff · escape commands (allowCommands) · 'handoff', 'resume' and 'message' events · commands with arguments · sending outside a handler · bot.delay()

Prerequisites

  • Node.js 22.12 or newer and an empty folder with "type": "module" in its package.json (Getting started).

The complete bot

How it works

  1. The gate. While a chat is handed off the bot does not route its messages: no handlers, flows or catch-all. Only the commands listed in handoff.allowCommands that have a bot.command() still run, so /bot always brings the bot back.
  2. Starting a handoff. ctx.handoff() closes the gate for this chat and cancels any conversation in it. The handler that hands off can still reply.
  3. Telling the agents. The 'handoff' event fires once per handoff. bot.send(chatId, text) sends outside a handler, here to each agent’s own chat. The ticket number keeps the agent commands short.
  4. Relaying. Messages of a handed-off chat are still stored and still fire the 'message' event, which forwards them to the agents. (Your CRM or inbox would subscribe here.)
  5. Agent commands. bot.command('reply', (ctx, args) => ...) receives the words after the command. isAgent(ctx) checks the sender id, so anyone else typing /reply gets nothing.
  6. Back to the bot. bot.resume(chatId, { reason }) reopens the gate and fires 'resume' with that reason, whoever called it: the agent (/done), the user (/bot) or the timer.
  7. The timeout. bot.delay(AGENT_TIMEOUT, fn) runs once after 10 minutes; every agent reply restarts it. If no agent writes in time, the chat goes back to the bot with the timeout message. The 'resume' handler cancels the timer however the handoff ended.
The handoff state is saved in the store, so with a persistent store (SQLite, Redis) a chat stays with the agents after a restart. This example keeps tickets and timers in memory: rebuild them from bot.listHandoffs() on start if you need them to survive.

Try it

The agent is the user agent: :as agent switches to them, and the lines bot → agent › are what the bot sends to the agent’s chat.

Run it on WhatsApp or Telegram

Set AGENTS to the agents’ ids (send /id from each agent’s phone to learn them), then node bot.js and scan the QR from WhatsApp → Linked devices:
On Telegram the ids are numbers (AGENTS=123456789); install @botmesh/telegram and swap the provider as in Or connect Telegram.

Next steps