AI AgentsWhatsAppNext.jsApp Router

Build a WhatsApp AI Agent with Next.js and Zavu

Learn how to build an AI-powered WhatsApp agent using Next.js and Zavu's managed AI Gateway. No external API keys required - access GPT-4, Claude, and more through Zavu.

Written by: Victor VillalobosReviewed by: Jennifer VillalobosDecember 23, 202510 min read

Build a WhatsApp AI Agent with Next.js and Zavu

In this tutorial, you'll build a production-ready WhatsApp AI agent using Next.js App Router and Zavu. The best part? You don't need to manage any external AI API keys - Zavu's AI Gateway gives you access to all top-tier AI models (GPT-4, Claude, Gemini, Mistral, and more) directly from your Zavu dashboard.

What We're Building

A Next.js application that:
  • Receives incoming WhatsApp messages via Route Handlers
  • Verifies webhook signatures for security
  • Uses Zavu's managed AI agents for intelligent responses
  • Leverages Next.js App Router and Server Actions
  • Automatically maintains conversation context

Prerequisites

  • Node.js 18+
  • A Zavu account with API credentials
  • Basic React and TypeScript knowledge
No external AI API keys required! Zavu's AI Gateway provides access to all major AI models through a single integration.

Installation

Create a new Next.js project or add to an existing one:

Choose your package manager:

Bun (recommended):
bash
bun install @zavudev/sdk
npm:
bash
npm install @zavudev/sdk
pnpm:
bash
pnpm add @zavudev/sdk

Then create the project:

bash
npx create-next-app@latest whatsapp-agent cd whatsapp-agent
When prompted, select:
  • TypeScript: Yes
  • ESLint: Yes
  • App Router: Yes
  • Src directory: Yes
  • Import alias: @/*

Project Structure

text
whatsapp-agent/ ├── src/ │ ├── app/ │ │ ├── api/ │ │ │ └── webhook/ │ │ │ └── route.ts │ │ └── page.tsx │ └── lib/ │ └── zavu.ts ├── .env.local └── package.json

Environment Configuration

Create a .env.local file in your project root:

bash
ZAVUDEV_API_KEY=your_zavu_api_key ZAVU_WEBHOOK_SECRET=your_webhook_secret

That's it! No OpenAI, Anthropic, or other AI provider keys needed.

How Zavu AI Gateway Works

Zavu provides a unified AI Gateway that gives you access to all top-tier AI models without managing individual API keys:

  • GPT-4o, GPT-4o-mini - OpenAI's latest models
  • Claude 3.5 Sonnet, Claude 3 Opus - Anthropic's models
  • Gemini Pro - Google's AI models
  • Mistral Large - Mistral AI's models
You can configure which model to use directly in your Zavu dashboard.

Initialize the Zavu Client

Create src/lib/zavu.ts:

typescript
import Zavudev from '@zavudev/sdk'; export const zavu = new Zavu({ apiKey: process.env.ZAVUDEV_API_KEY, });

Create the Webhook Route Handler

Create src/app/api/webhook/route.ts:

typescript
import { NextRequest, NextResponse } from 'next/server'; import crypto from 'crypto'; import { zavu } from '@/lib/zavu'; function verifyWebhookSignature(payload: string, signature: string): boolean { const secret = process.env.ZAVU_WEBHOOK_SECRET; if (!signature
!secret) { return false; } const expected = crypto .createHmac('sha256', secret) .update(payload) .digest('hex'); return crypto.timingSafeEqual( Buffer.from(sha256=${expected}), Buffer.from(signature) ); } export async function POST(request: NextRequest) { try { const rawBody = await request.text(); const signature = request.headers.get('x-zavu-signature')
''; if (!verifyWebhookSignature(rawBody, signature)) { console.error('Invalid webhook signature'); return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const payload = JSON.parse(rawBody); const eventType = payload.type; console.log(Received webhook event: ${eventType}); if (eventType === 'message.inbound') { const message = payload.data; console.log(Message from ${message.from}: ${message.text}); } return NextResponse.json({ status: 'ok' }); } catch (error) { console.error('Webhook error:', error); return NextResponse.json( { error: 'Internal server error' }, { status: 500 } ); } }

Deploy and Configure

  • Deploy your Next.js app to Vercel or any platform with HTTPS
  • Configure the webhook in your Zavu dashboard:
  • - Go to Senders > Select your sender > Webhook - Set URL to: https://yourdomain.com/api/webhook - Enable events: message.inbound - Copy the webhook secret to your .env.local file
  • Create an AI agent for your sender in the Zavu dashboard
  • Deploy your app:
  • bash
    npm run build npm start

    Testing Locally

    For local testing, use ngrok:

    bash
    npx ngrok http 3000

    Copy the HTTPS URL and configure it in your Zavu webhook settings.

    Create a Managed AI Agent

    Option 1: Via Zavu Dashboard

  • Go to Senders in your Zavu dashboard
  • Select the sender you want to add AI capabilities to
  • Click on AI Agent tab
  • Configure your agent and save
  • Option 2: Via Server Actions

    Create a server action at src/app/actions/agent.ts:

    typescript
    'use server'; import { zavu } from '@/lib/zavu'; import { revalidatePath } from 'next/cache'; export async function createAgent(formData: FormData) { const senderId = formData.get('senderId') as string; const name = formData.get('name') as string; const systemPrompt = formData.get('systemPrompt') as string; const response = await zavu.senders.agent.create({ senderId, name, provider: 'zavu', model: 'gpt-4o-mini', systemPrompt, contextWindowMessages: 10, includeContactMetadata: true, enabled: true }); revalidatePath('/dashboard'); return response.agent; } export async function getAgentStats(senderId: string) { const response = await zavu.senders.agent.stats(senderId); return response; }

    Knowledge Bases

    Create a server action for knowledge bases at src/app/actions/knowledge-base.ts:

    typescript
    'use server'; import { zavu } from '@/lib/zavu'; export async function createKnowledgeBase(formData: FormData) { const senderId = formData.get('senderId') as string; const name = formData.get('name') as string; const description = formData.get('description') as string; const response = await zavu.senders.agent.knowledgeBases.create({ senderId, name, description }); return response.knowledgeBase; } export async function addDocument(formData: FormData) { const senderId = formData.get('senderId') as string; const kbId = formData.get('kbId') as string; const title = formData.get('title') as string; const content = formData.get('content') as string; const response = await zavu.senders.agent.knowledgeBases.documents.create({ senderId, kbId, title, content }); return response.document; }

    Custom Tools

    Create a tool endpoint at src/app/api/tools/order-status/route.ts:

    typescript
    import { NextRequest, NextResponse } from 'next/server'; export async function POST(request: NextRequest) { try { const body = await request.json(); const { order_id } = body; const orderStatus = await getOrderFromDatabase(order_id); return NextResponse.json({ success: true, data: { order_id: order_id, status: orderStatus.status, estimated_delivery: orderStatus.delivery_date, tracking_url: orderStatus.tracking_url } }); } catch (error) { console.error('Tool error:', error); return NextResponse.json( { success: false, error: 'Internal server error' }, { status: 500 } ); } } async function getOrderFromDatabase(orderId: string) { return { status: 'shipped', delivery_date: '2024-01-20', tracking_url: 'https://tracker.example.com/ORD-12345' }; }

    Create the tool via server action:

    typescript
    // src/app/actions/tools.ts 'use server'; import { zavu } from '@/lib/zavu'; export async function createOrderStatusTool(formData: FormData) { const senderId = formData.get('senderId') as string; const webhookUrl = https://${process.env.VERCEL_URL || 'localhost:3000'}/api/tools/order-status; const response = await zavu.senders.agent.tools.create({ senderId, name: 'get_order_status', description: 'Get the current status of a customer order', webhookUrl, parameters: { type: 'object', properties: { order_id: { type: 'string', description: 'The order ID to look up' } }, required: ['order_id'] } }); return response.tool; }

    Using Your Own AI Credentials (Optional)

    If you prefer to use your own AI provider credentials:

  • Go to Settings > AI Providers in your Zavu dashboard
  • Add your API keys for OpenAI, Anthropic, Google, or Mistral
  • When creating an agent, use provider: "openai" instead of provider: "zavu"
  • This gives you full control over billing while still benefiting from Zavu's unified API.

    Next Steps

    • Explore the AI Agents dashboard to monitor conversations
    • Add knowledge bases for domain-specific responses
    • Create custom tools to integrate with your backend systems
    • Build conversation flows for specific use cases
    • Add a dashboard UI to manage your agents
    Check out the Zavu documentation for more examples and advanced features.

    Need help? Contact us or join our Discord community for support.

    Follow us on social media

    See it in action

    Book a personalized demo to see how Zavu AI Agents can transform your customer communication.

    Build a WhatsApp AI Agent with Next.js and Zavu | Zavu Blog | Zavu