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

Botman Bundle Laravel Package

sgomez/botman-bundle

Symfony bundle that integrates the BotMan chatbot framework into Symfony applications, making it easy to configure messaging platforms, register conversation handlers, and build conversational interfaces using familiar Symfony services and configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire it up

composer require sgomez/botman-bundle

Register the bundle (Symfony Flex usually does this automatically):

// config/bundles.php
return [
    // ...
    Sgomez\BotManBundle\BotManBundle::class => ['all' => true],
];

Configure at least one driver in config/packages/botman.yaml. The Web driver is the fastest path to a first working bot because you can exercise it with the botman/web widget without provisioning a Slack or Telegram token:

botman:
    drivers:
        web: ~          # or slack: { token: '%env(SLACK_TOKEN)%' }

Define a controller that boots a conversation and calls listen():

namespace App\Controller;

use BotMan\BotMan\BotMan;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class BotController extends AbstractController
{
    #[Route('/botman', name: 'botman')]
    public function listen(BotMan $botman): Response
    {
        $botman->hears('hello', fn (BotMan $bot) => $bot->reply('Hi there!'));
        $botman->hears('.*', fn (BotMan $bot) => $bot->reply('Sorry, I did not understand.'));

        $botman->listen();

        return new Response('', Response::HTTP_NO_CONTENT);
    }
}

Where to look first

  • bin/console config:dump-reference botman – the authoritative list of driver keys for the installed version.
  • bin/console debug:container --tag=botman.driver – confirm which drivers the bundle has registered.
  • The bundle source under vendor/sgomez/botman-bundle/ – its README is thin, so the DI extension and driver compiler pass are the real documentation.
  • The upstream BotMan docs (https://botman.io) for conversation, middleware, and driver semantics.

First real use case: a hears()-based Q&A handler behind a Slack slash command or web hook. Get the Web driver working locally first, then swap in the Slack/Telegram driver by changing only the botman.drivers block — application code stays identical.

Implementation Patterns

Registering conversations — Conversations are ordinary services. Tag or autoconfigure them and hand the FQCN to $botman->hears() or a middleware:

$botman->hears('order {id}', function (BotMan $bot) {
    $bot->startConversation($bot->getContainer()->make(OrderStatusConversation::class));
});

Because the bundle bridges to BotMan's container, make sure OrderStatusConversation is a public (or autowired) service, or pass a closure that does $this->get(OrderStatusConversation::class) from the controller.

Middleware via service tags — Cross-cutting concerns (logging, user lookup, typing indicators) belong in middleware tagged botman.middleware. Autoconfigure them:

services:
    _defaults:
        autowire: true
        autoconfigure: true
        tags: ['botman.middleware']
    App\BotMan\Middleware\:
        resource: '../src/BotMan/Middleware/'

Middleware can also be attached per-driver or per-hears() at runtime with $botman->middleware->heard(...) when you need it scoped rather than global.

Controller-per-platform vs. shared controller — For multi-channel bots, prefer one controller per platform route that shares a single "bot definition" service:

final class BotRegistrar
{
    public function __construct(private BotMan $botman) {}

    public function register(): void
    {
        $this->botman->hears('help', [HelpHandler::class, 'handle']);
        // ...
    }
}

Then Slack and Telegram controllers both call $registrar->register(); $botman->listen();. This keeps route wiring platform-specific but the conversation logic centralised and unit-testable.

Async / queue integration — If the bundle's botman.async settings are enabled, long-running handlers (LLM calls, third-party lookups) should delegate to a Messenger message and reply later via the stored BotMan instance ID. Configure the timeout in botman.async.timeout to be shorter than your HTTP timeout so the driver doesn't hang the webhook.

Testing — BotMan ships a FakeDriver (or you can subclass a driver) that lets you assert on outgoing replies without hitting a real API:

$bot = $this->createMock(BotMan::class);
// or use BotMan's FakeDriver and $bot->getDriver()->messages()

For end-to-end coverage, POST to /botman with the Web driver payload shape and assert on the returned JSON.

Gotchas and Tips

listen() writes to the response, it doesn't return one. BotMan's drivers call sendResponse() (typically exit or echo) internally. In Symfony this means a controller that returns a Response after listen() may already have output buffered. For the Web driver, capture the JSON with ob_start()/ob_get_clean() if you need to manipulate headers or wrap it; for messaging platforms just return new Response() and let BotMan handle the reply.

Registering two drivers makes them both listen. listen() iterates every registered driver and dispatches to whichever matches the request. If a payload accidentally matches two drivers you get duplicated replies. Remove unused drivers from botman.drivers rather than leaving them configured with empty tokens.

Conversation cache is required for multi-turn flows. BotMan persists conversation state between requests via a cache driver. If you don't configure one (or point it at Symfony's cache pool), startConversation() silently restarts on every message. Set botman.config.conversation_cache_time and ensure the underlying cache survives between requests — the default array cache does not.

Token configuration should always be env-backed. Use %env(SLACK_TOKEN)% in botman.drivers.slack.token and never commit real tokens. Verify with bin/console debug:container --env-vars that the variable is loaded in the target environment; a missing token surfaces as a generic InvalidArgumentException from the driver, not the bundle.

Version drift with BotMan core. The bundle pins a range of botman/botman versions and the driver class names/config keys change between 2.x releases. If a config key is rejected, run composer show botman/botman and cross-check the driver's __construct and getConfig() against vendor/botman/botman/src/Drivers/<X>/<X>Driver.php.

Debugging with no visible output. When a bot "does nothing", the cause is almost always (a) no driver matching the incoming request, or (b) the hears() pattern not matching. Enable the botman.middleware LoggingMiddleware (or your own tagged middleware) and log $bot->getMessage()->getText() plus $bot->getDriver()->getName() at the top of every handler.

Stateful BotMan service. The botman service is effectively request-scoped. Don't inject it into long-lived workers (Messenger consumers, RoadRunner/Swoole) and reuse it across jobs — construct a fresh instance per message or you'll get leaking conversation state.

Extension points worth knowing:

  • Custom driver: implement BotMan\BotMan\Interfaces\DriverInterface and tag with botman.driver.
  • Custom middleware: implement BotMan\BotMan\Interfaces\MiddlewareInterface and tag botman.middleware.
  • Override the cache by defining a service implementing BotMan\BotMan\Interfaces\CacheInterface and pointing the bundle config at it.

Maintenance signal. With 12 stars, this bundle is a thin wrapper — read BotManExtension::load() before trusting a config key from a blog post, and be prepared to vendor-patch if a Symfony minor upgrade breaks service decoration. The alternative is to drop the bundle and wire BotMan manually in services.yaml, which is roughly 30 lines of DI and often the pragmatic call for long-term maintenance.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle