Let’s explore the CopilotKit, an open-source framework not just for generating content or ideas but also for working side by side with your users to automate tasks and get things done faster and easier.
Artificial intelligence (AI) is one of the most used two-word phrases in the tech world in recent years. Entrepreneurs, doctors, lawyers, mechanics, electricians—if you use an internet-enabled device, you have probably heard about artificial intelligence. Its use is ubiquitous and cuts across various industries, especially those with readily available, systematic and organized data.
Artificial intelligence is a field of computer technology that mimics human intelligence by building systems that can do things that previously only humans could do. Systems that have AI can recognize images and text, solve math equations, learn, reason, predict outcomes and even be creative enough to write poems and create images.
You can imagine how productive a person can be if they have a human assistant helping them perform basic, repetitive, non-creative or non-rewarding tasks. Now, imagine the productivity increase when an AI with non-human requirements to function helps you do these tasks—that means no days off or incentives needed for increased volume or quality of work.
Imagine an entity whose success can be directly linked to productivity, uptime and accuracy. Whether it be a business or an application, imagine enhancing that entity with powerful AI-driven capabilities. Well, you can stop imagining. We now have the CopilotKit.
In this article, we are going to explore the CopilotKit. An open-source framework that helps you achieve all that we just explained above in your application. It is not just for generating content or ideas but also for working side by side with your users to automate tasks and get things done faster and easier.
To follow this tutorial, you must be familiar with React.js, EmailJS and Tailwind CSS.
CopilotKit is an open-source framework that helps developers integrate Copilot AI into their applications. It helps you build powerful AI-powered features that understand your application’s data and take actions on your behalf.
Today, Copilot AI can be used to achieve a lot. Here are some use cases:
In this guide, we are going to build a Next.js application and embed Copilot AI into it to automate specific tasks—most importantly, sending emails.
We will also explore how Copilot AI can understand and respond to questions about our app’s data by feeding that data directly to it.
We will simulate a scenario where some users in our system have accounts that are not validated. So instead of manually emailing each of them to validate their account, we will designate that task to Copilot AI. It will handle the work of identifying those users and emailing them for us right from within our app.
This task would have otherwise required the administrator of the application to:
This daunting two-step task will be automated with one sentence in a chat prompt. Like so:
“Compose and send a personalized email to all users that are not validated, telling them to log in and validate their account”
That’s all!
Start by creating a folder where this application will live. Let us call it copilotapp
. Open your code editor and open the folder you just created.
Next, let’s set up our Next.js project. Run this command in your terminal:
npx create-next-app@latest
Run the following command to install the dependencies we will be needing:
npm install emailjs-com @copilotkit/react-ui @copilotkit/react-core
From left to right, we installed EmailJS and CopilotKit respectively. The EmailJS SDK will allow us to send emails. The CopilotKit module provides us with the necessary tools to craft the AI agent that automates tasks for us.
Notice there are two parts of that CopilotKit installation code block:
<CopilotKit>
provider and various hooks.<CopilotSidebar>
, <CopilotPopup>
, <CopilotChat>
and more in case you want to customize them.After installing all these, we can now begin building our dummy app called Tamar
.
You can either self-host or use the cloud-hosted version of the CopilotKit runtime. In our case, we will go with the latter. So at this point, assuming you have a CopilotKit account, let’s go to the dashboard to get all the credentials we will need to complete our integration.
On your dashboard, navigate to Api Key section.
Copy your Api key and head back to our application.
To have Copilot AI accessible from anywhere in our application, we need to import it and wrap our entire application with it. We will do this by editing the layout.js
file as follows:
import { CopilotKit } from "@copilotkit/react-core";
import "@copilotkit/react-ui/styles.css";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<CopilotKit publicApiKey="your_api_key">{children}</CopilotKit>
</body>
</html>
);
}
To enable global access to CopilotKit from anywhere within our app, we wrapped our root app’s layout with the CopilotKit
provider.
Let’s now embed the Copilot interface into page.js
in our app
"use client";
import { CopilotPopup } from "@copilotkit/react-ui";
export default function Home() {
return (
<div className="p-6">
<h1 className="text-3xl font-bold mb-4">Welcome to Tamar</h1>
<h2 className="text-1xl font-bold mb-4">Registered Users Table</h2>
<CopilotPopup
instructions="You are assisting the user as best as you can. Answer in the best way possible given the data you have."
labels={{
title: "My Copilot AI",
initial: "Do you need any help?",
}}
/>
</div>
);
}
CopilotKit UI ships with a variety of user interfaces that you can choose from:
Regardless of the CopilotKit chat interface you choose to implement, they are all customizable. You can play around with how you want it to look. For this guide though, we will be implementing the CopilotPopup
UI.
We have imported the CopilotPopup
component from the CopilotKit react-ui
and added the component to the bottom of our application.
The component has two props:
instructions
prop: This tells the AI how to behave when responding to user prompts.labels
prop: This is an object that contains the text in the popup chat user interface. title
is the header while initial
is the first message the AI sends to you when you open the chat.According to the official CopilotKit website, CopilotKit provides you with four main features when you integrate its AI into your React application:
Connecting our application data to CopilotKit will make our Copilot AI aware of our data. That is, it will now be able to answer questions about our data and analyze our data.
To do this, we need to take two steps:
useCopilotReadable
hook.The useCopilotReadable
hook requires two props:
CopilotKit allows you to connect your data either through the frontend or backend. CopilotKit does not care where your data comes from; it just needs the data in JSON format. Whether from an API or database call, just fetch the data like you would do in any React app.
You can also choose to have Copilot AI retrieve your data from the backend for you by defining actions that can be called by your Copilot.
If your data is already in the frontend, whether it is hardcoded, from a form, or from a previous API fetch request, you are halfway to connecting your data to CopilotKit.
So whatever way you got your data, store it in state. Then the next step is to pass that state into the useCopilotReadable
hook. In this guide, we will use data hard-coded on the frontend for easy access.
Update your page.js
file with the following:
"use client";
import { useCopilotReadable } from "@copilotkit/react-core";
import { CopilotPopup } from "@copilotkit/react-ui";
import { useState } from "react";
export default function Home() {
const [users] = useState([
{
name: "Janet Monrow",
email: "janet@yupmail.com",
dob: "23-01-1995",
validated: true,
},
{
name: "Nanret Rodriguez",
email: "nanret@yupmail.com",
dob: "02-03-1998",
validated: true,
},
{
name: "Jacob Costco",
email: "jacob@yupmail.com",
dob: "15-12-2000",
validated: false,
},
{
name: "Lilian Fisher",
email: "lilian@yupmail.com",
dob: "30-06-1995",
validated: true,
},
{
name: "Terdoo Lisan",
email: "terdoo@yupmail.com",
dob: "10-10-1995",
validated: true,
},
{
name: "johnny whip",
email: "johnny@yupmail.com",
dob: "12-08-1995",
validated: false,
},
]);
useCopilotReadable({
description: "A list of registered users in Tamar's website",
value: users,
});
return (
<div className="p-6">
<h1 className="text-3xl font-bold mb-4">Welcome to Tamar</h1>
<h2 className="text-1xl font-bold mb-4">Registered Users Table</h2>
<div className="overflow-x-auto">
<table className="min-w-full bg-white border border-gray-200 rounded-lg shadow-sm">
<thead>
<tr className="bg-gray-100 text-left text-sm font-semibold text-gray-600 uppercase">
<th className="p-3 border-b">Name</th>
<th className="p-3 border-b">Email</th>
<th className="p-3 border-b">Date Of Birth</th>
<th className="p-3 border-b">validated</th>
</tr>
</thead>
<tbody>
{users.map((user, i) => (
<tr key={i} className="border-t hover:bg-gray-50">
<td className="p-3">{user.name}</td>
<td className="p-3">{user.email}</td>
<td className="p-3">{user.dob}</td>
<td className="p-3">{user.validated ? "Yes" : "No"}</td>
</tr>
))}
</tbody>
</table>
</div>
<CopilotPopup
instructions="You are assisting the user as best as you can. Answer in the best way possible given the data you have."
labels={{
title: "My Copilot AI",
initial: "Do you need any help?",
}}
/>
</div>
);
}
The useCopilotReadable hook expects an object with two properties:
users
array.We also added a table that simply displays our users data.
Finally, let us start our local server by running the following command:
npm run dev
Now that it is up and running, let’s ask Copilot some interesting questions like what users are not validated in our users data.
As you can see, now our AI is context-aware. It can answer questions about the data we fed it. There are two ways to interact with the Copilot AI. You can talk to it directly, which is the usual and standard way (the way we just did). You can use something called CoAgents, which are like smarter assistants that can plan and execute tasks with more context (e.g., LangGraph and CrewAI).
AI can handle many tasks independently, but it needs clear instructions to achieve its objectives, especially when interfacing with external services. Now we are going to use the useCopilotAction
hook to define exactly what should happen and how it should happen.
Update your page.js
file so that Copilot AI can take action for us:
import { useCopilotAction, useCopilotReadable } from "@copilotkit/react-core";
useCopilotAction({
name: "sendEmailToUser",
description: "Send a custom email to a specific user",
parameters: [
{
name: "recipient",
type: "string",
description: "The recipient's email address",
},
{
name: "subject",
type: "string",
description: "The subject of the email",
},
{
name: "body",
type: "string",
description: "The body of the email",
},
],
handler: async ({ recipient, subject, body }) => {
//our not yet defined sendEmail function
},
});
We begin by importing the useCopilotAction
hook from CopilotKit’s react-core.
The useCopilotAction hook accepts a single object that represents a specific action. The object must have four properties:
name
– The special name of the action we are about to let Copilot take for us.description
– A short description of what the action will do.parameters
– An array of variables that will be needed for the action to be carried out. They will eventually be passed to the handler()
function, which will then use them to carry out the actionhandler
– An asynchronous function that performs the actual logic to carry out the action that useCopilotAction
will perform.If you want multiple actions, you can call
useCopilotAction
as many times as you like.
Now let’s create a function called sendEmail()
that sends emails so that the useCopilotAction
handler can use that to send emails for us. Update the page.js
file with the following:
const sendEmail(recipient, subject, body){
const SERVICE_ID = 'EMAILJS_SERVICE_ID';
const TEMPLATE_ID = 'EMAILJS_TEMPLATE_ID';
const PUBLIC_KEY = 'EMAILJS_PUBLIC_KEY';
if (!SERVICE_ID || !TEMPLATE_ID || !PUBLIC_KEY) {
return "invalid configuration";
}
try {
await emailjs.send( SERVICE_ID, TEMPLATE_ID,
{
to_email: recipient,
subject,
message: body,
},PUBLIC_KEY
);
console.log(`Email sent to ${recipient}`);
return `Email sent to ${recipient}`;
} catch (error) {
console.error("Email error:", error);
return `Failed to send email to ${recipient}`;
}
}
The code snippet above shows the function that holds the logic that can send emails. The function requires three parameters: a recipient
, a subject
and a body
.
This function uses the EmailJS SDK to send emails to users. You can create an account with EmailJS to get the credentials needed to use the SDK, which are: service ID, template ID and public key.
From our data, we know that Johnny Whip and Jacob Costco are the users with accounts that have not been validated. As seen in the picture above, in the console, Copilot excellently sends email notifications to the right emails.
And in the chatting area, Copilot says emails were successfully sent! Now let’s verify if that is true by checking the users’ emails to see if the emails Copilot sent for us were received.
The pictures above clearly show that the emails from admin@tamar.com definitely came in for both Johnny and Jacob. The emails were nicely worded and personalized with full names.
From this guide, we have shown that with just a couple of steps, we can turn a simple Next.js app into one with AI-powered task automation abilities. We can see that Copilot AI is not just a chatbot. It is a machine that, when made knowledgeable about our data, can quickly move beyond answering questions to taking actions inside your application and can even work with external services.
It is important to note that while Copilot AI is powerful on its own, it is even more effective, relational and accurate with human guidance. It works its very best when given the right data, clear instructions and permissions to perform meaningful tasks.
Chris Nwamba is a Senior Developer Advocate at AWS focusing on AWS Amplify. He is also a teacher with years of experience building products and communities.