Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Studio Laravel Package

botman/studio

BotMan Studio is a Laravel-based starter kit for building chatbots with the BotMan PHP framework. It provides a ready-to-use application, integrated chat testing interface, and common messaging drivers so you can scaffold, run, and debug bots quickly.

View on GitHub
Deep Wiki
Context7

Getting Started

BotMan Studio is not a package you composer require into an existing app — it's a full Laravel skeleton (Laravel 5.7-era) with botman/botman, botman/laravel, and the web widget pre-wired. Treat it as a starting project or as a reference implementation.

composer create-project --prefer-dist botman/studio botman-app
cd botman-app
cp .env.example .env && php artisan key:generate
php artisan serve

Set APP_URL correctly in .env (the widget and every webhook URL depend on it), then drop driver credentials into config/botman/<driver>.php (Slack, Telegram, Facebook, Twilio, Nexmo) — Studio keeps them in a config/botman/ folder rather than a single file.

Where to look first, in order:

  1. routes/botman.php — the bot's brain. All hears / receives / on handlers live here by default.
  2. app/Http/Controllers/BotManController.php — handle() calls app('botman')->listen(); startConversation() renders the chat widget.
  3. routes/web.php — the botman and botman/chat routes, plus the CSRF exception in app/Http/Middleware/VerifyCsrfToken.php.
  4. config/botman/config.php — conversation_cache_time and user_cache_time (both in minutes).

First use case — prove the loop in 60 seconds, no channel required:

php artisan botman:tinker
BotMan > hi
Bot > Hey there!

Add a handler and retry:

// routes/botman.php
$botman->hears('hello', function ($bot) {
    $bot->reply('Hey there!');
});

$botman->hears('order {id}', function ($bot, $id) {
    $bot->reply("Looking up order #{$id}...");
});

Then open https://your-app.test/botman for the built-in web widget, and finally point a real channel at https://your-app.test/botman (Telegram setWebhook, Slack Event Subscriptions, Facebook callback URL + verify token). php artisan botman:list shows what's registered.

Implementation Patterns

Three handler types, and they are not interchangeable:

$botman->hears('status', StatusHandler::class);        // pattern match, first-match-wins
$botman->receives(['text','image'], function ($bot) {}); // catch-all by message type
$botman->on('conversation.started', function ($bot, $payload) {}); // driver/platform events

hears supports {placeholders} and regex. Registration order matters — put specific patterns above broad ones, and keep a single receives fallback at the bottom for the "I didn't understand" path.

Conversations for anything multi-step. Don't build state machines out of hears handlers; use a Conversation class. This is the single biggest maintainability win:

class OnboardConversation extends Conversation
{
    public function run()
    {
        $this->ask('What is your email?', function (Answer $answer) {
            $this->email = $answer->getText();
            $this->askForLocation('Where should we ship?', function (Answer $loc) {
                // $loc->getLatitude(), getLongitude()
                $this->say('Saved.');
                $this->stop();
            });
        });
    }
}

$botman->hears('onboard', function ($bot) {
    $bot->startConversation(new OnboardConversation());
});

The Answer object gives you getText(), getValue(), getImages(), getLocation(), plus the raw payload via getMessage()->getPayload(). Use $this->repeat(), $this->stop(), and $this->bot inside conversations.

Middleware is where you put cross-cutting concerns — logging every inbound message, resolving the app user from $bot->getMessage()->getSender(), rate limiting, analytics. Register globally in the service provider or per-handler:

$botman->middleware->heard(new LogIncomingMessage());
$botman->middleware->sending(new AppendSignature());

Keep handlers thin. The pattern that scales is handler → service/action → reply:

$botman->hears('invoice {id}', function ($bot, $id) {
    $invoice = app(InvoiceLookup::class)->find($id, $bot->getMessage()->getSender()['id']);
    $bot->reply($invoice ? "Total: {$invoice->total}" : "Not found.");
});

Rich replies — use the template classes rather than hand-rolling payloads: Button, ButtonTemplate, ListTemplate, Attachment, and $bot->replyWithImage(). $bot->typesAndWaits(1) adds a human-feeling delay.

Testing strategy: botman:tinker for the conversational logic, then each channel's own sandbox (Telegram test bot, Slack dev workspace, Facebook test page) for anything involving buttons, attachments, or webhook verification. For CI, POST a recorded driver payload to the /botman route and assert on the outgoing response — that's the only thing that exercises the real HTTP path.

Gotchas and Tips

  • This is a 2018 artifact. Last release October 2018, pinned to Laravel 5.x and PHP ≤7.4, and BotMan 2.x is effectively unmaintained. It will not boot on Laravel 9+/PHP 8. If you're on a modern Laravel, use it as a reference, then integrate botman/botman + botman/laravel into your real app and copy the controller/routes/config structure. That's the realistic "day-to-day leverage" answer.
  • CSRF will silently break the widget. 'botman' must be in VerifyCsrfToken::$except. If the widget posts fine but the bot never answers, check this first.
  • Conversation state lives in the Laravel cache, keyed per user, expiring per conversation_cache_time (minutes). With the file driver and more than one app server, users randomly fall out of conversations mid-flow. Use Redis/DB cache in production.
  • Config quirk: Studio's provider merges config/botman/*.php into the config namespace, but once you run php artisan config:cache, editing those files does nothing until you re-cache. In local dev, use config:clear.
  • Webhook secrets aren't verified for you. Facebook's verify token, Telegram's secret token, and Slack's signing secret must be validated explicitly (middleware or a check in the controller). A public /botman URL with no verification is an open relay into your bot logic.
  • Return fast. Telegram and Slack expect a 200 within a couple of seconds. Anything slow (HTTP calls to third parties, PDF generation) goes into a queued job that sends the reply proactively — which requires reconstructing the driver from stored channel/user data, so design for that before you need it.
  • Debugging: $bot->getMessage()->getPayload() and $bot->getDriver()->getName() dumped to storage/logs/laravel.log answer 90% of "why did it not match" questions. Note that botman:tinker does not simulate real driver payloads — attachments, buttons, and postbacks all look different in tinker than they do live, so never conclude a channel bug is fixed from tinker alone.
  • Extension points worth knowing: custom Driver classes, custom Middleware, conversation classes, and overriding the BotManWidget view for branding. The service provider (BotManServiceProvider) is the seam where you'd swap the singleton if you outgrow the defaults.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core