Agentes IAWhatsAppNestJSTypeScript

Construye un Agente de IA para WhatsApp con NestJS y Zavu

Aprende a construir un agente de WhatsApp potenciado por IA usando NestJS y el AI Gateway administrado de Zavu. Sin necesidad de API keys externas - accede a GPT-4, Claude y mas a traves de Zavu.

Redactado por: Jennifer VillalobosRevisado por: Victor Villalobos23 de diciembre de 202512 min

Construye un Agente de IA para WhatsApp con NestJS y Zavu

En este tutorial, construiras un agente de IA para WhatsApp listo para produccion usando NestJS y Zavu. La mejor parte? No necesitas gestionar ninguna API key de IA externa - el AI Gateway de Zavu te da acceso a todos los modelos de IA de primer nivel (GPT-4, Claude, Gemini, Mistral y mas) directamente desde tu dashboard de Zavu.

Lo Que Construiremos

Una aplicacion NestJS que:
  • Recibe mensajes entrantes de WhatsApp via webhooks
  • Verifica firmas de webhook para seguridad
  • Usa los agentes de IA administrados de Zavu para respuestas inteligentes
  • Aprovecha la inyeccion de dependencias y arquitectura modular de NestJS
  • Mantiene automaticamente el contexto de la conversacion

Requisitos Previos

  • Node.js 18+
  • Una cuenta de Zavu con credenciales de API
  • Conocimiento basico de TypeScript
No se requieren API keys de IA externas! El AI Gateway de Zavu proporciona acceso a todos los modelos de IA principales a traves de una sola integracion.

Instalacion

Crea un nuevo proyecto NestJS e instala las dependencias:

Elige tu gestor de paquetes:

Bun (recomendado):
bash
bun install @zavudev/sdk @nestjs/config dotenv
npm:
bash
npm install @zavudev/sdk @nestjs/config dotenv
pnpm:
bash
pnpm add @zavudev/sdk @nestjs/config dotenv

Luego crea el proyecto:

bash
npx @nestjs/cli new whatsapp-agent cd whatsapp-agent

Estructura del Proyecto

text
whatsapp-agent/ ├── src/ │ ├── app.module.ts │ ├── main.ts │ ├── webhook/ │ │ ├── webhook.module.ts │ │ ├── webhook.controller.ts │ │ ├── webhook.service.ts │ │ └── dto/ │ │ └── webhook-event.dto.ts │ └── zavu/ │ ├── zavu.module.ts │ └── zavu.service.ts ├── .env └── nest-cli.json

Configuracion del Entorno

Crea un archivo .env en la raiz de tu proyecto:

bash
ZAVUDEV_API_KEY=tu_api_key_de_zavu ZAVU_WEBHOOK_SECRET=tu_secreto_de_webhook PORT=3000

Eso es todo! No necesitas keys de OpenAI, Anthropic u otros proveedores de IA.

Como Funciona el AI Gateway de Zavu

Zavu proporciona un AI Gateway unificado que te da acceso a todos los modelos de IA de primer nivel sin gestionar API keys individuales:

  • GPT-4o, GPT-4o-mini - Los modelos mas recientes de OpenAI
  • Claude 3.5 Sonnet, Claude 3 Opus - Modelos de Anthropic
  • Gemini Pro - Modelos de IA de Google
  • Mistral Large - Modelos de Mistral AI
Puedes configurar que modelo usar directamente en tu dashboard de Zavu.

Crear el Modulo de Zavu

Crea src/zavu/zavu.module.ts:

typescript
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { ZavuService } from './zavu.service'; @Module({ imports: [ConfigModule], providers: [ZavuService], exports: [ZavuService], }) export class ZavuModule {}

Crea src/zavu/zavu.service.ts:

typescript
import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import Zavudev from '@zavudev/sdk'; @Injectable() export class ZavuService { private readonly zavu: Zavu; constructor(private configService: ConfigService) { this.zavu = new Zavu({ apiKey: this.configService.get<string>('ZAVUDEV_API_KEY'), }); } getClient(): Zavu { return this.zavu; } async createAgent(senderId: string, name: string, systemPrompt: string, model = 'gpt-4o-mini') { return await this.zavu.senders.agent.create({ senderId, name, provider: 'zavu', model, systemPrompt, contextWindowMessages: 10, includeContactMetadata: true, enabled: true }); } async createKnowledgeBase(senderId: string, name: string, description?: string) { return await this.zavu.senders.agent.knowledgeBases.create({ senderId, name, description }); } async addDocumentToKB(senderId: string, kbId: string, title: string, content: string) { return await this.zavu.senders.agent.knowledgeBases.documents.create({ senderId, kbId, title, content }); } async createTool(senderId: string, name: string, description: string, webhookUrl: string, parameters: any) { return await this.zavu.senders.agent.tools.create({ senderId, name, description, webhookUrl, parameters }); } }

Crear el Modulo de Webhook

Crea src/webhook/dto/webhook-event.dto.ts:

typescript
export class WebhookEventDto { type: string; data: any; timestamp?: string; }

Crea src/webhook/webhook.service.ts:

typescript
import { Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import * as crypto from 'crypto'; @Injectable() export class WebhookService { private readonly logger = new Logger(WebhookService.name); constructor(private configService: ConfigService) {} verifyWebhookSignature(payload: Buffer, signature: string): boolean { const secret = this.configService.get<string>('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) ); } async handleWebhookEvent(event: any) { this.logger.log(Evento de webhook recibido: ${event.type}); if (event.type === 'message.inbound') { const message = event.data; this.logger.log(Mensaje de ${message.from}: ${message.text}); } return { status: 'ok' }; } }

Crea src/webhook/webhook.controller.ts:

typescript
import { Controller, Post, Body, Headers, RawBody, HttpStatus, HttpException } from '@nestjs/common'; import { WebhookService } from './webhook.service'; @Controller('webhook') export class WebhookController { constructor(private readonly webhookService: WebhookService) {} @Post() async handleWebhook( @Body() body: any, @Headers('x-zavu-signature') signature: string, @RawBody() rawBody: Buffer, ) { if (!this.webhookService.verifyWebhookSignature(rawBody, signature)) { throw new HttpException('No autorizado', HttpStatus.UNAUTHORIZED); } try { return await this.webhookService.handleWebhookEvent(body); } catch (error) { throw new HttpException( 'Error interno del servidor', HttpStatus.INTERNAL_SERVER_ERROR ); } } }

Crea src/webhook/webhook.module.ts:

typescript
import { Module } from '@nestjs/common'; import { WebhookController } from './webhook.controller'; import { WebhookService } from './webhook.service'; import { ZavuModule } from '../zavu/zavu.module'; @Module({ imports: [ZavuModule], controllers: [WebhookController], providers: [WebhookService], }) export class WebhookModule {}

Actualizar el Modulo de la Aplicacion

Actualiza src/app.module.ts:

typescript
import { Module } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; import { WebhookModule } from './webhook/webhook.module'; @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, }), WebhookModule, ], }) export class AppModule {}

Actualizar main.ts

Actualiza src/main.ts:

typescript
import { NestFactory } from '@nestjs/core'; import { ValidationPipe } from '@nestjs/common'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.use((req, res, next) => { if (req.path === '/webhook' && req.method === 'POST') { let data = ''; req.setEncoding('utf8'); req.on('data', (chunk) => { data += chunk; }); req.on('end', () => { req.rawBody = Buffer.from(data); next(); }); } else { next(); } }); app.useGlobalPipes(new ValidationPipe()); const PORT = process.env.PORT || 3000; await app.listen(PORT); console.log(Aplicacion corriendo en: http://localhost:${PORT}); } bootstrap();

Desplegar y Configurar

  • Despliega tu app NestJS a un servidor con HTTPS
  • Configura el webhook en tu dashboard de Zavu
  • Crea un agente de IA para tu sender
  • Ejecuta el servidor:
  • bash
    npm run start:prod

    Crear un Agente de IA Administrado

    Opcion 1: Via Dashboard de Zavu

    Crea un agente directamente en el Dashboard de Zavu.

    Opcion 2: Via Servicio NestJS

    Crea un controlador src/agent/agent.controller.ts:

    typescript
    import { Controller, Post, Body } from '@nestjs/common'; import { ZavuService } from '../zavu/zavu.service'; @Controller('agent') export class AgentController { constructor(private readonly zavuService: ZavuService) {} @Post('create') async createAgent(@Body() body: { senderId: string; name: string; systemPrompt: string; model?: string; }) { const agent = await this.zavuService.createAgent( body.senderId, body.name, body.systemPrompt, body.model ); return { agent }; } }

    Bases de Conocimiento

    typescript
    // En zavu.service.ts async createKnowledgeBase(senderId: string, name: string, description?: string) { const response = await this.zavu.senders.agent.knowledgeBases.create({ senderId, name, description }); return response.knowledgeBase; } async addDocumentToKB(senderId: string, kbId: string, title: string, content: string) { const response = await this.zavu.senders.agent.knowledgeBases.documents.create({ senderId, kbId, title, content }); return response.document; }

    Herramientas Personalizadas

    typescript
    // En zavu.service.ts async createTool( senderId: string, name: string, description: string, webhookUrl: string, parameters: any ) { const response = await this.zavu.senders.agent.tools.create({ senderId, name, description, webhookUrl, parameters }); return response.tool; }

    Crea un controlador para el endpoint de la herramienta:

    typescript
    import { Controller, Post, Body } from '@nestjs/common'; @Controller('tools') export class ToolsController { @Post('order-status') async getOrderStatus(@Body() body: { order_id: string }) { const orderStatus = await this.getOrderFromDatabase(body.order_id); return { success: true, data: { order_id: body.order_id, status: orderStatus.status, estimated_delivery: orderStatus.delivery_date, tracking_url: orderStatus.tracking_url } }; } private async getOrderFromDatabase(orderId: string) { return { status: 'enviado', delivery_date: '2024-01-20', tracking_url: 'https://tracker.example.com/ORD-12345' }; } }

    Usando Tus Propias Credenciales de IA (Opcional)

    Si prefieres usar tus propias credenciales de proveedor de IA:

  • Ve a Settings > AI Providers en tu dashboard de Zavu
  • Agrega tus API keys
  • Al crear un agente, usa provider: "openai" en lugar de provider: "zavu"
  • Proximos Pasos

    • Explora el dashboard de AI Agents para monitorear conversaciones
    • Agrega bases de conocimiento para respuestas especificas del dominio
    • Crea herramientas personalizadas para integrar con tus sistemas backend
    Consulta la documentacion de Zavu para mas ejemplos y funciones avanzadas.

    Necesitas ayuda? Contactanos o unete a nuestra comunidad en Discord para soporte.

    Siguenos en redes sociales

    Mira como funciona

    Agenda una demo personalizada para ver como los Agentes IA de Zavu pueden transformar tu comunicacion con clientes.

    Construye un Agente de IA para WhatsApp con NestJS y Zavu | Zavu Blog | Zavu