
How to Connect WhatsApp to DeepSeek
DeepSeek exposes an OpenAI-compatible API, so you can use the same openai npm package — just point it at DeepSeek's endpoint. This makes it easy to swap between OpenAI, DeepSeek, and other compatible providers.
Prerequisites
- A paired whatsmeow-node session (How to Pair)
- A DeepSeek API key (set as
DEEPSEEK_API_KEYenvironment variable) — get one at platform.deepseek.com - The OpenAI SDK:
npm install openai
Step 1: Set Up Both Clients
The only difference from OpenAI is the baseURL and API key:
import { createClient } from "@whatsmeow-node/whatsmeow-node";
import OpenAI from "openai";
const client = createClient({ store: "session.db" });
const openai = new OpenAI({
baseURL: "https://api.deepseek.com",
apiKey: process.env.DEEPSEEK_API_KEY,
});
const SYSTEM_PROMPT = "You are a helpful WhatsApp assistant. Keep responses concise — under 500 characters when possible, since this is a chat interface.";
Step 2: Handle Incoming Messages
client.on("message", async ({ info, message }) => {
if (info.isFromMe) return;
const text =
(message.conversation as string) ??
(message.extendedTextMessage as { text?: string } | undefined)?.text;
if (!text) return;
await client.sendChatPresence(info.chat, "composing");
const reply = await askDeepSeek(info.sender, text);
await client.sendMessage(info.chat, { conversation: reply });
});
Step 3: Send to DeepSeek
async function askDeepSeek(userJid: string, userMessage: string): Promise<string> {
const response = await openai.chat.completions.create({
model: "deepseek-chat",
messages: [
{ role: "system", content: SYSTEM_PROMPT },
{ role: "user", content: userMessage },
],
});
return response.choices[0].message.content ?? "I couldn't generate a response.";
}
DeepSeek also offers deepseek-reasoner for complex reasoning tasks. Swap the model name to try it.
Step 4: Add Conversation History
Since DeepSeek uses the OpenAI-compatible format, the history pattern is identical:
import type { ChatCompletionMessageParam } from "openai/resources/chat/completions";
const conversations = new Map<string, ChatCompletionMessageParam[]>();
const MAX_HISTORY = 20;
async function askDeepSeek(userJid: string, userMessage: string): Promise<string> {
const history = conversations.get(userJid) ?? [];
history.push({ role: "user", content: userMessage });
if (history.length > MAX_HISTORY) {
history.splice(0, history.length - MAX_HISTORY);
}
const response = await openai.chat.completions.create({
model: "deepseek-chat",
messages: [{ role: "system", content: SYSTEM_PROMPT }, ...history],
});
const reply = response.choices[0].message.content ?? "I couldn't generate a response.";
history.push({ role: "assistant", content: reply });
conversations.set(userJid, history);
return reply;
}
Complete Example
import { createClient } from "@whatsmeow-node/whatsmeow-node";
import OpenAI from "openai";
import type { ChatCompletionMessageParam } from "openai/resources/chat/completions";
const client = createClient({ store: "session.db" });
const openai = new OpenAI({
baseURL: "https://api.deepseek.com",
apiKey: process.env.DEEPSEEK_API_KEY,
});
const SYSTEM_PROMPT =
"You are a helpful WhatsApp assistant. Keep responses concise — under 500 characters when possible, since this is a chat interface.";
const conversations = new Map<string, ChatCompletionMessageParam[]>();
const MAX_HISTORY = 20;
async function askDeepSeek(userJid: string, userMessage: string): Promise<string> {
const history = conversations.get(userJid) ?? [];
history.push({ role: "user", content: userMessage });
if (history.length > MAX_HISTORY) {
history.splice(0, history.length - MAX_HISTORY);
}
const response = await openai.chat.completions.create({
model: "deepseek-chat",
messages: [{ role: "system", content: SYSTEM_PROMPT }, ...history],
});
const reply = response.choices[0].message.content ?? "I couldn't generate a response.";
history.push({ role: "assistant", content: reply });
conversations.set(userJid, history);
return reply;
}
client.on("message", async ({ info, message }) => {
if (info.isFromMe) return;
const text =
(message.conversation as string) ??
(message.extendedTextMessage as { text?: string } | undefined)?.text;
if (!text) return;
console.log(`${info.pushName}: ${text}`);
await client.sendChatPresence(info.chat, "composing");
try {
const reply = await askDeepSeek(info.sender, text);
await client.sendMessage(info.chat, { conversation: reply });
console.log(`→ ${reply.slice(0, 80)}...`);
} catch (err) {
console.error("DeepSeek API error:", err);
await client.sendMessage(info.chat, {
conversation: "Sorry, I'm having trouble right now. Try again in a moment.",
});
}
});
client.on("logged_out", ({ reason }) => {
console.error(`Logged out: ${reason}`);
client.close();
process.exit(1);
});
async function main() {
const { jid } = await client.init();
if (!jid) {
console.error("Not paired! See: How to Pair WhatsApp");
process.exit(1);
}
await client.connect();
await client.sendPresence("available");
console.log("DeepSeek bot is online!");
process.on("SIGINT", async () => {
await client.sendPresence("unavailable");
await client.disconnect();
client.close();
process.exit(0);
});
}
main().catch(console.error);
Switching Between Providers
Since DeepSeek, OpenAI, and many other providers use the same API format, you can make the provider configurable:
const openai = new OpenAI({
baseURL: process.env.AI_BASE_URL ?? "https://api.openai.com/v1",
apiKey: process.env.AI_API_KEY,
});
const model = process.env.AI_MODEL ?? "gpt-4o";
This works with any OpenAI-compatible provider — DeepSeek, Groq, Together AI, Mistral, and more.
Common Pitfalls
Always check info.isFromMe first. Without this, the bot replies to its own messages forever.
Never hardcode your API key in the source. Use environment variables or a .env file (added to .gitignore).





