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

Filament Workflow Builder Laravel Package

briefley/filament-workflow-builder

A visual workflow builder for Filament panels. Design approval and automation flows with a drag-and-drop canvas, define states, transitions, conditions, and actions, then attach workflows to Eloquent models and manage runs from the admin UI.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish in one pass, then treat the migrations as the source of truth for the domain model before you touch the UI:

composer require briefley/filament-workflow-builder
php artisan vendor:publish --tag="filament-workflow-builder-migrations"
php artisan vendor:publish --tag="filament-workflow-builder-config"
php artisan migrate

Register the plugin on the panel(s) that should own authoring (usually an admin panel, not a customer-facing one):

use Briefley\FilamentWorkflowBuilder\FilamentWorkflowBuilderPlugin;

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugins([
            FilamentWorkflowBuilderPlugin::make(),
        ]);
}

Where to look first, in this order:

  1. config/filament-workflow-builder.php — queue connection, executor map, scheduling options, table names. Nearly every "why isn't it running" question resolves here.
  2. The published migrations — the workflow/step/run tables tell you what states exist (pending, running, completed, failed, skipped) and whether runs are persisted per-step or per-workflow. That shapes your reporting and retry strategy.
  3. src/ for the step executor contract and any events dispatched around transitions. Wire your own logging to those events rather than polling tables.
  4. The Filament resource(s) — check navigation group, tenancy, and policy hooks so authoring lands in the right place for your app.

First use case: pick something with a low ceiling but real value — an approval chain (order refund over threshold → manager → finance) or a content pipeline (draft → review → publish). Avoid starting with anything that mutates money or sends irreversible external calls; you want to learn the run/retry semantics on something you can safely replay.

Implementation Patterns

Executors are the main extension surface. Each step type maps to a class implementing the executor contract; the class receives the step's configured payload plus the run context and returns success/failure. Register them in config, not by convention, so you can swap implementations per environment:

// config/filament-workflow-builder.php
'executors' => [
    'send_email'      => App\Workflows\Executors\SendEmailExecutor::class,
    'create_invoice'  => App\Workflows\Executors\CreateInvoiceExecutor::class,
    'http_webhook'    => App\Workflows\Executors\HttpWebhookExecutor::class,
],

Keep executors thin and idempotent. The executor should do one thing and hand off anything heavy to its own job; the workflow engine is the orchestrator, not the worker.

Triggering from application code. Don't rely on humans clicking "run" in the panel. Seed workflows, then start runs from domain events:

// app/Observers/OrderObserver.php
public function updated(Order $order): void
{
    if ($order->wasChanged('status') && $order->status === 'paid') {
        Workflow::where('slug', 'post-purchase')->first()
            ?->startFor($order);
    }
}

If the package exposes a facade or a start() on the workflow model, wrap it in a small WorkflowRunner service of your own. That gives you one place to add tenancy scoping, context payloads, and telemetry — and one place to patch if the API shifts.

Human-in-the-loop steps. For approval-style steps, model them as a step that pauses the run and writes a task/notification, then resumes from a Filament action or a signed route. Persist the approver's user ID in the step record so your audit trail survives model deletions. This is the pattern that makes the package worth using over hand-rolled state machines.

Queued and scheduled execution. Point the package at a dedicated queue (e.g. workflows) in config so long step chains never starve your default queue. For scheduled workflows, confirm whether the package registers its own scheduler entry or expects you to add one to routes/console.php / Kernel — the latter is common and easy to miss:

Schedule::command('workflow:run-due')->everyMinute()->withoutOverlapping();

Testing. Fake the queue, assert on run/step rows, and unit-test executors in isolation:

Queue::fake();

$run = $workflow->startFor($order);

Queue::assertPushed(SendEmailJob::class);

$this->assertDatabaseHas('workflow_runs', [
    'id' => $run->id,
    'status' => 'pending',
]);

Treat the executor contract as the seam: your executor tests need no Filament, no panel, no DB beyond a fixture.

Multi-tenancy. If the admin panel is tenant-scoped, verify the workflow and run resources respect Filament's ->tenant() scoping. If they don't, add a global scope on the models via a service provider rather than forking the resource.

Gotchas and Tips

  • Unknown repo, small install base. The listing has 10 stars and no confirmed public repository. Pin the exact version in composer.json, commit the published config and migrations to your repo, and assume you may need to read vendor/ to answer questions. Budget for potentially maintaining a fork.
  • Serialization of step payloads. Anything configured in the UI step editor is stored as JSON. Don't push closures, models, or enum instances into step config — store IDs and scalars, resolve on execution. Half of all "step fails only in production" bugs are unserializable config that worked when authored in-process.
  • Idempotency under retries. Queued steps will re-run on failure unless the package tracks attempt counts per step. Make every executor safe to call twice: upsert instead of insert, external calls with an idempotency key, emails guarded by a "already sent" flag on the run.
  • Transactions and queues don't mix. If you start a workflow inside a DB transaction that later rolls back, the queued step may already be dispatched against a row that no longer exists. Dispatch on DB::afterCommit() or start the run from an event listener that fires post-commit.
  • Stale run state. Long approval gaps mean the run row can be hours or days old. Snapshot the data the step needs (amounts, recipients) into the run context at start time rather than re-reading live models mid-flight — otherwise an approver sees one number and finance sees another.
  • Timezone drift on scheduling. Scheduled workflows typically evaluate against config('app.timezone'). If your business hours are in a different zone, set it explicitly and write a test that asserts a run fires at the expected local time.
  • Debugging playbook: check the queue connection in config first, then failed jobs, then the run and step rows in that order. Add a failed() handler that writes the exception plus the step payload to your log channel — the payload is what you'll actually need. Enable Horizon or a similar dashboard before go-live; debugging a chain of five queued steps from logs alone is miserable.
  • Extension points worth using: custom executor classes (obviously), Filament action buttons on the run resource for manual retry/cancel, and the package's transition events for metrics. Avoid overriding the resources directly — subclass or extend via plugin configuration so a version bump doesn't break your panel.
  • Filament version coupling. Filament has breaking changes between majors and this package tracks it. Check the composer constraint for filament/filament before upgrading your panel; a Filament major bump will likely require a package major bump too.
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