Building an AI agent for your frontend project
Every day, new AI products and tools emerge, making it feel like AI is taking the world by storm — and for good reason. AI assistants can be incredibly useful across various domains, including ecommerce, customer support, media and content creation, marketing, education, and more. The significance and utility of AI are undeniable. Having expertise in AI in today’s rapidly evolving landscape can give you a huge advantage. The skill to build and ship AI agents is becoming increasingly sought after as the demand for AI-powered solutions continues to grow. The good news is that you don’t need to be an AI/ML expert to build AI agents and products. With the right toolset, building AI agents can be both accessible and enjoyable. This tutorial will guide you through building AI agents from scratch. We’ll build, deploy, implement, and test a webpage FAQ generator AI agent within a frontend project. This agent will generate a selected number of FAQs based on specified topics and keywords. We’ll also explore how to enhance the accuracy of an AI agent by instructing it to use a predefined set of documents instead of relying solely on web data. As with any development project, success hinges on choosing the right platform and tools. Here’s our powerful tech stack for building AI agents: OpenAI: The most used AI model provider. To follow along with this tutorial you’ll need to have an account with it BaseAI: A free and open source web AI framework for building serverless AI agents with Node.js and TypeScript Langbase: A powerful serverless platform for building and deploying AI products The BaseAI and Langbase duo is a powerful and flexible professional toolset for building and deploying AI agents and products with great DX. Developers can build, mix and match, test, and deploy AI agents and use them to create powerful AI products fast, easy, and at low cost. All major LLMs are supported and can be used with one unified API. Get excited, because by the end of this post, you'll be well on your way to creating your very own AI agents like a pro. Let's get started! What is an AI agent? An AI agent is a software program that uses artificial intelligence to perform tasks or make decisions on its own, often interacting with users or systems. It can be a chatbot, virtual assistant, or any tool that learns from data and automates processes, making things easier and faster. What are the benefits of building your own AI agent? Being able to leverage all the power of LLMs without the limits of third-party tools Flexible customization tailored to your specific project needs/use cases Seamless integration with your workflow and toolset Full control over the processed data Better privacy and security Scalability that meets your changing/growing needs Cost efficiency in the long run Full alignment with your brand identity An introduction to the BaseAI framework To use BaseAI efficiently, you need to understand the main functionalities it offers: AI pipes: These are serverless AI agents. They provide a unified API for all LLMs and work with any language and framework AI memory: This is a serverless RAG (Retrieval Augmented Generation) agent that provides long-term memory functionality with the ability to obtain, process, retain, and retrieve information AI tool: This is a function inside your codebase used to perform tasks that the AI model can't handle alone In this tutorial, we’ll explore the first two: AI pipes and memory. Getting started BaseAI works in close relation with Langbase, which provides a versatile AI Studio for building, testing, and deploying AI agents. The first step is to create a free account with Langbase. Once you have an account, you need to set up two things: Langbase User API key (you can find this in the Langbase settings) Your OpenAI API key in the LLM API keyset Now you are ready to start using BaseAI! Let’s create a new Node project: mkdir building-ai-agents && cd building-ai-agents npm init -y npm install dotenv Now, let’s initialize the new BaseAI project inside: npx baseai@latest init Normally, the base project structure looks like this: ROOT (of your app) ├── baseai | ├── baseai.config.ts | ├── memory | ├── pipes | └── tools ├── .env (your env file) └── package.json Right now, your project can differentiate a bit. You may notice that in your project, the memory, pipes, and tools directories are missing. Don’t worry — these are auto-generated when you create at least one memory, pipe, or tool respectively. Also before you start building AI agents, you need to add the Langbase API key and OpenAI API key in the project’s .env file. Rename the env.baseai.example file to .env and put the API keys in the appropriate places: # !! SERVER SIDE ONLY !! # Keep all your API keys secret — use only on the server side. # TODO: ADD: Both in your production and local env files. # L
Every day, new AI products and tools emerge, making it feel like AI is taking the world by storm — and for good reason. AI assistants can be incredibly useful across various domains, including ecommerce, customer support, media and content creation, marketing, education, and more. The significance and utility of AI are undeniable.
Having expertise in AI in today’s rapidly evolving landscape can give you a huge advantage. The skill to build and ship AI agents is becoming increasingly sought after as the demand for AI-powered solutions continues to grow. The good news is that you don’t need to be an AI/ML expert to build AI agents and products. With the right toolset, building AI agents can be both accessible and enjoyable.
This tutorial will guide you through building AI agents from scratch. We’ll build, deploy, implement, and test a webpage FAQ generator AI agent within a frontend project. This agent will generate a selected number of FAQs based on specified topics and keywords. We’ll also explore how to enhance the accuracy of an AI agent by instructing it to use a predefined set of documents instead of relying solely on web data.
As with any development project, success hinges on choosing the right platform and tools. Here’s our powerful tech stack for building AI agents:
- OpenAI: The most used AI model provider. To follow along with this tutorial you’ll need to have an account with it
- BaseAI: A free and open source web AI framework for building serverless AI agents with Node.js and TypeScript
- Langbase: A powerful serverless platform for building and deploying AI products
The BaseAI and Langbase duo is a powerful and flexible professional toolset for building and deploying AI agents and products with great DX. Developers can build, mix and match, test, and deploy AI agents and use them to create powerful AI products fast, easy, and at low cost. All major LLMs are supported and can be used with one unified API.
Get excited, because by the end of this post, you'll be well on your way to creating your very own AI agents like a pro. Let's get started!
What is an AI agent?
An AI agent is a software program that uses artificial intelligence to perform tasks or make decisions on its own, often interacting with users or systems. It can be a chatbot, virtual assistant, or any tool that learns from data and automates processes, making things easier and faster.
What are the benefits of building your own AI agent?
- Being able to leverage all the power of LLMs without the limits of third-party tools
- Flexible customization tailored to your specific project needs/use cases
- Seamless integration with your workflow and toolset
- Full control over the processed data
- Better privacy and security
- Scalability that meets your changing/growing needs
- Cost efficiency in the long run
- Full alignment with your brand identity
An introduction to the BaseAI framework
To use BaseAI efficiently, you need to understand the main functionalities it offers:
- AI pipes: These are serverless AI agents. They provide a unified API for all LLMs and work with any language and framework
- AI memory: This is a serverless RAG (Retrieval Augmented Generation) agent that provides long-term memory functionality with the ability to obtain, process, retain, and retrieve information
- AI tool: This is a function inside your codebase used to perform tasks that the AI model can't handle alone
In this tutorial, we’ll explore the first two: AI pipes and memory.
Getting started
BaseAI works in close relation with Langbase, which provides a versatile AI Studio for building, testing, and deploying AI agents. The first step is to create a free account with Langbase. Once you have an account, you need to set up two things:
- Langbase User API key (you can find this in the Langbase settings)
- Your OpenAI API key in the LLM API keyset
Now you are ready to start using BaseAI!
Let’s create a new Node project:
mkdir building-ai-agents && cd building-ai-agents
npm init -y
npm install dotenv
Now, let’s initialize the new BaseAI project inside:
npx baseai@latest init
Normally, the base project structure looks like this:
ROOT (of your app)
├── baseai
| ├── baseai.config.ts
| ├── memory
| ├── pipes
| └── tools
├── .env (your env file)
└── package.json
Right now, your project can differentiate a bit. You may notice that in your project, the memory
, pipes
, and tools
directories are missing. Don’t worry — these are auto-generated when you create at least one memory, pipe, or tool respectively.
Also before you start building AI agents, you need to add the Langbase API key
and OpenAI API key
in the project’s .env
file. Rename the env.baseai.example
file to .env
and put the API keys in the appropriate places:
# !! SERVER SIDE ONLY !!
# Keep all your API keys secret — use only on the server side.
# TODO: ADD: Both in your production and local env files.
# Langbase API key for your User or Org account.
# How to get this API key https://langbase.com/docs/api-reference/api-keys
LANGBASE_API_KEY="YOUR-LANGBASE-KEY"
# TODO: ADD: LOCAL ONLY. Add only to local env files.
# Following keys are needed for local pipe runs. For providers you are using.
# For Langbase, please add the key to your LLM keysets.
# Read more: Langbase LLM Keysets https://langbase.com/docs/features/keysets
OPENAI_API_KEY="YOUR-OPENAI-KEY"
ANTHROPIC_API_KEY=
COHERE_API_KEY=
FIREWORKS_API_KEY=
GOOGLE_API_KEY=
GROQ_API_KEY=
MISTRAL_API_KEY=
PERPLEXITY_API_KEY=
TOGETHER_API_KEY=
XAI_API_KEY=
N.B., the baseai.config.ts
file provides several configuration settings, one of which is to change the name of your .env
file to suit your needs. You can do this by setting the envFilePath
property.
Building a webpage FAQ generator AI agent locally using BaseAI
In this section, we’ll create your first AI agent — a webpage FAQ generator that generates a specified number of question-answer pairs about specific topics and keywords, with the selected tone.
Creating and configuring an AI pipe
To create a new pipe, run the following:
npx baseai@latest pipe
The CLI will ask you for the name and description of the pipe, and whether it will be public or private. Set the name to “faqs-generator” and the description to “A webpage FAQs generator”. Finally, make the pipe private. Once the pipe is created, you can find it in baseai/pipes/faqs-generator.ts
. Open it and replace the content with this:
import { PipeI } from '@baseai/core';
const pipeFaqsGenerator = (): PipeI => ({
// Replace with your API key https://langbase.com/docs/api-reference/api-keys
apiKey: process.env.LANGBASE_API_KEY!,
name: 'faqs-generator',
description: 'A webpage FAQs generator',
status: 'private',
model: 'openai:gpt-4o-mini',
stream: true,
json: false,
store: true,
moderate: true,
top_p: 1,
max_tokens: 1000,
temperature: 0.7,
presence_penalty: 1,
frequency_penalty: 1,
stop: [],
tool_choice: 'auto',
parallel_tool_calls: true,
messages: [
{
role: 'system',
content: `You're a helpful AI assistant. Generate {{count}} frequently asked questions (FAQs) about {{topic}} using the keywords {{keywords}}.
Each FAQ should consist of a question followed by a concise answer. Ensure the answers are clear, accurate, and helpful for someone who is unfamiliar with the topic. Keep the tone {{tone}}.
`
}
],
variables: [
{ name: 'count', value: '' },
{ name: 'topic', value: '' },
{ name: 'keywords', value: '' },
{ name: 'tone', value: '' }],
memory: [],
tools: []
});
export default pipeFaqsGenerator;
As you can see, the system prompt has now changed to suit our specific needs for FAQ generation:
"You're a helpful AI assistant. Generate {{count}} frequently asked questions (FAQs) about {{topic}} using the keywords {{keywords}}.
Each FAQ should consist of a question followed by a concise answer. Ensure the answers are clear, accurate, and helpful for someone who is unfamiliar with the topic. Keep the tone {{tone}}."
BaseAI allows you to use variables in your prompts. You can turn any text into a variable by putting it between {{}}
. So in our case, we need to create four variables:
-
count
: Sets the number of the FAQs we want to be generated -
topic
: Sets the main topic of the FAQs -
keywords
: Adds additional keywords to make the topic more specific -
tone
: Defines the tone of the generated content
These variables are provided when you run the pipe. We’ll explore this in a moment.
Integrating the pipe
Once we have created the pipe, we need to put it into action. Create a index.ts
file in the root and add this content:
import 'dotenv/config';
import {Pipe, getRunner} from '@baseai/core';
import pipeFaqsGenerator from './baseai/pipes/faqs-generator';
const pipe = new Pipe(pipeFaqsGenerator());
async function main() {
const {stream} = await pipe.run({
messages: [],
variables: [
{ name: 'count', value: '3' },
{ name: 'topic', value: 'money' },
{ name: 'keywords', value: 'investment' },
{ name: 'tone', value: 'informative' }],
stream: true
});
const runner = getRunner(stream);
runner.on('connect', () => {
console.log('Stream started.\n');
});
runner.on('content', content => {
process.stdout.write(content);
});
runner.on('end', () => {
console.log('\nStream ended.');
});
runner.on('error', error => {
console.error('Error:', error);
});
}
main();
Here, we run the pipe with the variables we want to use. We want to stream the response so we also set stream
property to true
. We use the extracted stream from the response and turn it into a runner. Next, we use it to stream the content. Let’s try it out.
Running and testing the pipe
To run the pipe, you first need to start the dev server:
npx baseai@latest dev
Then, in a new terminal, run the index.ts
file:
npx tsx index.ts
In a moment you should see the streamed content in your CLI. Congratulations! You have just built your first AI agent with ease.
Deploying the FAQ generator AI agent to Langbase
BaseAI gives you the ability to build and test AI agents locally but to use it in production, you need to deploy it to Langbase. Here’s how to do so. First, you need to authenticate with your Langbase account:
npx baseai@latest auth
Once you have successfully authenticated, deploying your pipe is a matter of running the following command:
npx baseai@latest deploy
Once deployed, you can access your pipe and explore all its settings and features in the Langbase AI Studio. This gives you much more power to explore and experiment with your AI agent in a user-friendly environment.
Building an AI agent with RAG
The FAQ generator is great for general questions but what if customers want to ask specific questions about your products or services? Then you can create a pipe with memory implementing the RAG technology.
What is RAG?
RAG, or Retrieval Augmented Generation, allows you to chat with your data. Imagine that I have read a book and then you ask me questions related to the book. I would use my memories of the book’s content to answer your questions. Similarly, when you ask a RAG AI agent a question, it uses its embedded memory to retrieve the necessary information about the answer. This reduces AI hallucinations and provides more accurate and relevant responses. In our project, we’re going to create a pipe with memory where we’ll embed a set of documents to be used as a knowledge base.
Creating AI memory
To create a new memory, run the following:
npx baseai@latest memory
The CLI will ask you for the memory name and description. You can call it “knowledge-base” and use whatever description you want. Leave the answer for “Do you want to create memory from current project git repository?” as “no”. This will create a baseai/memory/knowledge-base
directory with an index.ts
file inside:
import {MemoryI} from '@baseai/core';
const memoryKnowledgeBase = (): MemoryI => ({
name: 'knowledge-base',
description: "My knowledge base",
git: {
enabled: false,
include: ['documents/**/*'],
gitignore: false,
deployedAt: '',
embeddedAt: ''
}
});
export default memoryKnowledgeBase;
The next step is to add your data. Open this tutorial of mine, copy all the text, and put it in a tailwind-libraries.txt
file. Next, add the file in baseai/memory/knowledge-base/documents
. N.B., Langbase currently supports .txt
, .pdf
, .md
, .csv
, and all major plain code files. A single file size can be a maximum of 10MB. Now we need to embed the memory to generate embeddings for the documents. To create memory embeddings, run the following:
npx baseai@latest embed -m knowledge-base
Make sure to add OPENAI_API_KEY
to the .env
file at the root of your project. This is required to generate embeddings for the documents in the memory. BaseAI will generate embeddings for the documents and create a semantic index for search. Now let’s create a new pipe and add the memory we’ve just created to it:
npx baseai@latest pipe
Set the pipe name to “knowledge-base-rag”. BaseAI automatically detects when you have memory so it will ask you which one you want to use in your pipe. Select knowledge-base
, and use this for the system prompt:
You are a helpful AI assistant.You provide the best, concise, and correct answers to the user's questions.
Here is the generated pipe:
import { PipeI } from '@baseai/core';
import knowledgeBaseMemory from '../memory/knowledge-base';
const pipeKnowledgeBaseRag = (): PipeI => ({
// Replace with your API key https://langbase.com/docs/api-reference/api-keys
apiKey: process.env.LANGBASE_API_KEY!,
name: 'knowledge-base-rag',
description: 'A knowledge base with RAG functionality',
status: 'private',
model: 'openai:gpt-4o-mini',
stream: true,
json: false,
store: true,
moderate: true,
top_p: 1,
max_tokens: 1000,
temperature: 0.7,
presence_penalty: 1,
frequency_penalty: 1,
stop: [],
tool_choice: 'auto',
parallel_tool_calls: true,
messages: [
{
role: 'system',
content: `You are a helpful AI assistant.You provide the best, concise, and correct answers to the user's questions.`
},
{
role: 'system',
name: 'rag',
content:
"Below is some CONTEXT for you to answer the questions. ONLY answer from the CONTEXT. CONTEXT consists of multiple information chunks. Each chunk has a source mentioned at the end.\n\nFor each piece of response you provide, cite the source in brackets like so: [1].\n\nAt the end of the answer, always list each source with its corresponding number and provide the document name. like so [1] Filename.doc.\n\nIf you don't know the answer, just say that you don't know. Ask for more context and better questions if needed."
}
],
variables: [],
memory: [knowledgeBaseMemory()],
tools: []
});
export default pipeKnowledgeBaseRag;
BaseAI automatically adds a RAG system prompt that is suitable for most use cases but you can customize it to your needs. It helps the AI model understand the context of the conversation and generate responses that are relevant, accurate, and grammatically correct. Now, let’s test it. Create an index-rag.ts
file in the root and add the following content:
import 'dotenv/config';
import {Pipe, getRunner} from '@baseai/core';
import pipeKnowledgeBaseRag from './baseai/pipes/knowledge-base-rag';
const pipe = new Pipe(pipeKnowledgeBaseRag());
async function main() {
const {stream} = await pipe.run({
messages: [{role: 'user', content: 'Which Tailwind CSS component library provides the most components?'}],
stream: true
});
const runner = getRunner(stream);
runner.on('connect', () => {
console.log('Stream started.\n');
});
runner.on('content', content => {
process.stdout.write(content);
});
runner.on('end', () => {
console.log('\nStream ended.');
});
runner.on('error', error => {
console.error('Error:', error);
});
}
main();
Now, to run the pipe, make sure the dev server is running. Then run the index-rag.ts
file:
npx tsx index-rag.ts
After a moment, you should see something similar in your terminal:
**Tailwind Elements** provides the most components, with a huge set of more than 500 UI components. These components range from very simple elements like headings and icons to more complex ones like charts and complete forms, making it suitable for almost any kind of project [1].
Sources:
[1] tailwind-libraries.txt
Here, the AI agent uses the provided data to answer the question.
Building a basic AI-powered Next.js app
In this section, we’ll explore a simple example of how you can use AI agents in a Next.js frontend app. Start by running the following:
npx create-next-app@latest
Accept all default settings. When the app is set up, create an actions.ts
file in the app
directory with the following content:
'use server';
export async function generateCompletion(count: string, topic: string, keywords: string, tone: string) {
const url = 'https://api.langbase.com/v1/pipes/run';
const apiKey = 'PIPE-API-KEY';
const data = {
messages: [],
variables: [
{ name: 'count', value: count },
{ name: 'topic', value: topic },
{ name: 'keywords', value: keywords },
{ name: 'tone', value: tone }]
};
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`
},
body: JSON.stringify(data)
});
const resText = await response.json();
return resText;
}
Here, we have a function that generates an AI answer completion. You need to replace
with your Pipe API key. To get it, open your pipe in Langbase and click on the API tab next to the selected Pipe tab, and copy the API key from there. Now, open page.tsx
and replace its contents with the following:
'use client';
import { useState } from 'react';
import { generateCompletion } from './actions';
export default function Home() {
const url = 'https://api.langbase.com/v1/pipes/run';
const apiKey = 'YOUR-PIPE-KEY';
const [count, setCount] = useState('');
const [topic, setTopic] = useState('');
const [keywords, setKeywords] = useState('');
const [tone, setTone] = useState('');
const [completion, setCompletion] = useState('');
const [loading, setLoading] = useState(false);
const handleGenerateCompletion = async () => {
setLoading(true);
const {completion} = await generateCompletion(count, topic, keywords, tone)
setCompletion(completion);
setLoading(false)
};
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<div className="flex flex-col items-center">
<h1 className="text-4xl font-bold">
Generate FAQs
</h1>
<p className="mt-4 text-lg">
Enter a topic and click the button to generate FAQs using LLM
</p>
<input type="text" placeholder="Enter a topic"
className="w-1/2 m-3 rounded-lg border border-slate-300 bg-slate-200 p-3 text-sm text-slate-800 shadow-md focus:border-blue-600 focus:outline-none focus:ring-1 focus:ring-blue-600 dark:border-slate-200/10 dark:bg-slate-800 dark:text-slate-200 dark:placeholder-slate-400 dark:focus:border-blue-600 sm:text-base"
value={topic} onChange={e=> setTopic(e.target.value)}
/>
<input type="text" placeholder="Enter keywords"
className="w-1/2 m-3 rounded-lg border border-slate-300 bg-slate-200 p-3 text-sm text-slate-800 shadow-md focus:border-blue-600 focus:outline-none focus:ring-1 focus:ring-blue-600 dark:border-slate-200/10 dark:bg-slate-800 dark:text-slate-200 dark:placeholder-slate-400 dark:focus:border-blue-600 sm:text-base"
value={keywords} onChange={e=> setKeywords(e.target.value)}
/>
<input type="text" placeholder="Enter a tone"
className="w-1/2 m-3 rounded-lg border border-slate-300 bg-slate-200 p-3 text-sm text-slate-800 shadow-md focus:border-blue-600 focus:outline-none focus:ring-1 focus:ring-blue-600 dark:border-slate-200/10 dark:bg-slate-800 dark:text-slate-200 dark:placeholder-slate-400 dark:focus:border-blue-600 sm:text-base"
value={tone} onChange={e=> setTone(e.target.value)}
/>
<input type="text" placeholder="Enter a count"
className="w-1/2 m-3 rounded-lg border border-slate-300 bg-slate-200 p-3 text-sm text-slate-800 shadow-md focus:border-blue-600 focus:outline-none focus:ring-1 focus:ring-blue-600 dark:border-slate-200/10 dark:bg-slate-800 dark:text-slate-200 dark:placeholder-slate-400 dark:focus:border-blue-600 sm:text-base"
value={count} onChange={e=> setCount(e.target.value)}
/>
<button onClick={handleGenerateCompletion}
className="inline-flex items-center gap-x-2 m-3 rounded-lg bg-blue-600 px-4 py-2.5 text-center text-base font-medium text-slate-50 hover:bg-blue-800 focus:ring-4 focus:ring-blue-200 dark:focus:ring-blue-900">
Generate FAQs
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" viewBox="0 0 24 24" strokeWidth="2"
stroke="currentColor" fill="none" strokeLinecap="round" strokeLinejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M10 14l11 -11"></path>
<path d="M21 3l-6.5 18a.55 .55 0 0 1 -1 0l-3.5 -7l-7 -3.5a.55 .55 0 0 1 0 -1l18 -6.5"></path>
</svg>
</button>
{loading && <p className="mt-4">Loading...</p>}
{completion && (
<textarea readOnly value={completion} cols={100} rows={20}
className="w-full bg-slate-50 p-10 text-base text-slate-900 focus:outline-none dark:bg-slate-800 dark:text-slate-200 dark:placeholder-slate-400" />
)}
</div>
</main>
);
}
Here we created the necessary inputs for the pipe’s variables and added a textarea for the AI-generated response. Before running the app, go to the pipe in Langbase and, in the right sidebar in the Meta panel, turn the Stream mode to Off
. Now run the app and test it:
npm run dev
Here is what it should look like: Here is a prompt example: And here is the AI completion response:
Conclusion
In this tutorial, we explored the benefits of building your own AI agents. We did so by building a simple but powerful webpage FAQ generator. We also learned how to add memory to an AI agent to take advantage of RAG technology. Finally, we integrated the FAQ generator AI agent into a Next.js app. The future belongs to AI and gaining expertise in this area will offer you a big advantage. To learn more about building AI agents, don’t forget to check out the BaseAI and Langbase documentation.
Get set up with LogRocket's modern error tracking in minutes:
- Visit https://logrocket.com/signup/ to get an app ID.
- Install LogRocket via NPM or script tag.
LogRocket.init()
must be called client-side, not server-side.
NPM:
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
Script Tag:
Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
3.(Optional) Install plugins for deeper integrations with your stack:
- Redux middleware
- ngrx middleware
- Vuex plugin
What's Your Reaction?