Skip to main content

Running workflows

The Workflow facade

use Qanna\WorkflowEngine\Facades\Workflow;

// Synchronous — runs now, returns a WorkflowExecution
$execution = Workflow::run(
workflowId: 'send-welcome-email',
payload: ['email' => 'ada@example.com'],
triggeredBy: 'signup', // free-text label, recorded on the execution
);

// Queued — returns void; a worker runs it
Workflow::dispatch('send-welcome-email', ['email' => 'ada@example.com']);

// Resume a suspended execution
Workflow::resume($executionId, ['approved' => true]);

run() also accepts ExecutionMode $mode (default Sync) and an optional ?string $executionId. It returns null if the trigger declined to run.

The facade proxies ExecutionManagerContract — inject that instead of the facade if you prefer:

public function __construct(
private readonly \Qanna\WorkflowEngine\Engine\Contracts\ExecutionManagerContract $workflows,
) {}

From the command line

php artisan workflow:run send-welcome-email
php artisan workflow:run send-welcome-email --payload='{"email":"ada@example.com"}'

Without --payload, and when the trigger accepts input, the command prompts interactively for the payload and seeds the prompts from the trigger's saved config. It prints the execution timeline and exits non-zero if the workflow didn't succeed. See the CLI reference.

Via webhook

A workflow with a Webhook trigger is reachable at a generated POST URL under webhooks/. The request body becomes the payload; the response is { "execution_id": "...", "status": "..." }. Set a secret on the trigger to require an X-Webhook-Secret header.

Via schedule

A workflow with a Schedule trigger runs itself whenever its cron expression matches, as long as Laravel's scheduler is running.

Via model events

A workflow with a Model event trigger runs whenever the configured Eloquent events fire — queued by default, or inline in sync mode.

Handling the result

$execution = Workflow::run('flag-large-orders', $payload);

match ($execution?->status) {
ExecutionStatus::Succeeded => /* $execution->output */,
ExecutionStatus::Failed => report($execution->errorMessage),
ExecutionStatus::Cancelled => /* stopped intentionally */,
ExecutionStatus::Suspended => /* waiting — will resume later */,
null => /* trigger declined */,
};

See Error handling for what fails a workflow and how to observe it.