Create a custom AI chatbot with TalkJS and Claude
AI chatbots like Anthropic's Claude can provide automated, context-aware responses to all kinds of queries. With TalkJS, you can create a customizable chat application that integrates chatbot responses seamlessly into your user chat.
In this tutorial we'll show you how to use Anthropic's API to generate replies to user messages using the Claude family of language models. We'll then use TalkJS's REST API and webhooks to add Claude's responses directly to your chat:
To follow along with this tutorial, you will need:
- A TalkJS account. TalkJS provides a ready-to-use chat client for your application. Your account gives you access to TalkJS's free development environment.
- An existing TalkJS project using the JavaScript Chat SDK. See our Getting Started guide for an example of how to set this up.
- An installation of Node.js along with the npm package manager. We’ll use this to create our backend server.
- An Anthropic API account and API key.
We’ll build up the feature step by step in the following sections. If you would rather see the complete example code, see the Github repo for this tutorial.
First, we'll set up a TalkJS chat in our frontend code. The details will depend on exactly how you integrate TalkJS into your current application, but for our example we'll use TalkJS's JavaScript SDK to create a conversation between a user and a bot, and display it with our prebuilt chatbox UI:
Talk.ready.then(function () {
const me = new Talk.User({
id: "claudeExampleUser",
name: "Alice",
email: "alice@example.com",
role: "default",
photoUrl: "https://talkjs.com/images/avatar-1.jpg",
});
const talkSession = new Talk.Session({
appId: "<APP_ID>", // replace with your TalkJS app ID
me: me,
});
const bot = new Talk.User({
id: "claudeExampleBot",
name: "Bot 🤖",
email: "bot@example.com",
role: "default",
photoUrl: "https://talkjs.com/new-web/talkjs-logo.svg",
welcomeMessage:
"Hi, I'm a friendly chatbot! I'll use Anthropic's chat API to assist with your queries. How can I help?",
});
var conversation = talkSession.getOrCreateConversation(
"claudeExampleConversation"
);
conversation.setParticipant(me);
conversation.setParticipant(bot);
const chatbox = talkSession.createChatbox();
chatbox.select(conversation);
chatbox.mount(document.getElementById("talkjs-container"));
});
We've included a welcomeMessage
for the bot to start the conversation off.
Get notified about new messages
We'll eventually want the bot to reply to any messages that the user sends in the conversation. To do this, we'll first enable TalkJS webhooks, which allow the TalkJS server to notify your server when a message is sent.
Webhooks let you use an event-driven architecture, where you get told about events when they happen rather than having to constantly check for new messages. There are lots of events you can listen for, but we’re only interested in new messages being sent.
Webhooks are server-side only, so you’ll need a web server. We’ll be using Express in this tutorial, but feel free to use your favorite web server library instead. The following code sets up an Express server with a POST endpoint at /onMessageSent
that logs incoming events from the TalkJS server to the terminal:
import express from "express";
const app = express().use(express.json()); // creates http server
app.listen(3000, () => console.log("Server is up"));
app.post("/onMessageSent", (req, res) => {
console.log(req.body);
res.status(200).end();
});
For TalkJS to communicate with your server, you must expose it to the internet. This can be very difficult when developing locally, with endless firewalls and port forwarding to set up. Instead, we’ll use ngrok to create a secure tunnel to your local server. See our tutorial on How to integrate ngrok with TalkJS for instructions on how to install ngrok.
Once you have installed ngrok, run the following command:
ngrok http 3000
This command starts a secure tunnel to your local port 3000. The output should include the URL that ngrok exposes:
Forwarding https://<YOUR_SITE>.ngrok-free.app -> http://localhost:3000
You’re now ready to enable webhooks. You can do this in the Settings section of the TalkJS dashboard, under Webhooks. Paste the ngrok URL into the Webhook URL field, including the /onMessageSent
path: https://<YOUR_SITE>.ngrok-free.app/talkjs.
Select the message.sent option:
TalkJS will now send a web request to your server when a message is sent. To test this, write a message in your chat UI. You should see the event in your server’s console.
Call the Anthropic API
Next, we'll call the Anthropic create message API to generate replies to the user's messages.
The API call uses a secret key, so you'll need to call it from your backend server to avoid exposing the key.
First, install the @anthropic-ai/sdk
package:
npm install @anthropic-ai/sdk
Then, as a first test of the API, add the following to your server code:
import Anthropic from "@anthropic-ai/sdk";
const anthropicSecretKey = "<ANTHROPIC_SECRET_KEY>";
const anthropic = new Anthropic({
apiKey: anthropicSecretKey,
});
const messageHistory = [
{
role: "user",
content:
"You are a helpful assistant. Please provide short, concise answers.",
},
];
async function getReply(messageHistory) {
const response = await anthropic.messages.create({
model: "claude-3-haiku-20240307",
messages: messageHistory,
max_tokens: 1024,
});
return response.content[0].text;
}
The getReply
function calls the Anthropic API to create a message in response, given a messageHistory
list that represents the conversation so far.
In this first test example, we send a messageHistory
list that has a single message with a role
of user
. This initial user message gives some basic instructions on the type of replies we'd like to receive.
We also need to select one of Anthropic's language models to generate the reply. In this example, we use the Haiku 3 model, claude-3-haiku-20240307
, which is faster and cheaper but less capable than the Sonnet models. You can switch this out for a different model if you like. See Anthropic's list of models for more choices.
Next, update your app.post
call to call the getReply
function:
const botId = "chatbotExampleBot";
app.post("/onMessageSent", async (req, res) => {
if (senderId != botId) {
const reply = await getReply(messageHistory);
console.log(reply);
}
res.status(200).end();
});
We do not call the Anthropic API for messages from the bot, or it will get stuck in a loop of responding to itself!
Restart your server, and send another message. You should see a response logged to your terminal. At the moment, the response is very generic (something like "Okay, I'll provide short, concise answers."
),because it only has the instructions in the initial user message to work with. We want to instead give it the full conversation so far, so that it can reply with something relevant. To do this, replace your app.post
call with the following code, which creates a message history for each conversation:
const allMessageHistory = {};
app.post("/onMessageSent", async (req, res) => {
const convId = req.body.data.conversation.id;
const messageText = req.body.data.message.text;
const senderId = req.body.data.sender.id;
if (!(convId in allMessageHistory)) {
allMessageHistory[convId] = [
{
role: "user",
content:
"You are a helpful assistant. Please provide short, concise answers.",
},
];
}
const messageHistory = allMessageHistory[convId];
if (senderId == botId) {
// Bot message
messageHistory.push({ role: "assistant", content: messageText });
} else {
// User message
messageHistory.push({ role: "user", content: messageText });
getReply(messageHistory);
}
res.status(200).end();
});
You should now see a relevant reply logged to the terminal when you restart the server and send a message.
Call the TalkJS API
The final step is to display the bot's replies as messages in the chatbox. To do this, create a function to call the TalkJS REST API to send messages from the bot:
const appId = "<APP_ID>";
const talkJSSecretKey = "<TALKJS_SECRET_KEY>";
const basePath = "https://api.talkjs.com";
const conversationId = "claudeExampleConversation";
async function sendMessage(text) {
return fetch(
`${basePath}/v1/${appId}/conversations/${conversationId}/messages`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${talkJSSecretKey}`,
},
body: JSON.stringify([
{
text: text,
sender: botId,
type: "UserMessage",
},
]),
}
);
}
As with the Anthropic API, you should call the TalkJS API from your backend server to avoid exposing your secret key. You can find your secret key along with your app ID in the TalkJS dashboard under Settings.
Now you can call the sendMessage
function after getReply
:
app.post("/getMessages", async (req, res) => {
// ...
if (senderId == botId) {
// Bot message
messageHistory.push({ role: "assistant", content: messageText });
} else {
// User message
messageHistory.push({ role: "user", content: messageText });
const reply = await getReply(messageHistory);
await sendMessage(convId, reply);
}
res.status(200).end();
});
The responses from the Claude now appear in the chatbox as messages from the bot:
Customize your chat
You now have a working demonstration of how to integrate a Claude-powered chatbot into your TalkJS chat!
You may want to customize your chat further. For example, you could include an indicator in your chat that the bot is generating a response. See our blog post on How to add a custom typing indicator for a chatbot for information on ways to do this.
You can also use all our other features, such as custom themes, action buttons and HTML Panels, to control exactly how you want the chat to look and behave.
Summary
To recap, in this tutorial we have:
- Created a chat between a user and a bot
- Set up a web server to receive webhook events from the TalkJS server when new messages are sent
- Called the Anthropic API to generate replies to new user messages
- Called the TalkJS API to send the replies as messages in the chat
For the full example code for this tutorial, see our Github repo.
If you want to learn more about TalkJS, here are some good places to start:
- The TalkJS Docs help you get started with TalkJS.
- TalkJS tutorials provide how-to guides for many common TalkJS use cases.
- The talkjs-examples Github repo has larger complete examples that demonstrate how to integrate with other libraries and frameworks.