PHPackages                             wapkit/laravel-bot - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. wapkit/laravel-bot

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

wapkit/laravel-bot
==================

Extensible WhatsApp chatbot engine for Laravel. Plug in your own handlers and context per project.

v1.0.0(1mo ago)07↓100%MITPHPPHP ^8.2

Since Apr 24Pushed 1mo agoCompare

[ Source](https://github.com/alfredynhocg/wapkit-laravel-bot)[ Packagist](https://packagist.org/packages/wapkit/laravel-bot)[ RSS](/packages/wapkit-laravel-bot/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (5)Versions (2)Used By (0)

wapkit/laravel-bot
==================

[](#wapkitlaravel-bot)

Todo lo que necesitás para enviar mensajes de WhatsApp, recibir webhooks y construir chatbots completos en Laravel — usando la **WhatsApp Business Cloud API** oficial.

Este paquete incluye un motor listo para producción con gestión de estado de conversación, respaldo con IA, enrutamiento por intenciones y una Facade simple para que puedas enviar tu primer mensaje en menos de 5 minutos.

---

Requisitos previos
------------------

[](#requisitos-previos)

Antes de empezar, necesitás:

1. **PHP 8.2+** y **Laravel 10, 11, 12 o 13**
2. Una **[Cuenta de Meta Developers](https://developers.facebook.com/)** con una app de WhatsApp Business
3. Tu **Phone Number ID**, **Access Token**, **App Secret** y un **Verify Token** (esta cadena la elegís vos)

---

Instalación
-----------

[](#instalación)

```
composer require wapkit/laravel-bot
```

```
php artisan wapkit:install
```

Listo. El comando de instalación publica el archivo de configuración, ejecuta las migraciones y genera automáticamente el `WhatsAppServiceProvider` ya registrado en tu app.

---

Parte 1: Enviar un mensaje de WhatsApp desde Laravel
----------------------------------------------------

[](#parte-1-enviar-un-mensaje-de-whatsapp-desde-laravel)

Una vez instalado, podés enviar mensajes desde cualquier parte de tu aplicación usando la Facade `WapBot`.

**Agregá tus credenciales en `.env`:**

```
WHATSAPP_PHONE_NUMBER_ID=tu_phone_number_id
WHATSAPP_ACCESS_TOKEN=tu_access_token
WHATSAPP_APP_SECRET=tu_app_secret
WHATSAPP_VERIFY_TOKEN=tu_verify_token
```

**Enviar un mensaje de texto:**

```
use WapBot;

WapBot::sendText('+1234567890', '¡Hola desde Laravel! 👋');
```

**Enviar una imagen:**

```
WapBot::sendImage('+1234567890', 'https://ejemplo.com/imagen.jpg', '¡Mirá esto!');
```

**Enviar un documento:**

```
WapBot::sendDocument('+1234567890', 'https://ejemplo.com/factura.pdf', 'Tu factura', 'factura.pdf');
```

**Enviar botones interactivos:**

```
WapBot::sendButtons(
    to: '+1234567890',
    body: '¿En qué puedo ayudarte?',
    buttons: [
        ['id' => 'btn_pedidos',  'title' => '📦 Mis pedidos'],
        ['id' => 'btn_soporte',  'title' => '💬 Soporte'],
        ['id' => 'btn_catalogo', 'title' => '🛍️ Catálogo'],
    ],
);
```

**Enviar una plantilla de WhatsApp** (obligatoria para iniciar conversaciones):

```
WapBot::sendTemplate('+1234567890', 'pedido_confirmado', 'es', [
    ['type' => 'text', 'text' => 'PED-1234'],
    ['type' => 'text', 'text' => 'Bs 59.99'],
]);
```

Podés usar la Facade en controladores, jobs, listeners, comandos Artisan — en cualquier parte de tu app Laravel.

---

Parte 2: Recibir mensajes entrantes (Webhook)
---------------------------------------------

[](#parte-2-recibir-mensajes-entrantes-webhook)

El paquete **registra las rutas del webhook automáticamente** — no hace falta configuración adicional.

MétodoURL`GET``/webhook/whatsapp` — Verificación de Meta`POST``/webhook/whatsapp` — Mensajes entrantes**Exponé tu servidor local con ngrok:**

```
ngrok http 8000
```

**Configurá el webhook en Meta Developers:**

Copiá tu URL de ngrok, agregale `/webhook/whatsapp` y pegala en el campo **Webhook URL** de tu app de WhatsApp. Usá la misma cadena que pusiste en `WHATSAPP_VERIFY_TOKEN` como **Verify Token**.

Una vez verificado, cada mensaje enviado a tu número de WhatsApp llegará al controlador del paquete, que lo registra y lo enruta a tus handlers.

---

Parte 3: Construir un bot de WhatsApp completo
----------------------------------------------

[](#parte-3-construir-un-bot-de-whatsapp-completo)

Acá es donde wapkit se diferencia. En vez de escribir cadenas de `if/else` en tu controlador, registrás **handlers** — clases dedicadas para cada intención o botón — y el motor enruta automáticamente.

### Paso 1 — Generá tu estructura base

[](#paso-1--generá-tu-estructura-base)

```
php artisan wapkit:make-context TiendaContextBuilder
php artisan wapkit:make-handler MenuHandler
php artisan wapkit:make-handler PedidoHandler
```

### Paso 2 — Completá tu ContextBuilder

[](#paso-2--completá-tu-contextbuilder)

El `ContextBuilder` es el único lugar que conoce los datos de tu negocio. Le proporciona contexto al agente de IA para que las respuestas estén basadas en tu catálogo, políticas y horarios reales.

```
// app/WhatsApp/TiendaContextBuilder.php

class TiendaContextBuilder implements ContextBuilderInterface
{
    public function buildContext(?string $area = null): string
    {
        $productos = Producto::where('activo', true)
            ->get()
            ->map(fn ($p) => "- {$p->nombre}: Bs {$p->precio} | Tallas: {$p->tallas}")
            ->implode("\n");

        return  ['envio', 'delivery', 'llegar', 'despacho'],
        ];
    }
}
```

### Paso 3 — Escribí tus handlers

[](#paso-3--escribí-tus-handlers)

Cada handler es una clase PHP simple que envía una respuesta de WhatsApp. Inyectá `WhatsAppService` y `ConversationManager` según lo necesites.

```
// app/WhatsApp/Handlers/MenuHandler.php

class MenuHandler implements BotHandlerInterface
{
    public function __construct(private readonly WhatsAppService $wa) {}

    public function handle(string $from, array $context): void
    {
        $this->wa->sendList(
            to: $from,
            header: '🛍️ ModaFácil',
            body: '¿En qué puedo ayudarte?',
            footer: 'Tu tienda de confianza',
            buttonText: 'Ver opciones',
            sections: [
                [
                    'title' => 'Compras',
                    'rows'  => [
                        ['id' => 'btn_catalogo', 'title' => 'Ver catálogo'],
                        ['id' => 'btn_pedido',   'title' => 'Hacer un pedido'],
                    ],
                ],
            ],
        );
    }
}
```

```
// app/WhatsApp/Handlers/PedidoHandler.php

class PedidoHandler implements BotHandlerInterface
{
    public function __construct(
        private readonly WhatsAppService     $wa,
        private readonly ConversationManager $manager,
    ) {}

    public function handle(string $from, array $context): void
    {
        // Establecer estado para capturar el próximo mensaje de texto libre
        $this->manager->setState($from, 'esperando_pedido');
        $this->wa->sendText($from, '📝 Escribí los detalles de tu pedido (producto, talla, color):');
    }

    public function procesarPedido(string $from, string $detalle, array $context): void
    {
        $this->manager->reset($from);
        $this->wa->sendText($from, "✅ Pedido recibido: {$detalle}\n\nUn asesor te confirmará el precio en breve.");
    }
}
```

### Paso 4 — Generá y registrá el ServiceProvider

[](#paso-4--generá-y-registrá-el-serviceprovider)

Usá el comando incluido para generar el `WhatsAppServiceProvider` y registrarlo automáticamente en `bootstrap/providers.php`:

```
php artisan wapkit:make-provider
```

Esto crea `app/Providers/WhatsAppServiceProvider.php` con toda la estructura lista para completar, y lo agrega a `bootstrap/providers.php` sin que tengas que tocarlo manualmente.

> Si usás `wapkit:install`, este paso ya se ejecuta automáticamente.

Luego completá el provider con tus handlers y context builder:

```
// app/Providers/WhatsAppServiceProvider.php

use Wapkit\LaravelBot\Contracts\ContextBuilderInterface;
use Wapkit\LaravelBot\Core\HandlerRegistry;

class WhatsAppServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->bind(ContextBuilderInterface::class, TiendaContextBuilder::class);
    }

    public function boot(): void
    {
        $r = app(HandlerRegistry::class);

        // Handlers de intención por texto (activados por palabras clave)
        $r->intent('saludo',  MenuHandler::class);
        $r->intent('pedido',  PedidoHandler::class);

        // Handlers de botones (activados por ID exacto)
        $r->button('btn_menu',     MenuHandler::class);
        $r->button('btn_catalogo', CatalogoHandler::class);
        $r->button('btn_pedido',   PedidoHandler::class);

        // Handlers por prefijo — "producto_42" → ProductoHandler::showDetalle($from, '42', $ctx)
        $r->prefix('producto_', ProductoHandler::class, 'showDetalle');

        // Handlers de estado — se activa cuando el estado de conversación coincide y el usuario envía texto
        $r->state('esperando_pedido', PedidoHandler::class, 'procesarPedido');
    }
}
```

### Paso 5 — Agregá las palabras clave de tu dominio

[](#paso-5--agregá-las-palabras-clave-de-tu-dominio)

Publicá la configuración (si aún no lo hiciste) y extendé el array `keywords`:

```
// config/whatsapp-bot.php

'keywords' => [
    // Palabras clave base (incluidas por defecto)
    'saludo'  => ['hola', 'buenas', 'inicio', 'menu', 'start'],
    'soporte' => ['ayuda', 'soporte', 'hablar', 'humano'],

    // Palabras clave de tu dominio
    'pedido'   => ['pedido', 'comprar', 'quiero', 'necesito'],
    'precios'  => ['precio', 'cuanto cuesta', 'talla', 'valor'],
    'envios'   => ['envio', 'delivery', 'cuando llega', 'despacho'],
],
```

Ahora ejecutá `php artisan serve`, apuntá tu webhook a la URL local con ngrok y tu bot está en vivo.

---

Cómo funciona el enrutamiento
-----------------------------

[](#cómo-funciona-el-enrutamiento)

Cada mensaje entrante pasa por este flujo:

```
Usuario de WhatsApp
     ↓
POST /webhook/whatsapp
     ↓  Verificación HMAC + deduplicación de mensajes
BotEngine::handleMessage()
     ↓
ConversationManager — carga estado + contexto actuales
     ↓
Mensaje de TEXTO
  ├─ ¿Hay un handler registrado para el estado?  → StateHandler($from, $text, $ctx)
  ├─ ¿Exactamente 1 coincidencia por keyword?    → IntentHandler($from, $ctx)
  └─ 0 o múltiples coincidencias                → Agente IA (si está habilitado)
                                                    └─ sin respuesta → intención por defecto (menú)

Mensaje INTERACTIVO (botón / lista)
  ├─ ¿ID de botón exacto registrado?            → ButtonHandler($from, $ctx)
  ├─ ¿Comienza con un prefijo registrado?       → PrefixHandler($from, $sufijo, $ctx)
  └─ Sin coincidencia                           → intención por defecto (menú)

```

---

Agente de IA
------------

[](#agente-de-ia)

Cuando no se detecta ninguna intención, el motor llama al agente de IA automáticamente. Vos controlás **qué sabe** (via `ContextBuilder`) y **cómo se comporta** (via el system prompt).

**Activar/desactivar:**

```
AI_ENABLED=true
```

**Cambiar de proveedor** — el paquete usa [Prism](https://github.com/prism-php/prism) como capa de abstracción, así que cambiar es solo modificar el `.env`:

```
# Ollama (local, por defecto)
AI_PROVIDER=ollama
AI_MODEL=qwen2.5:7b
OLLAMA_HOST=http://localhost:11434

# OpenAI
AI_PROVIDER=openai
AI_MODEL=gpt-4o-mini
OPENAI_API_KEY=sk-...

# Anthropic
AI_PROVIDER=anthropic
AI_MODEL=claude-haiku-4-5-20251001
ANTHROPIC_API_KEY=sk-ant-...
```

**Ajustar el comportamiento de la IA:**

```
AI_MAX_TOKENS=512        # longitud máxima de respuesta
AI_TEMPERATURE=0.3       # 0.0 = determinístico, 1.0 = creativo
AI_MAX_INPUT_CHARS=500   # truncar mensajes largos antes de enviarlos
AI_RATE_LIMIT=20         # máximo de llamadas IA por minuto por número de teléfono
```

---

Temas avanzados
---------------

[](#temas-avanzados)

### Mensajes masivos con Laravel Queues

[](#mensajes-masivos-con-laravel-queues)

Para enviar mensajes a muchos usuarios sin bloquear el request, despachá un job:

```
// app/Jobs/EnviarNotificacionWhatsApp.php

class EnviarNotificacionWhatsApp implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        private string $telefono,
        private string $mensaje,
    ) {}

    public function handle(): void
    {
        WapBot::sendText($this->telefono, $this->mensaje);
    }
}
```

```
$usuarios = User::whereNotNull('phone')->get();

foreach ($usuarios as $usuario) {
    EnviarNotificacionWhatsApp::dispatch($usuario->phone, '¡Nueva oferta disponible! 🎉');
}
```

> **Importante:** Para iniciar conversaciones (no respuestas), WhatsApp requiere **Plantillas de Mensaje** pre-aprobadas. Usá `WapBot::sendTemplate()` para campañas salientes.

### Laravel Events

[](#laravel-events)

Para bots complejos, usá eventos para desacoplar el webhook de tu lógica de negocio:

```
// app/Events/MensajeWhatsAppRecibido.php

class MensajeWhatsAppRecibido
{
    use Dispatchable, SerializesModels;

    public function __construct(
        public string $telefono,
        public string $mensaje,
        public string $estado,
    ) {}
}
```

```
// Despachar desde tu handler
event(new MensajeWhatsAppRecibido($from, $text, $estadoActual));
```

### Laravel Notifications

[](#laravel-notifications)

Enviá mensajes de WhatsApp a través del sistema de notificaciones de Laravel:

```
// app/Notifications/PedidoConfirmado.php

class PedidoConfirmado extends Notification
{
    public function via($notifiable): array
    {
        return ['database', 'whatsapp_custom'];
    }

    public function toWhatsApp($notifiable): void
    {
        WapBot::sendTemplate(
            $notifiable->phone,
            'pedido_confirmado',
            'es',
            [['type' => 'text', 'text' => $this->pedido->numero]]
        );
    }
}

// Uso
$usuario->notify(new PedidoConfirmado($pedido));
```

### Estado y contexto de conversación

[](#estado-y-contexto-de-conversación)

Usá `ConversationManager` dentro de cualquier handler para controlar el flujo de conversación:

```
use Wapkit\LaravelBot\Core\ConversationManager;

// Establecer un estado para capturar el próximo mensaje del usuario
$this->manager->setState($from, 'esperando_ci');

// Establecer estado + guardar datos para pasos posteriores
$this->manager->setState($from, 'esperando_confirmacion', ['pedido_id' => 42]);

// Leer el contexto guardado en el siguiente handler
public function confirmar(string $from, string $respuesta, array $context): void
{
    $pedidoId = $context['pedido_id']; // 42
}

// Volver al estado inicial (menú)
$this->manager->reset($from);

// Vincular una conversación de WhatsApp con un usuario del sistema
$this->manager->linkClient($from, $usuario->id);
```

### Registro en base de datos

[](#registro-en-base-de-datos)

Todos los mensajes e interacciones con IA se registran automáticamente:

TablaContenido`whatsapp_conversations`Estado actual, contexto JSON, ID de cliente vinculado`whatsapp_messages`Log completo de mensajes entrantes y salientes con timestamps`whatsapp_ai_logs`Input, prompt, output, tokens, latencia y errores de IAConsultálos como cualquier modelo Eloquent:

```
use Wapkit\LaravelBot\Models\Conversation;
use Wapkit\LaravelBot\Models\Message;

// Todas las conversaciones en estado soporte
Conversation::where('estado', 'soporte')->get();

// Últimos 20 mensajes de un número
Message::where('phone', '591700000001')->latest()->take(20)->get();
```

---

Métodos disponibles en la Facade `WapBot`
-----------------------------------------

[](#métodos-disponibles-en-la-facade-wapbot)

MétodoDescripción`sendText($to, $mensaje)`Mensaje de texto plano`sendImage($to, $fuente, $caption)`Imagen desde URL o media ID`sendDocument($to, $fuente, $caption, $nombre)`PDF, Word, Excel, etc.`sendAudio($to, $fuente)`Archivo de audio`sendVideo($to, $fuente, $caption)`Archivo de video`sendLocation($to, $lat, $lng, $nombre, $direccion)`Pin en mapa`sendLocationRequest($to, $body)`Solicitar ubicación al usuario`sendButtons($to, $body, $buttons, $header, $footer)`Botones de respuesta rápida (máx. 3)`sendList($to, $header, $body, $footer, $buttonText, $sections)`Menú de lista desplazable`sendCtaUrl($to, $body, $buttonText, $url)`Botón de llamada a la acción con enlace`sendTemplate($to, $nombre, $idioma, $parametros)`Plantilla de mensaje pre-aprobada`sendTyping($to, $messageId)`Mostrar indicador de escritura`uploadMedia($filePath)`Subir un archivo local y obtener el media ID---

Comandos Artisan
----------------

[](#comandos-artisan)

ComandoDescripción`php artisan wapkit:install`Publicar configuración, ejecutar migraciones y generar el ServiceProvider`php artisan wapkit:make-provider`Generar `WhatsAppServiceProvider` y registrarlo en `bootstrap/providers.php``php artisan wapkit:make-handler {Nombre}`Generar un stub de handler`php artisan wapkit:make-context {Nombre}`Generar un stub de ContextBuilder---

Referencia de variables de entorno
----------------------------------

[](#referencia-de-variables-de-entorno)

```
# WhatsApp Cloud API
WHATSAPP_PHONE_NUMBER_ID=
WHATSAPP_ACCESS_TOKEN=
WHATSAPP_APP_SECRET=
WHATSAPP_VERIFY_TOKEN=
WHATSAPP_API_VERSION=v20.0

# Mensajes del bot
BOT_WELCOME_MESSAGE="👋 ¡Hola, {nombre}! ¿En qué puedo ayudarte hoy?"
BOT_THINKING_MESSAGE="⏳ Un momento..."
BOT_SUPPORT_MESSAGE="📩 Mensaje recibido. Un asesor te atenderá pronto."
BOT_FALLBACK_MESSAGE="No entendí tu consulta. Escribí *menu* para ver las opciones."

# Agente de IA
AI_ENABLED=true
AI_PROVIDER=ollama
AI_MODEL=qwen2.5:7b
OLLAMA_HOST=http://localhost:11434
AI_MAX_TOKENS=512
AI_TEMPERATURE=0.3
AI_TIMEOUT_SECONDS=30
AI_MAX_INPUT_CHARS=500
AI_RATE_LIMIT=20
```

---

Preguntas frecuentes
--------------------

[](#preguntas-frecuentes)

**¿Cómo envío un mensaje de WhatsApp desde un controlador?**

```
use WapBot;

class PedidoController extends Controller
{
    public function confirmar(Pedido $pedido): JsonResponse
    {
        WapBot::sendText($pedido->usuario->phone, "✅ Pedido #{$pedido->numero} confirmado.");
        return response()->json(['status' => 'ok']);
    }
}
```

**¿Cómo inicio una conversación con un usuario (sin que él haya escrito primero)?**

Usá una plantilla pre-aprobada — WhatsApp lo requiere para iniciar conversaciones:

```
WapBot::sendTemplate($phone, 'mensaje_bienvenida', 'es');
```

**¿Cómo desactivo la IA y uso solo handlers?**

```
AI_ENABLED=false
```

Cuando está desactivada, los mensajes sin coincidencia caen al handler de intención por defecto (normalmente tu menú).

**¿Puedo usar un proveedor de IA diferente?**

Sí. Configurá `AI_PROVIDER` como `openai`, `anthropic` o cualquier [proveedor soportado por Prism](https://github.com/prism-php/prism). No se necesitan cambios en el código.

**¿Cómo paso datos entre pasos de un flujo multi-paso?**

Usá `setState($from, $estado, $arrayContexto)` para guardar datos y leelos desde `$context` en el siguiente handler:

```
// Paso 1
$this->manager->setState($from, 'paso_2', ['nombre' => $nombre]);

// Handler del Paso 2
public function paso2(string $from, string $input, array $context): void
{
    $nombre = $context['nombre'];
}
```

**¿Cómo manejo tipos de mensajes no soportados (imágenes, audio, reacciones)?**

El controlador del webhook solo enruta tipos `text` e `interactive`. Los demás tipos se registran pero se ignoran silenciosamente. Extendé `BotEngine::handleMessage()` en tu propio controlador si necesitás manejo personalizado.

**¿Puedo usar esto con múltiples números de WhatsApp?**

Cada instancia de la aplicación Laravel maneja un número de teléfono (configurado via `WHATSAPP_PHONE_NUMBER_ID`). Para múltiples números, desplegá instancias separadas o sobreescribí la configuración de `WhatsAppService` en tiempo de ejecución.

---

Licencia
--------

[](#licencia)

MIT

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance90

Actively maintained with recent releases

Popularity6

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

46d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f4f256f7ff4b3b0716358fbe8af28a0c39c1f2512d359cd6070d9673bfcd35f9?d=identicon)[alfredynho](/maintainers/alfredynho)

---

Top Contributors

[![alfredynhocg](https://avatars.githubusercontent.com/u/114483425?v=4)](https://github.com/alfredynhocg "alfredynhocg (4 commits)")

### Embed Badge

![Health badge](/badges/wapkit-laravel-bot/health.svg)

```
[![Health](https://phpackages.com/badges/wapkit-laravel-bot/health.svg)](https://phpackages.com/packages/wapkit-laravel-bot)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3325.1M337](/packages/psalm-plugin-laravel)[pressbooks/pressbooks

Pressbooks is an open source book publishing tool built on a WordPress multisite platform. Pressbooks outputs books in multiple formats, including PDF, EPUB, web, and a variety of XML flavours, using a theming/templating system, driven by CSS.

45344.0k1](/packages/pressbooks-pressbooks)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
