Skip to content
Get started
Integrations

Vercel Chat SDK

Build agents on iMessage and SMS with Vercel's Chat SDK, powered by Linq.

Chat SDK is Vercel’s framework for building chat agents. Write your bot’s logic once and run it across platforms through adapters. The Linq adapter is the iMessage and SMS channel — your agent sends and receives texts, media, and tapback reactions over Apple Messages and SMS, using the same handlers you’d write for any other platform.

The adapter is built and maintained by Linq and lives at github.com/linq-team/linq-chat-sdk.

Terminal window
npm install @linqapp/chat-sdk-adapter chat

chat is Vercel’s Chat SDK core; @linqapp/chat-sdk-adapter is the Linq channel.

import { createLinqAdapter } from "@linqapp/chat-sdk-adapter";
import { Chat } from "chat";
const chat = new Chat({
userName: "mybot",
adapters: {
linq: createLinqAdapter({
apiKey: process.env.LINQ_API_KEY!,
signingSecret: process.env.LINQ_WEBHOOK_SECRET!,
}),
},
});
chat.onDirectMessage(async (thread, message) => {
await thread.subscribe();
await thread.post(`you said: ${message.text}`);
});
chat.onReaction(["thumbs_up"], async (event) => {
await event.thread.post("appreciate the tapback 🫡");
});

Then route Linq webhooks to the adapter from any fetch-style handler:

// e.g. a Next.js / Nitro / Hono POST route
export default async (request: Request) => chat.webhooks.linq(request);
OptionRequiredDescription
apiKeyyesYour Linq API key.
signingSecretyesThe signing secret from your webhook subscription. Inbound requests are verified with HMAC-SHA256 over {timestamp}.{body} with replay protection.
baseURLnoOverride the API base URL.

The adapter is webhook-driven. Create a webhook subscription pointing at your route and subscribe to at least:

  • message.received
  • reaction.added
  • reaction.removed

See webhook events for the full payload reference. Any event type the adapter doesn’t handle is acknowledged with a 200 and ignored.

The adapter maps Linq onto the Chat SDK’s thread/message/reaction model, so standard APIs (thread.post, thread.subscribe, onDirectMessage, onNewMessage, onReaction) work unchanged.

  • Text — inbound and outbound, in DMs and group chats.
  • Media — inbound images, audio, and files arrive as attachments; outbound attachments/files are sent as media parts (public HTTPS URLs by reference, or pre-uploaded for larger/raw files).
  • Reactions — iMessage tapbacks map to Chat SDK emoji both ways (see below).
  • Typing indicators — supported in DMs (Linq rejects typing in groups).
  • Edits — outbound message text can be edited.

Streaming is buffered (recipients see one final message). Stickers, message deletion, and modals have no iMessage equivalent and are not supported.

Standard tapbacks map to normalized Chat SDK emoji in both directions:

Linq tapbackChat SDK emoji
likethumbs_up
dislikethumbs_down
loveheart
laughlaugh
emphasizeexclamation
questionquestion

Custom emoji reactions pass through the default resolver (e.g. 👍thumbs_up); anything unmapped falls back to the raw emoji. See reactions for how Linq models tapbacks.

Thread IDs are stable and always take the form linq:{chatId}, so a conversation maps to the same Chat SDK thread whether it first arrives via webhook or API.

The repo includes a full example — a server running one AI bot across Linq, Telegram, and WhatsApp from a single set of handlers.