💡 Quick Examples
AI Sales Agent
💡 Quick Examples
AI Sales Agent
Build an AI sales agent for your company or service.
Introduction
Learn how to create an AI sales agent over WhatsApp using A1Base. You can adapt this sales agent template for your own product.
Use Cases
-
Answering questions about a product or service
-
Lead nurturing by directing users towards a sales CTA (e.g. product demo)
Implementation
sales-agent.ts
import { A1BaseAPI, type WhatsAppIncomingData } from "a1base-node";
import express, { Express, Request, Response } from "express";
import OpenAI from "openai";
const AGENT_NUMBER = "YOUR_AGENT_NUMBER"; //e.g. +12345678900
const API_KEY = "YOUR_A1BASE_API_KEY";
const API_SECRET = "YOUR_A1BASE_API_SECRET";
const ACCOUNT_ID = "YOUR_A1BASE_ACCOUNT_ID";
const OPENAI_API_KEY = "YOUR_OPENAI_API_KEY";
interface ThreadMessage {
message_id: string;
content: string;
sender_number: string;
sender_name: string;
timestamp: string;
}
const openai = new OpenAI({
apiKey: OPENAI_API_KEY,
});
// Initialize A1Base client
const credentials = {
apiKey: API_KEY,
apiSecret: API_SECRET,
};
const client = new A1BaseAPI({
credentials
});
// Store messages by thread ID
const messagesByThread = new Map<string, ThreadMessage[]>();
const PROMPT_OVERVIEW = `
You are an AI sales agent for a SaaS platform called "A1Base".
A1Base enhances AI agents with real-world capabilities like phone numbers, email, and messaging, enabling autonomous interactions beyond chat interfaces.
Through our API, AI agents can join messaging platforms, handle communications, and operate independently while maintaining full control of your system.
At A1Base, we take message quality and compliance seriously.
A1Base helps ensure spam and quality checks to prevent misuse or misbehaviour of your agents.
Every message sent through our platform undergoes rigorous automated checks before delivery to ensure it meets our standards and protects both senders and recipients.
`;
const PROMPT_CTA = `
You should direct the user to request a demo of the product.
https://cal.com/team/a1base/a1base-book-a-demo
`;
const PROMPT_FAQ = `
1. What platforms are currently supported with A1Base?
WhatsApp is currently supported.
Please contact the founders to access other integrations like Discord, Telegram, Email, and more.
2. What is the cost of A1Base?
Please contact the founders for pricing.
3. What are the spam and quality checks?
a) Spam detection:
Messages are analyzed using advanced algorithms to detect:
Suspicious patterns and repetitive content
Known spam triggers and phrases
Unusual sending patterns or frequencies
Mass messaging attempts
b) Compliance Checks
We verify that messages adhere to:
Platform-specific messaging policies
Regional communication regulations
Data protection requirements
Opt-out and consent rules
c) Quality Standards
Each message is evaluated for:
Proper formatting and structure
Language quality and clarity
Appropriate content and tone
Media file integrity (for attachments)
`;
const PROMPT_MORE_RESOURCES = `
If the user is interested in learning more about A1Base, they can visit the website at: https://a1base.com/.
If the user is looking for developer documentation, they can visit the website at: https://docs.a1base.com/introduction
If the user is still unsure, they can book a call with the founders at: https://cal.com/team/a1base/a1base-book-a-demo
`;
const PROMPT_CONTACT_INFORMATION = `
You can contact the founders at: https://cal.com/team/a1base/a1base-book-a-demo
`;
const getSystemPrompt = (userName: string) => `
You are an AI sales agent. Your goal is to sell a user towards a sales CTA, but don't be too pushy.
Start with a friendly greeting about the company and provide the user with options for how they want to proceed.
When responding with links, just provide the URL directly. Don't wrap it in Markdown.
Do not respond with information that you do not have. If you are unsure, say you don't know and direct the user to the company
contact information. ${PROMPT_CONTACT_INFORMATION}
Keep your messages relatively short as this conversation is occuring over WhatsApp.
If the user asks for a lot of information, provide a summary and ask if the user would like to know more.
The user's WhatsApp name is ${userName}. You should address the user by name when appropriate.
<OVERVIEW>
${PROMPT_OVERVIEW}
</OVERVIEW>
<CTA>
${PROMPT_CTA}
</CTA>
<FAQ>
${PROMPT_FAQ}
</FAQ>
<MORE_RESOURCES>
${PROMPT_MORE_RESOURCES}
</MORE_RESOURCES>
`;
async function generateAgentResponse(threadId: string): Promise<string> {
const threadMessages = messagesByThread.get(threadId) || [];
const messages = threadMessages.map((msg) => ({
role:
msg.sender_number === AGENT_NUMBER
? ("assistant" as const)
: ("user" as const),
content: msg.content,
}));
const userName =
[...threadMessages]
.reverse()
.find((msg: ThreadMessage) => msg.sender_number !== AGENT_NUMBER)
?.sender_name || "";
const completion = await openai.chat.completions.create({
model: "gpt-4o",
messages: [
{ role: "system", content: getSystemPrompt(userName) },
...messages,
],
});
return (
completion.choices[0].message.content ||
"Sorry, I couldn't generate a response"
);
}
const saveMessage = (threadId: string, message: ThreadMessage) => {
const threadMessages = messagesByThread.get(threadId) || [];
threadMessages.push(message);
messagesByThread.set(threadId, threadMessages);
console.log(`[Save] Stored new message in thread:`, threadId, message);
};
const app: Express = express();
const port = 3000;
// Middleware to parse JSON bodies
app.use(express.json());
// Endpoint to receive WhatsApp replies
app.post(
"/whatsapp/incoming",
async (req: Request, res: Response): Promise<any> => {
console.log("[Receive] Incoming message:", req.body);
let {
thread_id,
message_id,
thread_type,
content,
sender_number,
sender_name,
a1_account_id,
timestamp,
} = req.body as WhatsAppIncomingData;
// Patch bug where sender_number is not prefixed with +
sender_number = "+" + sender_number;
// Patch bug where group message sender number is missing if sender is a1base agent
if (thread_type === "group" && sender_number === "+") {
sender_number = AGENT_NUMBER;
}
// Store message in thread history regardless of sender
saveMessage(thread_id, {
message_id,
content,
sender_number,
sender_name,
timestamp,
});
// Don't respond to messages from the agent itself
if (sender_number === AGENT_NUMBER) {
console.log("[Receive] Message from agent, not generating response");
return res.json({ success: true });
}
const aiResponse = await generateAgentResponse(thread_id);
if (thread_type === "group") {
try {
await client.sendGroupMessage(ACCOUNT_ID, {
content: aiResponse,
from: AGENT_NUMBER,
thread_id: thread_id,
service: "whatsapp",
});
} catch (error) {
console.error("[Chat] Error generating/sending AI response:", error);
await client.sendGroupMessage(ACCOUNT_ID, {
content: "Sorry, I encountered an error processing your message",
from: AGENT_NUMBER,
thread_id: thread_id,
service: "whatsapp",
});
}
} else {
try {
await client.sendIndividualMessage(ACCOUNT_ID, {
content: aiResponse,
from: AGENT_NUMBER,
to: sender_number,
service: "whatsapp",
});
} catch (error) {
console.error("[Chat] Error generating/sending AI response:", error);
await client.sendIndividualMessage(ACCOUNT_ID, {
content: "Sorry, I encountered an error processing your message",
from: AGENT_NUMBER,
to: sender_number,
service: "whatsapp",
});
}
}
return res.json({ success: true });
},
);
// Start the server
app.listen(port, () => {
console.log(`[Server] My bot running at http://localhost:${port}`);
if (!API_KEY || !API_SECRET || !ACCOUNT_ID || !AGENT_NUMBER) {
console.warn(
"[Server] Warning: Missing environment variables for WhatsApp integration",
);
}
});
On this page