ashrafic/filament-automation-bridge
A Laravel/Filament bridge for connecting automation workflows to your admin panel. Trigger webhooks, manage integrations, and automate tasks directly from Filament resources with a simple, configurable setup.
This package (filament-automation-bridge, formerly filament-webhook-bridge) is a Filament plugin that wires Eloquent models, schedules, and manual actions into outbound webhooks targeting n8n and Make.com. It's an outbound-automation bridge — not an inbound webhook receiver.
Minimal setup:
composer require <vendor>/filament-automation-bridge
php artisan automation-bridge:install # publishes config, migrations, and registers the plugin
php artisan migrate
Register the plugin on your Filament panel provider:
->plugin(\Vendor\AutomationBridge\AutomationBridgePlugin::make())
Where to look first:
config/automation-bridge.php — destination credentials, auth mode, HMAC secret, SSRF allowlist, queue connection, rate-limit windows..php.stub files (Spatie-style) so you control what runs and when.First use case — send a Slack-style message via n8n whenever a Subscription is created:
Subscription → Event: created → map fields.HasWebhookTriggers trait, or let the WebhookEventSubscriber wildcard listener pick it up automatically.Run php artisan automation-bridge:test (if you prefer the CLI) or the Filament Test Connection action to confirm the round-trip.
Attaching triggers to models. Add HasWebhookTriggers to the model and declare trigger definitions. The package's WebhookEventSubscriber listens on Eloquent wildcards, so a single subscriber covers every model — you configure which triggers fire where in the DB, not in code.
class Subscription extends Model
{
use HasWebhookTriggers;
}
Trigger types you'll actually use day-to-day:
created/updated/deleted.status: pending → active).DateCondition.ManualTriggerAction.Manual dispatch from a resource page. Drop ManualTriggerAction into a page's actions array — it's already registered in the plugin's action registry, so you don't need to construct it.
Field mapping. The custom form components (field mapper, conditions builder, payload preview, test connection) are the primary authoring surface. You select a model field, apply a formatter (there's a PayloadFormatter contract plus destination-specific formatters registered in the service provider), and preview the payload live. If you need a custom format, implement PayloadFormatter and register it via the plugin's formatter registry — don't fork the built-ins.
Conditions. ConditionEvaluator supports AND/OR groups and a registry of operators. For anything domain-specific (e.g. isBusinessDay), implement the ConditionOperator contract and register it. The condition tree is stored on the trigger and evaluated before dispatch, so misconfigured operators fail silently at the delivery layer — test with a real payload in the preview.
Templates. Built-in templates were removed in this release; only user-created ones remain. Use Save as Template on an existing trigger to capture auth mode, headers, conditions, and field mapping. Create from Template opens a prefilled form. TemplateManager is the underlying service if you want to seed templates programmatically during deploy.
Historical sync. For backfilling existing records into a trigger, use HistoricalSyncService. It batches with progress tracking and runs through a queue job — dispatch it from an artisan command or a custom action, not from a request.
Delivery and reliability.
DeliveryService is the orchestrator; it handles dispatch, retry, and logging.RateLimiterService throttles per-destination — set limits per trigger, not globally.SecurityService handles HMAC signing and SSRF protection.Scheduled command pattern. Register the package's process command in app/Console/Kernel.php (or the routes/console.php equivalent), then author Schedule triggers with cron expressions. Use automation-bridge:prune on the same schedule to trim delivery logs.
Caching. ModelDiscoveryService and FieldSchemaAnalyzer cache discovered models and field schemas. Clear with the package's cache command after adding a model or relationship — otherwise your field mapper won't see new fields.
Migrations are .php.stub files. The package uses Spatie-style publishing. If you run php artisan migrate before running the install/publish command, nothing happens. Always vendor:publish the migration group first. If you have an existing install from a pre-1.0 version, the migration filenames changed — you'll need to reconcile your migrations table manually or drop and re-run on a fresh environment.
Fixed migration timestamps. This release pins migration timestamps to the package release date (2026-06-03) to keep ordering deterministic. Consequence: migrations run before any of your app's migrations from after that date. If your automation trigger migration references a users table or a foreign key created later, it will fail. Add explicit ->after() or split your reference into a second migration.
Optional event column. The deliveries.event column is now nullable. Any custom reporting you built that filters whereNotNull('event') will now exclude manual and schedule deliveries, which have no event class.
automation_triggers missing during db:seed. The package now guards against this, but if you seed triggers in your own seeders, run them after migrations in a fresh environment. db:seed alone on a fresh DB before migrate will still fail.
Routes are prefixed automation-bridge. All webhook/retry/test routes live under /automation-bridge/*. If you're fronting this behind a proxy or a custom middleware group, update your path allowlist. Also check for collisions if you had a manual automation-bridge prefix.
Filament v5 required. The plugin now uses Filament\Actions\Action (not Tables\Actions\Action), and column APIs (TextColumn, ToggleColumn, toolbarActions) are v5 idioms. Running against Filament v4 will break the resource pages. If you've overridden any pages via Resource::getPages(), mirror the mount/fillForm + Laravel redirect() pattern for Create from Template — the TableAction version silently failed to redirect.
SSRF protection is opinionated. SecurityService blocks private IPs and non-allowlisted hosts by default. If your n8n instance runs on http://localhost:5678 or http://10.x.x.x, every dispatch will fail with a validation exception. Add the host to the config allowlist — don't disable the check.
Auth mode changes regenerate the secret placeholder. The dynamic helper text in Settings reflects the current mode; if you switch from Basic to Bearer, re-enter the token — the field is cleared to prevent credential leakage between modes. Persisted values are encrypted; rotating the app APP_KEY will make existing credentials unreadable, so re-key after any re-encryption.
Translation files are per-section with flat dot notation. If you extended or overrode the old single-file translation, it's now split across lang/{locale}/automation-bridge/*.php with keys like triggers.form.model.label. Override via lang/vendor/automation-bridge/... and re-publish after upgrading — old overrides will appear to do nothing.
Hardcoded nav group. Triggers, Templates, and Delivery Log are pinned to the "Automation Bridge" group with a fixed sort order. If you need them elsewhere, override the page's getNavigationGroup() on your own subclass — the plugin doesn't expose a config toggle for this.
Queue is mandatory. Delivery jobs and historical sync both dispatch on the queue. If your queue worker isn't running, "Test Connection" succeeds (synchronous) but real deliveries pile up. Check the health widget first when triggers "don't fire" — it surfaces queue backlog before it surfaces errors.
Debouncing edits. ModelEvent and StatusChanged triggers fire on saved. Bulk updates via Model::where(...)->update(...) do not fire model events — use the Manual trigger or HistoricalSyncService for bulk backfills.
Extension points to prefer. PayloadFormatter and ConditionOperator contracts, the formatter registry on the service provider, and TriggerManager (register custom trigger types here rather than patching the manager). Avoid extending DeliveryService directly — it is not designed as a template method and its internals changed across the 1.0 → 1.1 line.
Debugging a failed delivery. The Delivery Log page merges model + model ID into a single column and shows request/response JSON in slideovers with copy buttons. Look at security_error → your allowlist or HMAC secret; 4xx → destination auth mode mismatch; timeout → queue worker or destination unreachable. Retry replays the stored payload, not the current model state — if you fixed field mapping, re-trigger rather than retry.
How can I help you explore Laravel packages today?