Skip to content

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:

bash
php artisan vendor:publish --tag=voodflow-config

Model Bindings

Voodflow resolves all its Eloquent models through the Laravel service container. You can swap any model with your own subclass:

php
// 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:

php
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:

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:

php
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:

php
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:

php
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

EventProperties
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:

php
// 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:

php
// 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:

php
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:

php
// config/voodflow.php
'execution_middleware' => [
    \App\Voodflow\Middleware\EnsureTenantActive::class,
    \App\Voodflow\Middleware\RateLimitExecutions::class,
],

Middleware classes implement WorkflowMiddlewareInterface:

php
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:

php
// 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.md in the Voodflow package before each upgrade for breaking changes to extension points

Proprietary software — source-available. All rights reserved.