--- title: Construye un Agente de IA para WhatsApp con NestJS y Zavu description: Aprende a construir un agente de WhatsApp potenciado por IA usando NestJS y el AI Gateway administrado de Zavu. date: 2025-12-23 author: Jennifer Villalobos locale: es source: https://www.zavu.dev/es/blog/whatsapp-ai-agents-nestjs tags: Agentes IA, WhatsApp, NestJS, TypeScript --- # Construye un Agente de IA para WhatsApp con NestJS y Zavu En este tutorial, construiras un agente de IA para WhatsApp listo para producción usando NestJS y Zavu. La mejor parte? No necesitas gestiónar 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 más) directamente desde tu dashboard de Zavu. ## Lo Que Construiremos Una aplicación 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 automáticamente el contexto de la conversacion ## Requisitos Previos - Node.js 18+ - Una cuenta de Zavu con credenciales de API - Conocimiento básico 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 través de una sola integración. ## 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 ``` 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 ``` ## Configuración 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 gestiónar API keys individuales: - **GPT-4o, GPT-4o-mini** - Los modelos más 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('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('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 Aplicación 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(`Aplicación corriendo en: http://localhost:${PORT}`); } bootstrap(); ``` ## Desplegar y Configurar 1. Despliega tu app NestJS a un servidor con HTTPS 2. Configura el webhook en tu dashboard de Zavu 3. Crea un agente de IA para tu sender 4. 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: 1. Ve a **Settings** > **AI Providers** en tu dashboard de Zavu 2. Agrega tus API keys 3. 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 específicas del dominio - Crea herramientas personalizadas para integrar con tus sistemas backend Consulta la [documentación de Zavu](https://docs.zavu.dev) para más ejemplos y funciones avanzadas.