Skip to main content
Version: 2.0

Events

Lifecycle events are dispatched at key stages of workflow and activity execution to notify your application of progress, completion, or failures. These are standard Laravel events — register listeners in your EventServiceProvider or with Event::listen().

All V2 lifecycle events are dispatched after the durable state is committed to the database. This means listeners only observe events backed by committed truth — if a transaction rolls back, no event is dispatched.

Event Identity

Every V2 event carries durable identity fields:

FieldDescription
instanceIdThe workflow instance ID (stable across continue-as-new).
runIdThe specific execution run ID.
workflowTypeThe durable type key registered via #[Type('...')].
workflowClassThe PHP class name of the workflow.
committedAtISO 8601 timestamp of when the durable record was committed (wall-clock commit time).

Activity events additionally include:

FieldDescription
activityExecutionIdThe durable activity execution ID.
activityTypeThe durable type key of the activity.
activityClassThe PHP class name of the activity.
sequenceThe position of the activity within the workflow execution.
attemptNumberThe attempt number (starts at 1).

Workflow Events

WorkflowStarted

Dispatched when a workflow start is durably committed — meaning the first run has been created and the WorkflowStarted history event has been recorded.

use Workflow\V2\Events\WorkflowStarted;

Event::listen(WorkflowStarted::class, function (WorkflowStarted $event) {
Log::info('Workflow started', [
'instance_id' => $event->instanceId,
'run_id' => $event->runId,
'type' => $event->workflowType,
]);
});

This event also fires when a new run begins via continue-as-new.

WorkflowCompleted

Dispatched when a workflow run completes successfully.

use Workflow\V2\Events\WorkflowCompleted;

Event::listen(WorkflowCompleted::class, function (WorkflowCompleted $event) {
Log::info('Workflow completed', [
'instance_id' => $event->instanceId,
'run_id' => $event->runId,
]);
});

WorkflowFailed

Dispatched when a workflow run fails terminally.

Additional fields:

  • exceptionClass: The PHP exception class name.
  • message: The exception message.
use Workflow\V2\Events\WorkflowFailed;

Event::listen(WorkflowFailed::class, function (WorkflowFailed $event) {
Log::error('Workflow failed', [
'instance_id' => $event->instanceId,
'exception' => $event->exceptionClass,
'message' => $event->message,
]);
});

Activity Events

ActivityStarted

Dispatched when an activity task is claimed and execution begins.

use Workflow\V2\Events\ActivityStarted;

Event::listen(ActivityStarted::class, function (ActivityStarted $event) {
Log::info('Activity started', [
'activity' => $event->activityType,
'sequence' => $event->sequence,
'attempt' => $event->attemptNumber,
]);
});

ActivityCompleted

Dispatched when an activity completes successfully.

use Workflow\V2\Events\ActivityCompleted;

Event::listen(ActivityCompleted::class, function (ActivityCompleted $event) {
Log::info('Activity completed', [
'activity' => $event->activityType,
'execution_id' => $event->activityExecutionId,
]);
});

ActivityFailed

Dispatched when an activity fails terminally (all retries exhausted or non-retryable exception). Retryable failures that will be retried do not trigger this event.

Additional fields:

  • exceptionClass: The PHP exception class name.
  • message: The exception message.
use Workflow\V2\Events\ActivityFailed;

Event::listen(ActivityFailed::class, function (ActivityFailed $event) {
Log::error('Activity failed', [
'activity' => $event->activityType,
'exception' => $event->exceptionClass,
'message' => $event->message,
]);
});

Failure Events

FailureRecorded

Dispatched whenever a durable failure record is committed — for both workflow and activity terminal failures. This is the single hook for error-reporting integrations like Sentry or Bugsnag.

FieldDescription
failureIdThe durable failure record ID.
sourceKind"workflow_run" or "activity_execution".
sourceIdThe ID of the source (run ID or activity execution ID).
exceptionClassThe PHP exception class name.
messageThe exception message.
use Workflow\V2\Events\FailureRecorded;

Event::listen(FailureRecorded::class, function (FailureRecorded $event) {
// Report to Sentry, Bugsnag, etc.
report(new \RuntimeException(
"[{$event->sourceKind}] {$event->exceptionClass}: {$event->message}"
));
});

Timestamp Semantics

The committedAt field on all events represents commit time — the wall-clock time at which the durable record (history event or failure record) was written to the database. This is distinct from:

  • Workflow virtual time: The logical time inside the workflow execution (used by timers).
  • Attempt time: When a specific activity attempt started or finished.
  • Resume latency: How long after a timer was due the workflow actually resumed.

Commit time is the most useful timestamp for external integrations because it reflects when the state became durable and observable.

Lifecycle

A typical successful workflow lifecycle:

Workflow\V2\Events\WorkflowStarted
Workflow\V2\Events\ActivityStarted
Workflow\V2\Events\ActivityCompleted
Workflow\V2\Events\WorkflowCompleted

A workflow lifecycle with a terminal activity failure:

Workflow\V2\Events\WorkflowStarted
Workflow\V2\Events\ActivityStarted
Workflow\V2\Events\ActivityFailed
Workflow\V2\Events\FailureRecorded (source: activity_execution)
Workflow\V2\Events\WorkflowFailed
Workflow\V2\Events\FailureRecorded (source: workflow_run)

Event Namespace

V2 events live in the Workflow\V2\Events namespace. If you are upgrading an existing app, see Migration for the V1 compatibility event mapping.