Open source
Workflows for Laravel
composer require roundly-consulting/workflows-for-laravelOverview
Durable, versioned workflows for Laravel. A workflow is a JSON graph of triggers, conditions, approvals, waits, delays and escalations that your users edit in a builder — or you write in PHP — and the engine runs each published version exactly as it was published, step by step on your queues. Waits are stored as rows and survive restarts and deploys, business time follows a weekday or opening-hours calendar, retries reuse one idempotency key per step visit, and dry runs show every path without writing anything. MIT-licensed, built on Laravel’s queue, scheduler and database plus Roundly’s crypto, enums and package-toolkit; approvals, lifecycle, notifications, opening hours, forms and teams plug in as optional bridges.
What you get
Workflows stored as versioned JSON
A workflow is a JSON graph of nodes and edges with a published JSON Schema. Edits go into a draft; publishing freezes it, and every run finishes on the version it started on.
Four ways to start
Manual starts with validated input or a form, app events and mapped Laravel events, cron schedules (also once per matching subject) and an opt-in signed webhook route.
Durable waits and business time
Delays, waits for events or conditions and timeouts are stored as rows and woken by the scheduler. Business days and hours follow a weekday or opening-hours calendar, DST included.
Escalations and retries
A waiting step can reassign, notify or start another workflow, level by level. Failed steps retry with backoff and a stable idempotency key, and once() makes database effects exactly-once.
Declarative conditions, no code in graphs
Conditions are JSON clauses over registered fields only — no expression language, no regex, nothing a workflow author could execute.
Dry runs, history and a run overlay
Walk a workflow without writing anything — one path or every branch — read each run’s step log with its resolved input, and count waiting runs per node.
Facade, DI or actions — and a builder in PHP
One Workflows facade, an injectable manager or single-purpose actions, a fluent graph builder, a record-only fake, step fakes and Pest expectations.
Documentation
Use cases
Where the package fits — approvals with deadlines, reviews in business days, SLA reminders, onboarding and processes your customers configure themselves.
Installation
Install via Composer, publish config and the eight migrations, settle key types, schedule workflows:wake, register a subject type and start a workflow.
Configuration
Every key of config/workflows.php with its env variable, default and range — key types, queue, limits, retries, authorization, webhooks, pruning.
Concepts
Definitions, versions, instances, nodes, step runs, visits, waits, escalations, signals, parties, actors and owners — and the life of one instance.
Subjects, owners and parties
Register subject types with typed fields, resolve owners, use the HasWorkflows trait, and address approvers and recipients as party references.
The Workflows facade
Tour the Workflows facade — start, emit, for($subject), the definition handle, versions, instances, registries, the graph builder, wake and prune.
DI and actions
Skip the facade: inject WorkflowsManager or call a single-purpose action — every host-facing action with its execute() signature and facade path.
Graph schema
The roundly.workflows.graph/v1 document — rules, value references, durations, parties — and the full graph, template and shared-definition JSON Schemas.
Graph builder in PHP
Workflows::graph() writes the same JSON graph in PHP — every step helper, modifier, edge method and value helper (When, Ref, Party, After, Trigger, Stage).
Built-in steps
Every built-in step type — trigger, condition, branch, set_field, transition, delay, wait, loop, start_workflow, end, approval, notify, webhook.
Conditions
Declarative JSON conditions — all, any, not and field clauses, operators per field type, null, decimal and date semantics, and their publish checks.
Triggers
Start workflows manually with validated input or a form, from app and mapped Laravel events, on a cron schedule, or from a signed inbound webhook.
Definitions and versions
Create, edit, publish, retire and restore definitions, keep workflows as files with workflows:sync, diff versions and copy templates between owners.
Step handler contract
Write your own step type: registration, the StepType class, ConfigSchema, StepContext, StepResult and WaitSpec, idempotency, failures and cancel hooks.
Business time and escalations
Weekday and opening-hours calendars, business-day and business-hour arithmetic across DST, and escalation levels that reassign, notify or start workflows.
The engine
How steps run: jobs and leases, two transactions per step, waits and workflows:wake, retries, idempotency, limits, authorization and owner context.
Publish validation
Validate drafts and graphs before publishing — the ValidationReport, the eleven passes and every machine-readable validation code with its meaning.
Dry runs and history
Walk a workflow without writing anything — one path or every branch — then read instance history, the step log with resolved inputs and the run overlay.
Building a visual editor
What a visual builder calls — schemas, step catalogue, field pickers, live validation, diffs, dry runs and the overlay — and the JSON resources to render.
Bridges to other packages
Optional bridges — approval steps, lifecycle transitions and events, notify steps, opening-hours calendars, form triggers, teams and signed webhooks.
Recipes
Five complete workflow files — purchase approval, the rework loop, onboarding, an SLA reminder, a nightly schedule — and a test that drives them.
Database
The eight tables — every column, index and foreign key, how key types size the morph columns, and what workflows:prune deletes after retention.
Events
Every event the package dispatches after commit — instance, step, escalation, publish, draft and retire events — with their payloads.
Exceptions
Every exception with its errorCode() and HTTP status — unknown definitions, conflicts, invalid graphs and inputs, authorization and registration errors.
Artisan commands
workflows:install, wake, prune, catalogue, validate, sync, export, list, show, retry, cancel, doctor and make:workflow-step — what each does.
Troubleshooting
Every workflows:doctor finding with its fix, and every failure code — when it is written and whether a manual retry can help.
Testing
Workflows::fake() records without running — assertion pairs, recorded operations, passthrough, step fakes, InteractsWithWorkflows and Pest expectations.
Requirements
PHP 8.4+ and Laravel 13, MySQL 8 or PostgreSQL, a queue worker with pcntl, the scheduler running workflows:wake and three Roundly packages.
Show your open-source love
This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.
More ways to support, including cryptoBy donating, you agree to our donation terms.
Want this built into your product?
We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.