Extending Voodflow
This page documents the extension points available in Voodflow beyond custom nodes: overriding Eloquent models, customizing configuration, binding custom services, and integrating with the FilamentPHP panel.
Configuration Overrides
All runtime behavior can be tuned via config/voodflow.php. Publish the config if you haven't:
php artisan vendor:publish --tag=voodflow-configModel Bindings
Voodflow resolves all its Eloquent models through the Laravel service container. You can swap any model with your own subclass:
// config/voodflow.php
'models' => [
'workflow' => \App\Models\Voodflow\Workflow::class,
'execution' => \App\Models\Voodflow\Execution::class,
'execution_node' => \App\Models\Voodflow\ExecutionNode::class,
'credential' => \App\Models\Voodflow\Credential::class,
'message_layout' => \App\Models\Voodflow\MessageLayout::class,
],Your custom model must extend the original Voodflow model:
namespace App\Models\Voodflow;
use Voodflow\Models\VoodflowWorkflow as BaseWorkflow;
class Workflow extends BaseWorkflow
{
// Add custom relationships, scopes, or methods
public function tenant(): BelongsTo
{
return $this->belongsTo(Tenant::class);
}
public function scopeForTenant(Builder $query, int $tenantId): Builder
{
return $query->where('tenant_id', $tenantId);
}
}Custom Execution Pipeline
The execution pipeline runs through a series of pipeline stages. You can add custom stages via config/voodflow.php:
'pipeline' => [
'stages' => [
\Voodflow\Pipeline\ValidateWorkflow::class,
\Voodflow\Pipeline\PrepareContext::class,
\App\Voodflow\Pipeline\TenantIsolation::class, // ← custom stage
\Voodflow\Pipeline\ExecuteNodes::class,
\Voodflow\Pipeline\PersistResult::class,
\App\Voodflow\Pipeline\NotifyOnCompletion::class, // ← custom stage
],
],A pipeline stage must implement PipelineStageInterface:
namespace App\Voodflow\Pipeline;
use Voodflow\Contracts\PipelineStageInterface;
use Voodflow\Execution\ExecutionContext;
class TenantIsolation implements PipelineStageInterface
{
public function handle(ExecutionContext $context, \Closure $next): ExecutionContext
{
// Scope the context to the current tenant before execution begins
$context->setVariable('tenant_id', $context->workflow->tenant_id);
return $next($context);
}
}Credential Drivers
By default, Voodflow stores credentials encrypted in the voodflow_credentials table. You can add custom credential types by registering a resolver:
use Voodflow\Facades\Voodflow;
Voodflow::registerCredentialType('vault', function (array $fields): array {
// Resolve secrets from HashiCorp Vault at runtime
$client = app(VaultClient::class);
return $client->secret($fields['vault_path']);
});The custom type will appear in the Credential creation form alongside the built-in types.
Event Hooks
Voodflow dispatches Laravel events at key points in the execution lifecycle. Listen to them in your EventServiceProvider:
protected $listen = [
\Voodflow\Events\WorkflowExecutionStarted::class => [
\App\Listeners\TrackWorkflowMetrics::class,
],
\Voodflow\Events\WorkflowExecutionCompleted::class => [
\App\Listeners\NotifyAdminOnFailure::class,
],
\Voodflow\Events\WorkflowExecutionFailed::class => [
\App\Listeners\AlertOpsTeam::class,
],
\Voodflow\Events\NodeExecuted::class => [
\App\Listeners\AuditSensitiveNode::class,
],
];Event Payloads
| Event | Properties |
|---|---|
WorkflowExecutionStarted | $execution, $workflow, $context |
WorkflowExecutionCompleted | $execution, $duration_ms |
WorkflowExecutionFailed | $execution, $errorMessage, $errorCode |
NodeExecuted | $executionNode, $nodeType, $input, $output |
FilamentPHP Integration Points
Panel Registration
Voodflow registers its Filament resources through VoodflowPlugin. You can customize its panel configuration:
// In your PanelProvider
use Voodflow\VoodflowPlugin;
->plugins([
VoodflowPlugin::make()
->navigationGroup('Automation') // Override nav group label
->navigationSort(10) // Set nav order
->canManageWorkflows(fn () => auth()->user()->hasRole('admin'))
->canViewExecutions(fn () => auth()->user()->can('view_executions'))
])Custom Filament Resources
You can register additional Filament resources that operate on Voodflow models:
// app/Filament/Resources/WorkflowAuditResource.php
use Filament\Resources\Resource;
use App\Models\Voodflow\Workflow;
class WorkflowAuditResource extends Resource
{
protected static ?string $model = Workflow::class;
protected static ?string $navigationGroup = 'Automation';
// Build your custom table/form...
}Register it in your panel provider as any other Filament resource.
Overriding Voodflow Pages
To override a built-in Voodflow Filament page (e.g. the execution list), extend the original class and re-register it:
namespace App\Filament\Voodflow;
use Voodflow\Filament\Resources\ExecutionResource\Pages\ListExecutions as BaseListExecutions;
class ListExecutions extends BaseListExecutions
{
protected function getTableQuery(): Builder
{
// Scope to current tenant
return parent::getTableQuery()->where('tenant_id', auth()->user()->tenant_id);
}
}Then tell Voodflow to use your page via VoodflowPlugin::make()->executionListPage(ListExecutions::class).
Workflow Middleware
Apply global middleware to all workflow executions, similar to HTTP middleware:
// config/voodflow.php
'execution_middleware' => [
\App\Voodflow\Middleware\EnsureTenantActive::class,
\App\Voodflow\Middleware\RateLimitExecutions::class,
],Middleware classes implement WorkflowMiddlewareInterface:
class RateLimitExecutions implements WorkflowMiddlewareInterface
{
public function handle(VoodflowExecution $execution, \Closure $next): void
{
$key = "workflow_executions:{$execution->workflow_id}";
if (RateLimiter::tooManyAttempts($key, 100)) {
throw new ExecutionThrottledException('Too many executions for this workflow.');
}
RateLimiter::hit($key, 60);
$next($execution);
}
}Service Container Bindings
Swap Voodflow's internal services by binding alternatives in your service provider:
// Override the template engine
$this->app->bind(
\Voodflow\Contracts\TemplateEngineInterface::class,
\App\Voodflow\TwigTemplateEngine::class
);
// Override the credential encryption driver
$this->app->bind(
\Voodflow\Contracts\CredentialEncryptorInterface::class,
\App\Voodflow\VaultCredentialEncryptor::class
);Notes
- Always extend, never modify, core Voodflow classes — this ensures smooth upgrades
- After modifying
config/voodflow.php, clear the config cache:php artisan config:clear - Custom pipeline stages, event listeners, and middleware are testable in isolation using standard PHPUnit techniques
- Check the
CHANGELOG.mdin the Voodflow package before each upgrade for breaking changes to extension points