DEV Community

Leo Laish
Leo Laish

Posted on

Building Your First AYW Bot: A Step-by-Step Guide

Building Your First AYW Bot: A Step-by-Step Guide

A complete tutorial for building your first human-guided AI chatbot with AYW. From setup to deployment in 15 minutes.

Published: May 16, 2026 | 8 min read | Part 1 of AYW Dev.to Series

What is AYW?

AYW (As You Wish) is a modern, interactive chatbot platform that puts human guidance at the center of AI conversations. Unlike traditional chatbots that follow rigid scripts or fully autonomous AI that can go off-track, AYW bots learn from human guidance and adapt to each unique customer journey.

Prerequisites

  • Node.js 18+ installed
  • PostgreSQL database (we use Prisma ORM)
  • OpenAI API key (for AI responses)
  • Basic knowledge of TypeScript and React

Architecture Overview

AYW uses a monorepo architecture with three main apps:

ayw-monorepo/
├── apps/
│   ├── backend/     # Express + TypeScript API
│   ├── frontend/    # React + Vite web app
│   └── chatbot/     # Chatbot logic (in development)
├── packages/        # Shared utilities
└── prisma/          # Database schema
Enter fullscreen mode Exit fullscreen mode

The backend handles API routes, WebSocket connections, and AI integration. The frontend provides the user interface including a chat widget, dashboard, and landing page.

Step 1: Clone and Install

git clone https://github.com/ayw-ai/ayw-monorepo.git
cd ayw-monorepo
npm install
Enter fullscreen mode Exit fullscreen mode

This uses npm workspaces to install dependencies across all apps.

Step 2: Set Up Environment Variables

Create .env files in both apps/backend and apps/frontend:

apps/backend/.env:

DATABASE_URL="postgresql://user:password@localhost:5432/ayw_db"
OPENAI_API_KEY="your-openai-api-key"
JWT_SECRET="your-jwt-secret"
FRONTEND_URL="http://localhost:3000"
PORT=4000
Enter fullscreen mode Exit fullscreen mode

apps/frontend/.env:

VITE_API_URL="http://localhost:4000"
Enter fullscreen mode Exit fullscreen mode

Step 3: Set Up the Database

cd apps/backend
npx prisma migrate dev --name init
npx prisma generate
Enter fullscreen mode Exit fullscreen mode

This creates your database schema with tables for users, conversations, and messages.

Step 4: Start the Development Servers

In the root directory, run:

npm run dev
Enter fullscreen mode Exit fullscreen mode

This concurrently starts:

  • Backend server on http://localhost:4000
  • Frontend on http://localhost:3000
  • Chatbot service (when ready)

Step 5: Create Your First Bot Configuration

Now let's configure your first bot. Create a bot config in apps/backend/src/services/botConfig.ts:

export interface BotConfig {
  name: string;
  type: 'welcome' | 'support' | 'sales' | 'feedback';
  systemPrompt: string;
  temperature: number;
  maxTokens: number;
}

export const welcomeBot: BotConfig = {
  name: 'Welcome Bot',
  type: 'welcome',
  systemPrompt: `You are the AYW Welcome Bot. Your job is to:
1. Greet visitors warmly
2. Understand their intent (support, sales, feedback)
3. Route them to the appropriate specialist bot
4. Maintain a helpful, human-guided tone

Always be polite, concise, and guide users to the right destination.`,
  temperature: 0.7,
  maxTokens: 500
};
Enter fullscreen mode Exit fullscreen mode

Step 6: Build the Chat Service with OpenAI

Create apps/backend/src/services/chatbotService.ts:

import OpenAI from 'openai';
import { PrismaClient } from '@prisma/client';
import { BotConfig, welcomeBot, supportBot, salesBot, feedbackBot } from './botConfig';

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const prisma = new PrismaClient();

const botConfigs: Record<string, BotConfig> = {
  welcome: welcomeBot,
  support: supportBot,
  sales: salesBot,
  feedback: feedbackBot
};

export class ChatbotService {
  async processMessage({ message, conversationId, botType, userId }: {
    message: string;
    conversationId?: string;
    botType: string;
    userId?: string;
  }) {
    const config = botConfigs[botType] || welcomeBot;

    // Create or get conversation
    let conversation;
    if (conversationId) {
      conversation = await prisma.conversation.findUnique({
        where: { id: conversationId }
      });
    } else {
      conversation = await prisma.conversation.create({
        data: {
          botType,
          userId,
          status: 'active'
        }
      });
    }

    // Save user message
    await prisma.message.create({
      data: {
        conversationId: conversation.id,
        role: 'user',
        content: message
      }
    });

    // Get conversation history
    const history = await prisma.message.findMany({
      where: { conversationId: conversation.id },
      orderBy: { createdAt: 'asc' },
      take: 10
    });

    // Call OpenAI with human-guided system prompt
    const completion = await openai.chat.completions.create({
      model: 'gpt-4-turbo-preview',
      messages: [
        { role: 'system', content: config.systemPrompt },
        ...history.map(msg => ({
          role: msg.role as 'user' | 'assistant',
          content: msg.content
        }))
      ],
      temperature: config.temperature,
      max_tokens: config.maxTokens
    });

    const botResponse = completion.choices[0].message.content;

    // Save bot response
    await prisma.message.create({
      data: {
        conversationId: conversation.id,
        role: 'assistant',
        content: botResponse,
        botType
      }
    });

    return {
      message: botResponse,
      conversationId: conversation.id,
      botType: config.type
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 7: Build the Frontend Chat Interface

Create apps/frontend/src/pages/ChatPage.tsx:

import { useState, useRef, useEffect } from 'react';
import { Send, Bot, User } from 'lucide-react';
import { chatbotService } from '../services/chatbotService';

interface Message {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  timestamp: Date;
}

export default function ChatPage() {
  const [messages, setMessages] = useState<Message[]>([]);
  const [input, setInput] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const messagesEndRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  const sendMessage = async () => {
    if (!input.trim()) return;

    const userMessage: Message = {
      id: Date.now().toString(),
      role: 'user',
      content: input,
      timestamp: new Date()
    };

    setMessages(prev => [...prev, userMessage]);
    setInput('');
    setIsLoading(true);

    try {
      const response = await chatbotService.sendMessage({
        message: input,
        botType: 'welcome'
      });

      const botMessage: Message = {
        id: (Date.now() + 1).toString(),
        role: 'assistant',
        content: response.message,
        timestamp: new Date()
      };

      setMessages(prev => [...prev, botMessage]);
    } catch (error) {
      console.error('Failed to send message:', error);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div className="flex flex-col h-screen max-w-4xl mx-auto p-4">
      <header className="mb-4">
        <h1 className="text-2xl font-bold">AYW Chatbot Demo</h1>
        <p className="text-gray-600">Powered by human-guided AI</p>
      </header>

      <div className="flex-1 overflow-y-auto border rounded-lg p-4 space-y-4">
        {messages.map(msg => (
          <div
            key={msg.id}
            className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
          >
            <div className={`flex items-start gap-2 max-w-[80%] ${msg.role === 'user' ? 'flex-row-reverse' : ''}`}>
              <div className="w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center">
                {msg.role === 'user' ? <User size={18} /> : <Bot size={18} />}
              </div>
              <div className={`rounded-lg p-3 ${msg.role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-100'}`}>
                <p>{msg.content}</p>
                <span className="text-xs opacity-70 mt-1 block">
                  {msg.timestamp.toLocaleTimeString()}
                </span>
              </div>
            </div>
          </div>
        ))}
        {isLoading && (
          <div className="flex justify-start">
            <div className="bg-gray-100 rounded-lg p-3">
              <p className="animate-pulse">Thinking...</p>
            </div>
          </div>
        )}
        <div ref={messagesEndRef} />
      </div>

      <div className="mt-4 flex gap-2">
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
          placeholder="Type your message..."
          className="flex-1 border rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
        />
        <button
          onClick={sendMessage}
          disabled={isLoading}
          className="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600 disabled:opacity-50"
        >
          <Send size={18} />
        </button>
      </div>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 8: Test Your Bot

  1. Navigate to http://localhost:3000/chat
  2. Type: "Hello, I need help with my account"
  3. The Welcome Bot should greet you and route your intent
  4. Check the backend logs to see the OpenAI API calls

Why Human-Guided AI Matters

Traditional chatbots fail because they either:

  • Follow rigid scripts (frustrating for complex queries)
  • Use fully autonomous AI (unpredictable, hard to trust)

AYW's human-guided approach means:

  • AI handles routine queries instantly
  • Human experts guide complex conversations
  • The system learns from every interaction
  • Customers get fast, accurate, trustworthy support

Next Steps

Now that you've built your first AYW bot, you can:

  1. Add more bot types - Create specialist bots for support, sales, etc.
  2. Implement WebSocket - Add real-time streaming responses
  3. Add human escalation - Allow bots to hand off to human agents
  4. Integrate analytics - Track conversation success rates
  5. Deploy to production - Use Vercel for frontend, Railway or Render for backend

Resources


Building something cool with AYW? Tag your project with #AYWChatbot and share it in the comments below! 👇

Tags: #AI #Chatbots #TypeScript #React #NodeJS #OpenAI #Tutorial #HumanGuidedAI

Series: AYW Developer Tutorials (Part 1 of 6)

Top comments (0)