Kapso is an official Chat SDK Adapter

By Rodrigo Gaona

Kapso’s Chat SDK adapter lets developers build WhatsApp agents with one TypeScript handler, signed Kapso webhooks, native buttons, media attachments, reactions, outbound DMs, and Kapso-backed conversation history.

Kapso is an official Chat SDK Adapter

Today we are releasing @kapso/chat-adapter, the Kapso-maintained WhatsApp adapter for Chat SDK.

If you are building an AI support agent, operations assistant, onboarding bot, or any workflow that needs to live inside WhatsApp, this adapter gives you the Chat SDK interface you already know with Kapso’s WhatsApp infrastructure underneath.

Why this matters

Chat SDK gives developers a standard TypeScript interface for chat agents. Instead of writing one bot for Slack, another for Discord, another for Teams, and another for WhatsApp, you write the agent logic once:

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

The adapter does the platform work: webhook verification, message parsing, thread IDs, formatting, API calls, buttons, files, reactions, and history.

WhatsApp is worth supporting well because it is where many customers already talk to businesses. But WhatsApp automation has a lot of edge cases: connected numbers, Meta payloads, signatures, media upload and download, interactive replies, conversation history, templates, and the difference between testing and production infrastructure.

Kapso already handles the WhatsApp side. The new adapter bridges that into Chat SDK so your agent can treat WhatsApp like a first-class chat surface.

Install

npm install chat @kapso/chat-adapter @chat-adapter/state-memory

For production, use a durable Chat SDK state adapter instead of in-memory state. The memory adapter is great for local development and tests.

Quick start

Create a shared Chat SDK instance and register Kapso as a platform adapter:

import { Chat } from "chat";
import { createMemoryState } from "@chat-adapter/state-memory";
import { createKapsoAdapter } from "@kapso/chat-adapter";

export const bot = new Chat({
  userName: "support",
  state: createMemoryState(),
  adapters: {
    kapso: createKapsoAdapter(),
  },
});

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

Then add a webhook route. In a Next.js App Router project:

import { bot } from "@/lib/bot";

export async function POST(request: Request): Promise<Response> {
  return bot.webhooks.kapso(request);
}

Configure a Kapso webhook for whatsapp.message.received, point it at that route, and use the same secret as KAPSO_WEBHOOK_SECRET.

KAPSO_API_KEY=your_project_api_key
KAPSO_PHONE_NUMBER_ID=your_phone_number_id
KAPSO_WEBHOOK_SECRET=your_webhook_secret

That is enough for inbound WhatsApp messages to reach your Chat SDK handlers and for thread.post() replies to go back through Kapso.

What you can build

Customer support agents

Run a support agent that responds inside WhatsApp while keeping the same Chat SDK code you use elsewhere.

bot.onDirectMessage(async (thread, message) => {
  const history = await thread.adapter.fetchMessages(thread.id, { limit: 20 });

  const answer = await answerCustomer({
    latestMessage: message.text,
    history: history.messages,
  });

  await thread.post(answer);
});

Kapso-backed history means your agent can fetch previous WhatsApp messages instead of relying only on what happened during the current process lifetime.

Approval flows with buttons

Chat SDK cards with actions map to WhatsApp reply buttons:

import { Actions, Button, Card } from "chat";

await thread.post(
  Card({
    title: "Approve refund?",
    children: [
      Actions([
        Button({ id: "approve", label: "Approve", value: "refund-123" }),
        Button({ id: "reject", label: "Reject", value: "refund-123" }),
      ]),
    ],
  }),
);

bot.onAction("approve", async (action) => {
  await action.thread?.post(`Approved ${action.value}`);
});

WhatsApp supports up to three reply buttons. The Kapso adapter validates that limit and validates button labels, so production behavior is explicit instead of silently dropping actions.

Media workflows

Send receipts, images, audio, videos, documents, and stickers through Chat SDK file attachments:

await thread.post({
  markdown: "Here is the receipt.",
  files: [
    {
      filename: "receipt.pdf",
      mimeType: "application/pdf",
      data: await fs.promises.readFile("receipt.pdf"),
    },
  ],
});

Inbound media becomes Chat SDK attachments. When Kapso provides a mirrored media URL, the attachment includes url. When a WhatsApp media ID is available, the adapter can lazily fetch the file data through Kapso.

Outbound WhatsApp conversations

If your app needs to start a conversation, use openDM():

import type { KapsoAdapter } from "@kapso/chat-adapter";

const adapter = bot.getAdapter("kapso") as KapsoAdapter;
const threadId = await adapter.openDM("15551234567");
const thread = bot.thread(threadId);

await thread.post("Hello from Kapso.");

The adapter encodes WhatsApp phone number IDs, customer WhatsApp IDs, and Kapso conversation IDs into stable Chat SDK thread IDs. You can use the exported helpers to encode and decode those IDs instead of constructing them manually.

Why Kapso is the right WhatsApp layer for Chat SDK

This adapter is intentionally Kapso-first.

There is already a low-level WhatsApp Cloud API adapter in the Chat SDK ecosystem. Kapso solves a different problem: getting AI agents and product teams onto WhatsApp faster, with infrastructure around setup, storage, operations, webhooks, media, and developer tooling.

With Kapso, you can:

  • Connect a WhatsApp number with the Kapso CLI
  • Inspect numbers, messages, conversations, templates, and webhooks from the terminal
  • Let agents operate WhatsApp through Project MCP without shell access
  • Give coding agents current docs through llms.txt and the Docs MCP
  • Install Kapso agent skills so AI coding tools follow Kapso-specific integration patterns
  • Use the open-source Kapso TypeScript SDK directly when you need APIs outside Chat SDK’s adapter surface

The Chat SDK adapter is the runtime piece of that stack. The CLI helps you set up and operate projects. MCP lets agents work with live Kapso resources. Skills help coding agents edit your codebase correctly. The adapter lets your application receive and respond to WhatsApp messages with standard Chat SDK primitives.

Get started

Install the adapter:

npm install chat @kapso/chat-adapter @chat-adapter/state-memory

Create a Kapso project, connect a WhatsApp number, and set your environment variables:

KAPSO_API_KEY=your_project_api_key
KAPSO_PHONE_NUMBER_ID=your_phone_number_id
KAPSO_WEBHOOK_SECRET=your_webhook_secret

Then wire your Chat SDK webhook route:

export async function POST(request: Request): Promise<Response> {
  return bot.webhooks.kapso(request);
}

Thanks for reading.

Links