AI Agent JavaScript Tutorial: Build a Web Agent with Node.js and OpenAI
AI Agent JavaScript Tutorial: Build a Web Agent with Node.js and OpenAI
Most AI agent tutorials focus on Python. But if your stack is JavaScript or TypeScript, you can build production-ready agents with Node.js -- and the tooling has caught up.
This tutorial walks you through building a complete AI agent in JavaScript: from a basic chatbot to a tool-using agent with a web interface. You'll use the Vercel AI SDK, which provides the best developer experience for building AI agents in JS/TS.
In this tutorial:
- Setting up your Node.js project
- Building a basic AI chatbot
- Adding tool calling
- Building a web interface
- Streaming responses
- Production considerations
Related tutorials: AI Agent Python Tutorial · Build AI Agent From Scratch · AI Agent API Integration
Setting Up Your Node.js Project
Prerequisites
- Node.js 18+ (check with
node --version) - An OpenAI API key
- npm or pnpm
Step 1: Initialize the Project
mkdir js-agent-tutorial && cd js-agent-tutorial
npm init -y
npm install ai @ai-sdk/openai dotenv zod
Step 2: Configure Environment
Create .env:
OPENAI_API_KEY=sk-your-key-here
Step 3: TypeScript Setup (Recommended)
npm install -D typescript @types/node
npx tsc --init
Set "module": "ESNext" and "moduleResolution": "bundler" in tsconfig.json.
Building a Basic AI Chatbot
Start with the simplest agent -- a chatbot that can reason:
// chat.ts
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';
import 'dotenv/config';
async function chat(message: string) {
const { text } = await generateText({
model: openai('gpt-4o'),
system: 'You are a helpful assistant that provides concise, accurate answers.',
prompt: message,
});
return text;
}
const response = await chat('What are the 3 best practices for building AI agents?');
console.log(response);
Run it: npx tsx chat.ts
This works, but it's just a chatbot. Let's make it an agent by adding tools.
Adding Tool Calling
Tools are what turn a chatbot into an agent. The Vercel AI SDK makes tool definition clean with Zod schemas:
// agent.ts
import { openai } from '@ai-sdk/openai';
import { generateText, tool } from 'ai';
import { z } from 'zod';
import 'dotenv/config';
const webSearch = tool({
description: 'Search the web for current information',
parameters: z.object({
query: z.string().describe('The search query'),
}),
execute: async ({ query }) => {
const response = await fetch(
`https://api.tavily.com/search`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query,
api_key: process.env.TAVILY_API_KEY,
max_results: 3,
}),
}
);
const data = await response.json();
return data.results.map((r: any) => `${r.title}: ${r.content}`).join('\n');
},
});
const calculator = tool({
description: 'Evaluate a mathematical expression',
parameters: z.object({
expression: z.string().describe('A valid math expression like "2 + 2" or "Math.PI * 5"'),
}),
execute: async ({ expression }) => {
try {
const result = Function(`"use strict"; return (${expression})`)();
return `Result: ${result}`;
} catch {
return 'Error: Invalid expression';
}
},
});
const saveFile = tool({
description: 'Save content to a file',
parameters: z.object({
filename: z.string().describe('The filename to save to'),
content: z.string().describe('The content to write'),
}),
execute: async ({ filename, content }) => {
const fs = await import('fs/promises');
await fs.writeFile(filename, content, 'utf-8');
return `Saved to ${filename}`;
},
});
Get AI agent tips in your inbox
Multi-agent workflows, BYOK tips, and product updates. No spam.
Running the Agent with Tools
async function runAgent(userMessage: string) {
const { text, steps } = await generateText({
model: openai('gpt-4o'),
system: `You are a research agent. Use tools to find information and complete tasks.
Always verify facts with web search before stating them.
Save important results to files.`,
prompt: userMessage,
tools: { webSearch, calculator, saveFile },
maxSteps: 10,
});
console.log('Agent output:', text);
console.log(`Used ${steps.length} steps`);
return text;
}
await runAgent(
'Search for the current population of Tokyo, calculate the density per square km (area is 2,194 sq km), and save a summary to tokyo-stats.txt'
);
The agent will:
- Search for Tokyo's population
- Calculate density using the calculator tool
- Save the summary to a file
- Report the results
Building a Web Interface
Server Side (Next.js API Route)
// app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText, tool } from 'ai';
import { z } from 'zod';
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: openai('gpt-4o'),
system: 'You are a helpful AI agent with access to tools. Use them to complete tasks.',
messages,
tools: {
webSearch: tool({
description: 'Search the web for current information',
parameters: z.object({ query: z.string() }),
execute: async ({ query }) => {
const res = await fetch('https://api.tavily.com/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query,
api_key: process.env.TAVILY_API_KEY,
max_results: 3,
}),
});
const data = await res.json();
return data.results.map((r: any) => `${r.title}: ${r.content}`).join('\n');
},
}),
},
});
return result.toDataStreamResponse();
}
Client Side (React Component)
// app/chat/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
export default function ChatPage() {
const { messages, input, handleInputChange, handleSubmit } = useChat();
return (
<div className="max-w-2xl mx-auto p-4">
<h1>AI Agent Chat</h1>
<div className="space-y-4 mb-4">
{messages.map((m) => (
<div key={m.id} className={m.role === 'user' ? 'text-right' : 'text-left'}>
<div className={`inline-block p-3 rounded-lg ${
m.role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-100'
}`}>
{m.content}
</div>
</div>
))}
</div>
<form onSubmit={handleSubmit} className="flex gap-2">
<input
value={input}
onChange={handleInputChange}
placeholder="Ask me anything..."
className="flex-1 p-2 border rounded"
/>
<button type="submit" className="px-4 py-2 bg-blue-500 text-white rounded">
Send
</button>
</form>
</div>
);
}
Streaming Responses
For long-running agent tasks, streaming keeps users engaged. The Vercel AI SDK handles this natively:
import { streamText } from 'ai';
const result = streamText({
model: openai('gpt-4o'),
prompt: 'Research the top 5 AI agent frameworks and compare them',
tools: { webSearch },
maxSteps: 10,
onStepFinish({ toolResults }) {
console.log('Step completed:', toolResults);
},
});
for await (const textPart of result.textStream) {
process.stdout.write(textPart);
}
Production Considerations
Error Handling
const result = await generateText({
model: openai('gpt-4o'),
prompt: userMessage,
tools: { webSearch, calculator, saveFile },
maxSteps: 10,
onError: ({ error }) => {
console.error('Agent error:', error);
},
});
Rate Limiting
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
const ratelimit = new Ratelimit({
redis: Redis.fromEnv(),
limiter: Ratelimit.slidingWindow(10, '1 m'),
});
export async function POST(req: Request) {
const ip = req.headers.get('x-forwarded-for') ?? 'anonymous';
const { success } = await ratelimit.limit(ip);
if (!success) {
return new Response('Rate limited', { status: 429 });
}
// ... agent logic
}
Cost Tracking
const { text, usage } = await generateText({
model: openai('gpt-4o'),
prompt: message,
tools,
});
console.log(`Tokens: ${usage.promptTokens} prompt + ${usage.completionTokens} completion`);
const cost = (usage.promptTokens * 0.0000025) + (usage.completionTokens * 0.00001);
console.log(`Estimated cost: $${cost.toFixed(4)}`);
For detailed cost analysis, use our AI Cost Calculator.
When to Use JavaScript vs Python for AI Agents
Scroll to see full table
| Factor | JavaScript/TypeScript | Python |
|---|---|---|
| Best for | Web apps, real-time UI, Next.js projects | Data science, ML pipelines, research |
| SDK quality | Vercel AI SDK (excellent) | LangChain (mature, complex) |
| Tool ecosystem | Growing fast | Extensive |
| Streaming | Native, easy | Possible but verbose |
| Type safety | TypeScript (excellent) | Type hints (good) |
Choose JavaScript if your project is already in JS/TS or you need tight web integration. Choose Python for research-heavy workflows or when you need Python's ML ecosystem.
For a deeper comparison of frameworks, see our AI Agent Orchestration Guide.
Skip the Code: Use Ivern AI
If you want agent capabilities without building from scratch, Ivern AI gives you:
- Agent squads in 2 minutes -- no code, no configuration files
- BYOK pricing -- bring your OpenAI or Anthropic key, zero markup
- Built-in web interface -- chat with agents, assign tasks, review results
- Streaming responses -- real-time output as agents work
- Tool integrations -- web search, file operations, and more built in
Get started free: ivern.ai/signup
Next Steps
- Add more tools -- database queries, email sending, Slack notifications
- Build multi-agent systems -- see our Multi-Agent Tutorial
- Add persistence -- store conversations and agent state in a database
- Deploy -- use Vercel, Railway, or your own infrastructure
Related guides: How to Connect Multiple AI Models · AI Agent API Integration · Best AI Agent Platforms 2026
Related Articles
AI Agent API Integration Tutorial: Connect Agents to Any External Service
Step-by-step tutorial for connecting AI agents to external APIs and services. Covers REST API integration, authentication, error handling, rate limiting, and building a tool layer that lets agents interact with any service.
AI Agent Collaboration Tutorial: How to Make Multiple Agents Work Together
Learn how to build collaborative AI agent systems where multiple specialized agents share context, hand off tasks, and produce results together. Covers communication patterns, context sharing, and real implementation examples.
AI Agent Prompt Engineering Tutorial: Write Prompts That Get Better Results
Master prompt engineering for AI agents with this practical tutorial. Covers system prompts, tool-use prompting, few-shot examples, chain-of-thought reasoning, and prompt patterns that improve agent output quality by 3-5x.
Want to try multi-agent AI for free?
Generate a blog post, Twitter thread, LinkedIn post, and newsletter from one prompt. No signup required.
Try the Free DemoAI Content Factory -- Free to Start
One prompt generates blog posts, social media, and emails. Free tier, BYOK, zero markup.
No spam. Unsubscribe anytime.