I just shipped a new feature package for Volet: volet-chatbot. It adds a chat UI to your Volet widget, backed by any OpenAI-compatible endpoint: OpenAI itself, or your own Laravel app's backend.

What is Volet, again?

Volet is the customer interaction widget I've been building for Laravel apps. Think Crisp, Intercom, or Tawk.to, but open source and yours to run. It's a floating panel that opens on click, and everything inside it is a pluggable feature: a Web Component you register from your own VoletServiceProvider. Volet ships with feedback message collection out of the box, and the ecosystem grows through feature packages like volet-featureboard, a full feature-request-and-voting board your visitors can use straight from the widget.

volet-chatbot is the newest one: a chat interface for talking to an LLM, dropped straight into that same panel.

Why a chatbot feature

A support widget without a chat option feels incomplete in 2026. But "just add a chatbot" hides a real problem the moment you actually build it: the widget is frontend-heavy JavaScript running in a visitor's browser, and an LLM API key is not something you can ever let that browser hold. Every architecture decision in this package flows from that one constraint.

How it works

Rather than writing yet another HTTP client for OpenAI's wire format, volet-chatbot is built directly on Laravel's own first-party laravel/ai package. That turned out to be the right call for almost everything this feature needs:

  • The key never leaves the server. The widget's JavaScript calls a route on your own Laravel app; that route resolves an Agent class and does the actual model call server-side. Your OPENAI_API_KEY lives in .env, full stop.
  • Point it anywhere. Default provider is OpenAI itself, but override OPENAI_URL and it talks to your own backend, or any other OpenAI-compatible endpoint, instead. No code change.
  • Streaming, for free. Responses stream token-by-token over SSE, because laravel/ai already does that well. I didn't need to hand-roll a stream parser.
  • Conversation history, for free. Guests are tracked by a conversation_id minted on the first message, stored client-side (localStorage), and sent back on the next one. No account or cookie required. If a visitor happens to be logged in, their user_id rides along automatically. This is laravel/ai's own conversation storage, volet-chatbot doesn't add a single migration of its own.
  • Extending it stays out of my hands, on purpose. Want tools, MCP servers, structured output, provider failover? Extend the shipped ChatbotAgent class in your own app and point one config key at your subclass. Everything past "which agent answers this widget" is laravel/ai's existing surface. I didn't build a second plugin system on top of one that already exists.

Installation

composer require mydnic/volet-chatbot

php artisan vendor:publish --provider="Laravel\Ai\AiServiceProvider"
php artisan migrate

php artisan vendor:publish --tag="volet-assets" --force
php artisan vendor:publish --tag="volet-chatbot-config"

Set your key, register the feature in your VoletServiceProvider:

use Mydnic\VoletChatbot\VoletChatbot;

$volet->register(
    (new VoletChatbot)->setLabel('Chat with us')
);

Add @volet to your layout like any other Volet feature, and you've got a streaming chat widget on your site.