Direct Messages

Use bot.openDM() to open a direct message conversation with a user. When the user ID format is unique to one platform, Chat SDK infers the adapter from the ID.

DM behavior

DMs behave slightly differently from channel messages:

  • If you register onDirectMessage, every incoming DM routes there before onSubscribedMessage, onNewMention, and pattern handlers. DM-centric flows such as WhatsApp conversations, Telegram DMs, and web chat then run through one handler.
  • If no onDirectMessage handlers are registered, DMs continue through normal routing. Unsubscribed DMs are treated as mentions, so existing onNewMention bots keep working without the user having to @-mention the bot.
  • Each top-level DM starts a new conversation. Thread replies within a DM continue the same conversation, giving you the same per-thread isolation as channels.

Handle incoming DMs

lib/bot.ts
bot.onDirectMessage(async (thread, message) => {
  await thread.post(`You said: ${message.text}`);
});

Open a DM

From an Author object

The most common pattern is to pass the author from an incoming message:

lib/bot.ts
bot.onSubscribedMessage(async (thread, message) => {
  if (message.text === "DM me") {
    const dmThread = await bot.openDM(message.author);
    await dmThread.post("Hello! This is a private message.");
  }
});

From a user ID

Pass a user ID string directly. The adapter is inferred from the ID format:

lib/bot.ts
const dmThread = await bot.openDM("U1234567890"); // Slack
FormatPlatform
U... / W...Slack
29:...Teams
users/...Google Chat
Numeric IDDiscord or Telegram

Numeric IDs can be ambiguous when multiple numeric-ID adapters are registered. For platforms whose user IDs are not globally distinguishable, call the adapter directly and wrap the returned thread ID with bot.thread().

lib/bot.ts
const threadId = await bot.getAdapter("whatsapp").openDM("15551234567");
const dmThread = bot.thread(threadId);

Check if a thread is a DM

lib/bot.ts
bot.onSubscribedMessage(async (thread, message) => {
  if (thread.isDM) {
    await thread.post("This is a private conversation.");
  }
});

Read more