Files
vercel__workflow/packages/core/CHANGELOG.md
github-actions[bot] e6af70b9d9 Version Packages (beta) (#3318)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-06 09:02:00 -07:00

165 KiB

@workflow/core

5.0.0-beta.40

Minor Changes

  • #3347 8d47928 Thanks @karthikscale3! - Add a bulk run cancellation primitive. @workflow/world defines the BulkCancelWorkflowRuns* contract and an optional runs.cancelMany; @workflow/world-vercel implements it via a single POST /v4/runs/cancel; @workflow/core adds a cancelRuns helper that uses cancelMany when available and falls back to bounded-concurrency single-run cancellation.

  • #3048 f8f6e17 Thanks @TooTallNate! - Add an experimental QuickJS WASM VM engine for workflow execution, opt-in via WORKFLOW_VM=quickjs (or per-run executionContext.workflowVm). The engine performs the same full event replay as the default node:vm engine but runs workflow code in a QuickJS VM compiled to WebAssembly, enabling platforms without node:vm support and laying the groundwork for VM-memory snapshotting.

  • #3046 5d591d2 Thanks @NathanColosimo! - Retain workflow execution across inline steps within one invocation; WORKFLOW_RETAINED_VM=0 disables retention. Boundaries whose step arguments are not primitive values fall back to ordinary replay.

  • #3047 89ede82 Thanks @NathanColosimo! - Retained workflow VMs now keep the fast path when step arguments are plain data or standard built-ins (Map, Set, Date, typed arrays, URL, Headers, …), not just primitives. A boundary falls back to a normal replay only when serializing its arguments ran code the workflow controls — a getter, a proxy, a custom serializer — or computed an Error's stack trace.

Patch Changes

  • #2960 79e4c04 Thanks @alangenfeld! - Re-route a queue delivery that reaches a deployment other than the one its run is pinned to, retry transient publishing failures through normal queue redelivery, and fail the run with the new DEPLOYMENT_MISMATCH error code once the recovery budget is spent.

  • #3316 e084e08 Thanks @karthikscale3! - Allow configuring the polling interval used by Run.returnValue with WORKFLOW_RETURN_VALUE_POLL_INTERVAL_MS.

  • #3345 9c1b3c8 Thanks @karthikscale3! - Initialize lazy hook resume replay from the hook_received write via the new advisory preloadEvents param, skipping run_started and the initial events.list; safe fallback otherwise.

  • #3301 cb77725 Thanks @VaguelySerious! - Add env option to split correlation ID derivation into per-entity-type sequential ULIDs, instead of sharing one derivation source

  • #3332 939ffb4 Thanks @NathanColosimo! - Reject unsupported Hook retention synchronously inside QuickJS workflows.

  • #3319 27a3f15 Thanks @NathanColosimo! - Preserve Hook minimum-retention deadlines in QuickJS workflows.

  • #3048 f8f6e17 Thanks @TooTallNate! - QuickJS engine performance: cache compiled WebAssembly modules process-wide, and execute steps inline in a live-VM continuation loop (no queue round-trip per step, cheap events fed before step bodies, delayed wait-continuation dispatch for racing timers).

  • #3301 cb77725 Thanks @VaguelySerious! - Fix stream IDs minted while serializing a step's arguments latching the host wall clock into a run's ID sequence, which gave every entity created afterwards a different correlation ID on each replay

  • #3360 72efc90 Thanks @elliotdauber! - Derive inline-execution duration limits from World.getRuntimeDeadline() (implemented on Vercel World via @vercel/functions).

  • Updated dependencies [8d47928, 1222aab, 2eddf74, de1905f, 79e4c04, 9c1b3c8, e6f1b6f, 72efc90]:

    • @workflow/world@5.0.0-beta.25
    • @workflow/world-vercel@5.0.0-beta.36
    • @workflow/world-local@5.0.0-beta.34
    • @workflow/errors@5.0.0-beta.16

5.0.0-beta.39

Minor Changes

  • #3186 4a9d26b Thanks @alangenfeld! - Record the compute instance that ran each step attempt: CreateEventParams.computeInstanceId is stamped on step_started writes, forwarded in the world-vercel v4 frame meta alongside vercelId, read back on AnalyticsEvent / AnalyticsStep, and surfaced as "Compute Instance ID" in the observability attribute panel.

  • #3244 ee944d2 Thanks @pranaygp! - Stamp the creating client's environment into the queue message's runInput, and refuse a queue delivery whose run was created in a different environment than the consuming deployment runs in, so one run ID can no longer be forked into two environments.

  • #3145 1471f25 Thanks @VaguelySerious! - Strengthen the event-creation precondition guard: replay-context writes now also send the number of loaded events, so a snapshot that is missing an event is rejected instead of committing a divergent event log, and a rejection restarts the replay in-process (consuming the events a world may attach to the rejection) rather than re-committing the rejected payload or re-invoking over the queue. @workflow/world-local and @workflow/world-postgres do not implement the check.

  • #2989 9cc11f5 Thanks @alangenfeld! - Emit a faas.instance OTEL span attribute (a synthesized per-warm-instance id) on the flow and step route spans, so traces can distinguish which compute instance handled each request.

  • #3230 31f92df Thanks @karthikscale3! - Lazy hook resumption: on a fast path, resumeHook() writes the hook_received event and dispatches the workflow queue message concurrently instead of sequentially, cutting a round trip off resume latency. A (runId, resumeId) dedup constraint keeps the two writers converging on exactly one event; the runtime falls back to the sequential path when dedup support is unavailable or when WORKFLOW_DISABLE_LAZY_HOOK_RESUME=1. resumeHook() resolves to a ResumedHook (a Hook plus an optional resilientResume: true flag, set only when the direct write failed transiently and the resume was recovered via the queue consumer's re-ensure) — preserving the contract introduced alongside the resilient-resume work.

  • #1834 438eaa6 Thanks @TooTallNate! - Make resumeHook() resilient to transient hook_received event write failures (429/5xx) by carrying the payload on the queue message for the runtime to materialize. Returned Hook gets a new resilientResume: true flag when this fallback path is taken.

Patch Changes

  • #3288 679dfa9 Thanks @NathanColosimo! - Simplify hardened serialization: intrinsic captures assert at import instead of degrading per use, URLSearchParams now serializes natively on Node 18, and bound-function getters are reported as guest code (previously a getter defined via fn.bind() executed with an empty report).

  • #3257 b732e91 Thanks @TooTallNate! - Serializing values built inside the node:vm workflow VM no longer executes workflow code, using engine brand checks and host intrinsics captured at boot.

  • #3273 4174a6e Thanks @VaguelySerious! - Treat an empty VERCEL_URL as not running on Vercel, so a .env.local left behind by vercel env pull no longer makes local runs fail with Invalid URL

  • #3208 4017597 Thanks @alangenfeld! - Report replay-divergence counts on event writes that recover or exhaust replay retries.

  • Updated dependencies [4a9d26b, 1471f25, c93f6f7, 31f92df, 4017597, 438eaa6, ee944d2, 2677653, aa78a7e, f05f642, ee944d2]:

    • @workflow/world@5.0.0-beta.24
    • @workflow/world-vercel@5.0.0-beta.35
    • @workflow/errors@5.0.0-beta.15
    • @workflow/world-local@5.0.0-beta.33

5.0.0-beta.38

Patch Changes

  • #3198 b92c23c Thanks @TooTallNate! - Don't observe idle — and raise a WorkflowSuspension — while a delivery that is committed to reaching the workflow is still parked between its serial queue slot and its detached resolve(). A run with an outstanding sleep() replaying a batch of parallel step results could suspend inside that gap with none of the batch's follow-up work queued, going dormant until an unrelated timer fired.

  • #3142 a09d001 Thanks @VaguelySerious! - Revert the static workflow world target injection: the world package is again resolved at runtime from WORKFLOW_TARGET_WORLD instead of being aliased into host bundles at build time.

  • Updated dependencies [34975f6, a09d001]:

    • @workflow/world-vercel@5.0.0-beta.34
    • @workflow/utils@5.0.0-beta.8
    • @workflow/world-local@5.0.0-beta.32
    • @workflow/errors@5.0.0-beta.14

5.0.0-beta.37

Major Changes

  • #3128 7959acc Thanks @NathanColosimo! - BREAKING CHANGE: Remove the deprecated experimental_setAttributes and ExperimentalSetAttributesOptions aliases; use setAttributes and SetAttributesOptions instead.

  • #3112 4ada27d Thanks @NathanColosimo! - Remove deprecated world-specific factory aliases in favor of createWorld.

  • #3061 62d570e Thanks @NathanColosimo! - Remove the retired step route runtime and make queue health checks target the combined flow handler.

  • #3045 d813fb8 Thanks @NathanColosimo! - Deterministic sandbox hardening: crypto.subtle.digest in workflow functions now computes synchronously via node:crypto (byte-identical values, deterministic timing under replay); Atomics.waitAsync, async WebAssembly compilation, WeakRef, and FinalizationRegistry are no longer exposed (wall-clock timing and GC observation cannot be replayed).

Minor Changes

  • #3098 8a95d36 Thanks @TooTallNate! - Carry the owning run's public key in forwarded WritableStream descriptors, so a run writing into another run's stream seals frames with no run fetch and no key-API round trip.

  • #3146 e8bc7d6 Thanks @TooTallNate! - Let observability tooling decrypt sealed (encp) payloads: key resolution now yields the run's full key capability, and hydrateDataWithKey dispatches on the envelope format.

  • #3094 7a65030 Thanks @TooTallNate! - Teach the serialization layer to read and write encp sealed envelopes via a PayloadKey union, so a cross-run writer can encrypt with only a public key. Existing symmetric call sites are unaffected.

  • #3096 0b1ca15 Thanks @TooTallNate! - resumeHook() now seals its payload to the target run's published public key when one is present, removing the cross-deployment run-key API round trip from hook resumption. Readers resolve the full key capability so they can open sealed payloads.

  • #3095 b4ba79e Thanks @TooTallNate! - Derive each run's X25519 public key at start() and stamp it on the run, so cross-run writers can seal payloads to the run without fetching its symmetric key.

  • #3093 4ba223a Thanks @TooTallNate! - Add the encp sealed-box encryption primitive: X25519 keypairs derived from the existing per-run key material, letting cross-run writers encrypt with only a public key. Not yet wired into any write path.

  • #3099 a86035f Thanks @TooTallNate! - The cross-deployment capability probe now returns the target run's public key, letting start() seal workflow arguments without a separate key-lookup request.

Patch Changes

  • #3111 8c12358 Thanks @NathanColosimo! - Clarify runtime invariants and compression behavior.

  • #3155 b8bcded Thanks @TooTallNate! - Seal forwarded writes to streams taken with getWritable() in a workflow body, which previously fell back to fetching the owner's symmetric key because the workflow VM has no key material to publish on the handle.

  • #3125 d24c91c Thanks @karthikscale3! - Hooks can carry an optional resumeContext; when present, resumeHook/resumeWebhook resume from it directly instead of fetching the full run, saving a round trip per resume. When the context also carries the run's encryptionPublicKey, the resume seals its payload (encp) directly to that key, so a default webhook resume needs neither a run read nor a run-key lookup. These two optimizations fall back independently: it fetches the full run when the context is absent, and uses symmetric encryption when no usable public key is available.

  • #3069 fd05393 Thanks @TooTallNate! - Fix a false "exceeded max retries" run failure: the retry-ceiling guard counted duplicate step_started events written by invocations racing on the same pending batch as real attempts. The owned-recovery ceiling now counts only the owning message's own starts, and the background-step ceiling counts only bare (queue-delivered) starts.

  • #3088 fc81f45 Thanks @karthikscale3! - Stream writes dispatch the first chunk of an idle stream immediately (flush window default 0 instead of 10ms). Fast producers keep full batching via in-flight accumulation; set streamFlushIntervalMs (World option) or WORKFLOW_STREAM_FLUSH_INTERVAL_MS (env, takes precedence) above 0 to opt into a windowed leading edge.

  • #3131 d7553c4 Thanks @NathanColosimo! - Avoid rescanning already prewarmed replay payloads during inline replays.

  • #3110 5d17c60 Thanks @NathanColosimo! - Consolidate runtime event merging logic.

  • #3139 2941b1c Thanks @pranaygp! - Deliver step results, wait completions, hook payloads and aborts in strict event-log order relative to one another, preventing replay divergence (CORRUPTED_EVENT_LOG) when a step completion is adjacent in the log to a wait_completed, hook_received or abort that a concurrent branch is awaiting.

  • #3078 b610c46 Thanks @karthikscale3! - Stream write batching now lives in the server writable itself (group commit), so raw ReadableStreams piped across workflow/step boundaries batch the same as getWritable() instead of sending one request per chunk.

  • Updated dependencies [8c12358, b4ba79e, a86035f, d24c91c, 313a074, fc81f45, 49276f2, 49276f2, 4ada27d, 62d570e, 62d570e, 62d570e, 49276f2]:

    • @workflow/world@5.0.0-beta.23
    • @workflow/world-vercel@5.0.0-beta.33
    • @workflow/world-local@5.0.0-beta.31
    • @workflow/utils@5.0.0-beta.7
    • @workflow/errors@5.0.0-beta.13

5.0.0-beta.36

Minor Changes

  • #2865 a5e6f11 Thanks @NathanColosimo! - Add experimental_minRetention for keeping a Hook token unavailable after its run ends, and require supporting Worlds to advertise the hookRetention capability.

  • #2946 eb8fdb9 Thanks @VaguelySerious! - The WORKFLOW_PRECONDITION_GUARD event-creation guard is now on by default; opt out with WORKFLOW_PRECONDITION_GUARD=0.

Patch Changes

  • #2993 6d1d700 Thanks @NathanColosimo! - Avoid resolving run data before background step execution.

  • #2996 d8071bb Thanks @joeyhotz! - Cache self-hosted step port discovery per process.

  • #2986 fe12b84 Thanks @shalabhc! - Enforce a server-supplied per-run event limit (default 25K)

  • #2970 bb773e9 Thanks @VaguelySerious! - Keep the inline event-log delta fast path active with open hooks when WORKFLOW_PRECONDITION_GUARD=1 and the World declares capabilities.preconditionGuard. The lazy inline step_started claim now carries the guard snapshot so a stale replay's claim is fenced (412 → fresh replay), and guard-enforced batches with an open hook take the await-then-run path so a fenced claim never executes the step body.

  • #2980 268fede Thanks @NathanColosimo! - Prepare encrypted replay payloads concurrently and cache the decrypted, decompressed representation for reuse across inline replay iterations.

  • #3035 9177ba8 Thanks @VaguelySerious! - Enforce maxRetries for inline and backgrounded steps that time out

  • #2995 6353c8c Thanks @VaguelySerious! - Fix stream writes never batching: flushablePipe awaited each writer.write() and the WritableStream sink serialized chunks one at a time, so the server writable's buffer never held more than one chunk and its writeMulti batching path never engaged — every chunk became its own server round trip. The server writable now exposes a durable batch write that flushablePipe uses to coalesce chunks arriving while a previous write is in flight into a single writeMulti, while preserving the existing durability guarantees. Coalesced batches are split at chunk-count and byte wire limits (WORKFLOW_STREAM_MAX_CHUNKS_PER_BATCH, WORKFLOW_STREAM_MAX_BYTES_PER_BATCH), independent of the read-ahead backpressure bound (WORKFLOW_STREAM_MAX_INFLIGHT_CHUNKS).

  • Updated dependencies [7d29bab, fe12b84, 6f032d7, a5e6f11, 850777a, 457e671, eb8fdb9, 9078126, 59c1369, bb773e9, 4ecbe7e]:

    • @workflow/world@5.0.0-beta.22
    • @workflow/world-local@5.0.0-beta.30
    • @workflow/world-vercel@5.0.0-beta.32
    • @workflow/errors@5.0.0-beta.12

5.0.0-beta.35

Minor Changes

  • #2266 a00d169 Thanks @VaguelySerious! - Add an opt-in optimistic-concurrency guard for event creation (WORKFLOW_PRECONDITION_GUARD=1): replay-context event creations send a stateUpdatedAt snapshot timestamp, and the runtime reloads the event log and retries (then falls back to a queue re-invocation) when the backend reports a newer out-of-band event with a 412 PreconditionFailedError.

  • #2929 1933e29 Thanks @VaguelySerious! - Report run-started-to-first-step (rsfs) and final-scheduling-replay (finalSchedulingReplay) latency telemetry on step completion events.

Patch Changes

  • #2153 6b8efd5 Thanks @rchasman! - Record cross-run lineage when start() is called from inside a workflow or step: the new run is tagged with $parentRunId (its direct parent) and inherits the parent's $rootRunId, so a daisy chain or fan-out of any depth groups under one root id.

  • #2943 fd107b9 Thanks @VaguelySerious! - Fixed TTFS latency telemetry reporting 0 for runs with region-tagged run IDs.

  • Updated dependencies [f72184d, a00d169, a00d169, 1933e29, 6b8efd5]:

    • @workflow/world-local@5.0.0-beta.29
    • @workflow/world-vercel@5.0.0-beta.31
    • @workflow/world@5.0.0-beta.21
    • @workflow/errors@5.0.0-beta.11

5.0.0-beta.34

Patch Changes

  • #2901 9242ddb Thanks @karthikscale3! - Move client-observed stream telemetry to core: chunk_rtt on the flush span, connect_ms on the read span, and new workflow.stream.close and workflow.stream.read.complete spans. Dedupe @opentelemetry/api to one workspace instance.

  • Updated dependencies [9242ddb]:

    • @workflow/world-vercel@5.0.0-beta.30

5.0.0-beta.33

Minor Changes

  • #1981 9da2d76 Thanks @TooTallNate! - start() now delegates run ID generation to world.createRunId(options) when the world provides it, falling back to a monotonic ULID otherwise. The full options bag is passed through so worlds can read whichever fields they recognise. Adds a new region option that worlds may consume — when set, it is also forwarded onto the queue options so the initial workflow message is routed to the matching region.

Patch Changes

  • Updated dependencies [f2be954, ac41e7d, a4d8de0, c31e30c, 9da2d76, 9da2d76]:
    • @workflow/world@5.0.0-beta.20
    • @workflow/world-vercel@5.0.0-beta.29
    • @workflow/errors@5.0.0-beta.10
    • @workflow/world-local@5.0.0-beta.28

5.0.0-beta.32

Patch Changes

  • #2891 4a43e39 Thanks @karthikscale3! - Emit a client-observed workflow.stream.flush span per stream-write batch, with a buffer_dwell_ms attribute separating client-side batching cost from network/server time. Log under DEBUG=workflow:* when @opentelemetry/api fails to load in world-vercel.

  • Updated dependencies [4a43e39]:

    • @workflow/world-vercel@5.0.0-beta.28

5.0.0-beta.31

Minor Changes

  • #2882 0b956f6 Thanks @VaguelySerious! - Rename experimental_setAttributes to setAttributes — the attributes feature is no longer experimental. The old name remains available as a deprecated alias.

Patch Changes

  • Updated dependencies [7a1ea5a, 0b956f6]:
    • @workflow/world@5.0.0-beta.19
    • @workflow/world-local@5.0.0-beta.27
    • @workflow/errors@5.0.0-beta.10
    • @workflow/world-vercel@5.0.0-beta.27

5.0.0-beta.30

Minor Changes

  • #2850 f28150c Thanks @karthikscale3! - Report step progress alongside step-to-step overhead latency telemetry.

  • #2872 36c63af Thanks @mitul-s! - Record the source run on replays: recreateRunFromExisting now stamps replayedFromRunId into the new run's executionContext (and start accepts a matching option) so tooling can surface a run as a replay and link back to its origin.

Patch Changes

  • #2790 145835b Thanks @NathanColosimo! - Centralize workflow event type classifiers and event-data payload field helpers.

  • #2687 9958424 Thanks @Osamaali313! - Fix extractStreamIds overflowing the stack on circular references. The hydrated observability data it walks comes from devalue, which preserves circular and repeated references, so a step result containing a cycle would crash run inspection (wf inspect and the web dashboard) with a RangeError. The traversal now tracks visited containers and skips cycles.

  • #2848 6603628 Thanks @VaguelySerious! - Fix duplicate inline step execution when a hook or wait wakes a run while the step is still running (#2780). The lazy step_started now records the owning queue message ID, and wake replays schedule a delayed backstop for in-flight inline steps instead of immediately re-dispatching them. Disable with WORKFLOW_INLINE_OWNERSHIP=0.

  • #2874 48fcc4e Thanks @karthikscale3! - Add a namespace option to start(), recreateRunFromExisting(), reenqueueRun(), and wakeUpRun() for targeting deployments with namespaced queue topics, and make healthCheck() respect its timeout when the stream read hangs.

  • #2857 2c6ee61 Thanks @karthikscale3! - Add stream latency to OTEL spans

  • Updated dependencies [f28150c, 84df8f3, 4dce2ae, 145835b, 6603628, 2c6ee61]:

    • @workflow/world@5.0.0-beta.18
    • @workflow/world-vercel@5.0.0-beta.26
    • @workflow/world-local@5.0.0-beta.26
    • @workflow/errors@5.0.0-beta.10

5.0.0-beta.29

Minor Changes

  • #2833 3f69666 Thanks @VaguelySerious! - Report time-to-first-step and step-to-step overhead latency telemetry on step completion events.

Patch Changes

  • #2833 3f69666 Thanks @VaguelySerious! - experimental_setAttributes now resolves via an in-process replay instead of a queue re-invocation, removing a delivery round-trip before subsequent steps.

  • #2840 712ed61 Thanks @VaguelySerious! - Add an optional reason to run cancellation (run.cancel({ cancelReason })), recorded on the cancellation event and shown in the run detail view.

  • Updated dependencies [79a9813, 3f69666, 712ed61]:

    • @workflow/world-local@5.0.0-beta.25
    • @workflow/world@5.0.0-beta.17
    • @workflow/world-vercel@5.0.0-beta.25
    • @workflow/errors@5.0.0-beta.10

5.0.0-beta.28

Patch Changes

  • #2779 7637196 Thanks @VaguelySerious! - Fix createHook() conflicting with the run's own disposed hook when a token is reused after dispose() within the same run

  • #2732 239031a Thanks @NathanColosimo! - Respect framework base paths when routing workflow traffic and expose health checks on generated Next.js workflow routes.

  • #2807 e7e5a0e Thanks @VaguelySerious! - Steps that receive an AbortSignal argument no longer pay a per-step queue round-trip: the real-time abort-stream reader opened for such a step is now released when the step finishes, so the step can complete inline instead of reporting pending work on every invocation.

  • #2752 0f557d5 Thanks @ijjk! - Statically inject the configured world package into host bundles instead of selecting worlds dynamically at runtime.

  • #2468 49a50e8 Thanks @NathanColosimo! - Standardize first-party World packages on createWorld(), support relative target World modules consistently, and align the Postgres World DATABASE_URL fallback with bootstrap.

  • Updated dependencies [c1d29f1, c1d29f1, 7637196, e7e5a0e, 239031a, 0f557d5, fe327e6, 49a50e8, 03862ed]:

    • @workflow/world-local@5.0.0-beta.24
    • @workflow/utils@5.0.0-beta.6
    • @workflow/world-vercel@5.0.0-beta.24
    • @workflow/world@5.0.0-beta.16
    • @workflow/errors@5.0.0-beta.10

5.0.0-beta.27

Minor Changes

  • #2718 cc7f076 Thanks @VaguelySerious! - Make runtime tuning constants (timeouts, retry counts, stream buffering/reconnect) configurable via WORKFLOW_* environment variables, and forward WORKFLOW_TEST_LIMIT_OVERRIDES to the backend as a request header so a deployment can tighten server-side limits for testing.

Patch Changes

  • #2665 5a23159 Thanks @NathanColosimo! - Reduce e2e timing and polling flakes.

  • #2678 f6772d9 Thanks @ijjk! - Speed up Next.js workflow dev rebuilds, ignore commented imports during HMR discovery, and avoid Turbopack resolving custom-world dynamic imports.

  • Updated dependencies [f6772d9, fc5bdcb, f76377b, cc7f076, 2ab7057, 89f4726]:

    • @workflow/utils@5.0.0-beta.5
    • @workflow/world-local@5.0.0-beta.23
    • @workflow/world@5.0.0-beta.15
    • @workflow/world-vercel@5.0.0-beta.23
    • @workflow/errors@5.0.0-beta.9

5.0.0-beta.26

Patch Changes

  • 603ad97 - Treat transient world-vercel transport failures as retryable, surfacing them as a TRANSPORT type WorkflowWorldError, to be retried by the queue instead of failing the run.

  • #2685 2477ad8 Thanks @VaguelySerious! - Fix a turbo-mode race where a fire-and-forget hook, wait, or attribute created by a workflow that completes synchronously could be written to the server before the run was created.

  • Updated dependencies [897aac9, 603ad97, 1dcdafd]:

    • @workflow/world-vercel@5.0.0-beta.22

5.0.0-beta.25

Patch Changes

  • #2666 b180270 Thanks @NathanColosimo! - Retry inline step completion persistence failures instead of recording them as step failures.

  • 1ea2b4e - Fix a turbo-mode race where step-body writes (experimental_setAttributes and stream writes via getWritable) could reach the server before the workflow run was created.

  • Updated dependencies [5977694, d4e6c5b, a1cbc8b, 48e6bbf]:

    • @workflow/world-local@5.0.0-beta.22
    • @workflow/world-vercel@5.0.0-beta.21
    • @workflow/world@5.0.0-beta.14
    • @workflow/errors@5.0.0-beta.8

5.0.0-beta.24

Patch Changes

  • #2565 3fd4cc5 Thanks @ijjk! - Collapse default workflow build output to a single completion summary and move detailed progress logs behind DEBUG=workflow:build.

5.0.0-beta.23

Patch Changes

  • #2592 2bf5257 Thanks @karthikscale3! - Add OpenTelemetry spans, turbo tagging, and generated-route module timing around /flow initialization.

5.0.0-beta.22

Patch Changes

  • #2569 d108ba3 Thanks @VaguelySerious! - Turbo mode now tells world-vercel to skip the run_started event-log preload it never reads, reducing request time.

  • Updated dependencies [25c3df7, d476d7a, d108ba3]:

    • @workflow/world@5.0.0-beta.13
    • @workflow/world-vercel@5.0.0-beta.20
    • @workflow/errors@5.0.0-beta.8
    • @workflow/world-local@5.0.0-beta.21

5.0.0-beta.21

Minor Changes

  • #2526 3e82a12 Thanks @VaguelySerious! - Add turbo mode (on by default, disable with WORKFLOW_TURBO=0): on the first delivery of a run's first invocation the runtime backgrounds run_started, skips the initial event-log load, and forces optimistic inline start so the run reaches its first steps with no preceding network round-trips. It is safe there because the first delivery has no concurrent handler to race; turbo mode deactivates once a hook or sleep is encountered.

Patch Changes

  • #2412 6de5ea5 Thanks @VaguelySerious! - Fix a race where an AbortController aborted from a step was not reflected in a controller.signal passed to a subsequent step. The step now commits the abort's durable hook event before completing, and the workflow's suspension waits for the abort to land before serializing downstream step arguments.

  • #2472 66ca0dc Thanks @pranaygp! - Memoize hydrated step return values across inline replay iterations, turning the per-invocation step-result decrypt+parse cost from O(N²) to O(N) for sequential workflows. Only primitive results are cached, so deterministic replay is preserved.

5.0.0-beta.20

Minor Changes

  • #2525 7aee0d4 Thanks @TooTallNate! - Derive the workflow VM's deterministic RNG seed from runId:workflowName:deploymentId (instead of including the run's startedAt) and its initial fixed clock from the ULID timestamp embedded in runId. These inputs are all available the moment a queue message arrives, decoupling VM setup from the run_started round-trip. Note: this changes the seed-derived value sequence (step/hook correlation IDs, nanoids, random values) for a given run, so runs started before this change must not be replayed across the upgrade.

  • #2516 84ccd40 Thanks @VaguelySerious! - Inline execution now runs up to WORKFLOW_MAX_INLINE_STEPS (default 3) steps in parallel per suspension, each lazily created. An opt-in WORKFLOW_OPTIMISTIC_INLINE_START (default off) additionally starts step bodies before step_started is confirmed, reconciling the in-flight start before the terminal write so a lost create-claim is discarded; it is off by default because under contention a step body can run more than once (e.g. two runs writing to the workflow stream can corrupt it), so only enable it for idempotent steps.

Patch Changes

  • #2473 16b3670 Thanks @pranaygp! - Drain consecutively consumable replay events in a single synchronous pass instead of one process.nextTick per event, removing O(N) macrotask hops from replay.

  • #2475 2074f91 Thanks @pranaygp! - Skip the per-step incremental events.list round-trip in the inline sequential loop by consuming an event-log delta returned from the step's terminal write (gated to the single-step case with no open hooks or waits).

    Add the opt-in CreateEventParams.sinceCursor contract so a step-terminal events.create can return the event-log delta since that cursor (via EventResult.events/cursor/hasMore).

    Return the inline delta from a step-terminal write when sinceCursor is supplied, computed identically to events.list so the consumed prefix cannot skew from the server log.

    Forward sinceCursor over the v4 wire in @workflow/world-vercel so the server can return the delta on a step-terminal response; older servers ignore it and the runtime falls back to events.list.

  • #2478 e7ef9d8 Thanks @pranaygp! - Lazy inline step start: the owned-inline runtime path now sends a single step_started carrying the step input, letting the world create the step on the fly and saving one round-trip per inline step.

    @workflow/world: step_started event data accepts an optional input, and EventResult gains a stepCreated ownership signal.

    @workflow/world-local: step_started with input atomically creates the step plus a synthetic step_created event; a lazy step_started for an already-existing step throws EntityConflictError so concurrent losers skip (exactly-once).

    @workflow/world-postgres: same lazy-create + exactly-once create-claim for the Postgres backend.

    @workflow/world-vercel: sends the step input on step_started over the v4 wire and threads the server's stepCreated signal into EventResult.

  • #2522 722bb7c Thanks @VaguelySerious! - Cache the local dev server port per process so workflow replays no longer re-run OS port discovery (which spawns lsof on macOS, ~60ms) on every replay.

  • #2527 de91f20 Thanks @karthikscale3! - Refine WORKFLOW_TRACE_MODE=linked (the default) so each queue-delivered workflow.execute / step.execute span nests under its local delivery context instead of starting a new trace root.

  • #2511 ab2e9b8 Thanks @VaguelySerious! - Emit workflowName on per-step events (step_created, step_completed, and lazy-start step_started) so Worlds can access it without additional queries

  • #2471 939890d Thanks @pranaygp! - Cache the compiled workflow-bundle vm.Script per process so replays reuse the compiled bundle instead of re-parsing it on every iteration.

  • #2490 a92c16d Thanks @pranaygp! - Reject an explicit empty-string token in createHook(). Omit the option (or pass undefined) to get a randomly generated token, or pass a non-empty string.

  • #2529 37312ed Thanks @pranaygp! - Speed up workflow stack-trace remapping when source maps are absent (production default): skip bundle scanning when no frame references the workflow file and memoize parsed source maps per bundle.

  • Updated dependencies [b563126, 2074f91, e7ef9d8, ab2e9b8, 1332da3, fb5abbb, 90efb96]:

    • @workflow/world-local@5.0.0-beta.20
    • @workflow/world-vercel@5.0.0-beta.19
    • @workflow/world@5.0.0-beta.12
    • @workflow/errors@5.0.0-beta.8

5.0.0-beta.19

Patch Changes

  • Updated dependencies [26fd184]:
    • @workflow/world-vercel@5.0.0-beta.18

5.0.0-beta.18

Minor Changes

  • #2394 5f0b845 Thanks @pranaygp! - Compress serialized payloads (step inputs/outputs, workflow arguments/return values, errors, hook payloads) before storage using composable codec format prefixes. zstd is the preferred codec (markedly faster than gzip at an equal-or-better ratio, via node:zlib); gzip (CompressionStream) is the portable fallback when zstd is unavailable. Reads dispatch on the prefix, so both codecs are always decodable. Compression is applied before encryption, gated on run specVersion 5, and skipped for small or incompressible payloads. WORKFLOW_DISABLE_COMPRESSION=1 disables writes; WORKFLOW_COMPRESSION_CODEC=gzip forces the portable codec.

Patch Changes

  • #2394 5f0b845 Thanks @pranaygp! - Emit OpenTelemetry span attributes for payload compression on the serialize (write) and deserialize (read) paths: workflow.serialization.{operation,compressed,uncompressed_bytes,stored_bytes,compression_ratio}. Sizes are measured at the compression boundary (pre-encryption). Telemetry failures never affect serialization.

  • #2397 4b7a720 Thanks @pranaygp! - start({ deploymentId: 'latest' }) is now a no-op in Worlds that don't support atomic deployments (local dev, Postgres) instead of throwing — it logs a warning and targets the current deployment, so workflows that use 'latest' on Vercel still run locally.

  • #2470 3c79c56 Thanks @TooTallNate! - Fix the payload-compression capability cutoff: gzip/zstd are gated on 5.0.0-beta.18 (the first published version containing the compression read path) instead of 5.0.0-beta.16. The previous cutoff would let a producer write compressed payloads to a beta.16/beta.17 target that cannot decode them.

  • Updated dependencies [5f0b845, 5f0b845, 6aa1ce0]:

    • @workflow/world-vercel@5.0.0-beta.17
    • @workflow/world@5.0.0-beta.11
    • @workflow/errors@5.0.0-beta.8
    • @workflow/world-local@5.0.0-beta.19

5.0.0-beta.17

Minor Changes

  • #2363 926a5e7 Thanks @karthikscale3! - Add WORKFLOW_TRACE_MODE with a new linked default: each workflow/step invocation span is now its own trace root with span links to the delivery and run-origin contexts, instead of one trace spanning the entire run. world-vercel now explicitly injects W3C traceparent/tracestate/baggage headers on outgoing workflow-server requests.

    Span names are also friendlier: workflow and step spans now use the short function name (e.g. workflow.execute processOrder, step.execute chargeCard, workflow.start processOrder) instead of the uppercase prefixes and full machine names (WORKFLOW_V2 workflow//./src/jobs/order//processOrder). The full name remains available in the workflow.name / step.name span attributes, and new workflowDisplayName / stepDisplayName helpers are exported from @workflow/utils.

    Behavioral changes to telemetry under the new default (set WORKFLOW_TRACE_MODE=continuous to restore the previous trace shape exactly; the span-name change applies in both modes):

    • A run no longer shares one trace ID: the trace of the request that called start() no longer contains the workflow's execution spans — navigate via span links or the workflow.run.id attribute instead.
    • Sampling decisions are made independently per invocation root (previously one parent-based decision covered the whole run), and the number of root spans/traces increases to one per invocation.
    • workflow.execute/step.execute invocation spans (formerly WORKFLOW_V2/STEP) become parentless roots, which changes parent/child-based queries and service-map edges.
    • Re-enqueued queue messages forward the original run-origin trace carrier unchanged, rather than each invocation's current context.
    • Queries or dashboards matching the old WORKFLOW_V2 .../STEP ... span names must switch to the new names.
    • The queue-delivered workflow.execute span kind changed from internal to consumer, matching the queue-delivered step.execute span (this applies in both modes).

    Existing attributes and baggage keys are unchanged, and everything remains a no-op when no OpenTelemetry SDK is registered.

Patch Changes

  • Updated dependencies [926a5e7]:
    • @workflow/world-vercel@5.0.0-beta.16
    • @workflow/utils@5.0.0-beta.4
    • @workflow/errors@5.0.0-beta.8
    • @workflow/world-local@5.0.0-beta.18

5.0.0-beta.16

Minor Changes

  • #2385 628795a Thanks @pranaygp! - Add an allowReservedAttributes option to start() so framework-level callers can seed reserved $-prefixed run attributes at creation, matching the existing experimental_setAttributes option. The flag is carried through the resilient-start queue input so lazy run creation validates identically.

Patch Changes

  • Updated dependencies [af859c3, 628795a, 0178fa5]:
    • @workflow/world-local@5.0.0-beta.17
    • @workflow/world-vercel@5.0.0-beta.15
    • @workflow/world@5.0.0-beta.10
    • @workflow/errors@5.0.0-beta.7

5.0.0-beta.15

Minor Changes

  • #1853 303b6da Thanks @TooTallNate! - Add opt-in wire-level framing for byte streams (type: 'bytes') so consumers can identify chunk boundaries — a prerequisite for transparent auto-reconnect. The framing decision is gated on a new framedByteStreams capability and recorded per-stream in the serialized ref (framing: 'framed-v1'); legacy raw streams continue to work unchanged.

  • #2373 01c8c08 Thanks @pranaygp! - Replace hook.hasConflict (a Promise<boolean> property) with hook.getConflict(), a method returning a promise that suspends the workflow to commit hook registration and resolves with the conflicting Run when another active hook owns the token (or null once the hook is registered), without waiting for hook payload data. Code using await hook.hasConflict should migrate to const conflict = await hook.getConflict() and branch on conflict !== null.

  • #2226 ae8d6fe Thanks @pranaygp! - Allow passing initial run attributes through start(), and speed up workflow-level setAttribute calls by using native events for recording attributes.

Patch Changes

  • #1925 b3279f8 Thanks @VaguelySerious! - V2 suspension processing: unify wait + step queue dispatch into a single parallel batch. The runtime now queues every pending operation (non-inline steps + wait timer) in one Promise.all and then inline-executes one owned step (if any). The asymmetric { timeoutSeconds } return contract for waits is dropped from suspension processing; waits become normal queue continuations with delaySeconds, deduplicated per wait so repeated suspension passes don't accumulate delayed messages. Continuation delays are clamped to 23h (VQS's message-retention bound) with longer waits chained across hop-keyed messages, so multi-day sleep()s work on every world. This restores inline step execution for Promise.race(step, sleep) workflows without any of the carve-outs the prior fix needed: even when the inline step blocks the handler, the wait continuation fires in parallel and drives the next replay. As part of the same change, world-local's queue now honors delaySeconds (matches world-vercel / world-postgres), and its close() aborts pending delayed deliveries and retry sleeps so dev-server/test shutdown isn't held open by wait timers.

  • Updated dependencies [b3279f8, f2a7bde, ae8d6fe]:

    • @workflow/world-local@5.0.0-beta.16
    • @workflow/world@5.0.0-beta.9
    • @workflow/world-vercel@5.0.0-beta.14
    • @workflow/errors@5.0.0-beta.7

5.0.0-beta.14

Minor Changes

  • #2305 4670c4b Thanks @willsather! - Add an optional namespace parameter that scopes queue topic prefixes to __{namespace}_wkf_workflow_*. This allows configuring multiple frameworks in the same deployment without queue topic collision.

Patch Changes

  • #2345 bf44d4d Thanks @pranaygp! - Fix unhandled rejection when step_created/wait_created calls fail in waitUntil

  • #2318 eb976db Thanks @VaguelySerious! - Automatically reconnect object streams when the server stream connection times out.

  • #2336 a813382 Thanks @TooTallNate! - Fix unexpected rejections in waitUntil causing process crashes

  • Updated dependencies [95d7009, 4670c4b]:

    • @workflow/world-vercel@5.0.0-beta.13
    • @workflow/world@5.0.0-beta.8
    • @workflow/world-local@5.0.0-beta.15
    • @workflow/errors@5.0.0-beta.7

5.0.0-beta.13

Minor Changes

  • #1854 8d75491 Thanks @TooTallNate! - Surface workflowCoreVersion from the responding deployment in healthCheck() results.

Patch Changes

  • #2185 0fd0891 Thanks @VaguelySerious! - Fix CorruptedEventLogError on replay when a workflow races a hook read against a sleep() (e.g. Promise.race([hook, sleep])). Branch-deciding deliveries (buffered hook payloads and wait completions) are now handed to the workflow in strict event-log order — anchored on event position rather than on microtask-resolution timing — so the committed branch wins the race deterministically, independent of decryption/hydration time or Promise.race argument order.

  • #2257 ccd37e9 Thanks @pranaygp! - Avoid unhandled run lookups for unused or empty readable streams and include Vercel request correlation headers in world transport errors.

  • #2301 bb6ff9a Thanks @pranaygp! - Update vulnerable package dependencies to patched releases.

  • #2292 aa628b7 Thanks @pranaygp! - Bump devalue to 5.8.1 to address published security advisories.

  • Updated dependencies [867e339, ccd37e9, 81bda49, c19f38d]:

    • @workflow/world-local@5.0.0-beta.14
    • @workflow/world-vercel@5.0.0-beta.12

5.0.0-beta.12

Patch Changes

  • #2211 52d63d1 Thanks @pranaygp! - Prevent replayed workflows from advancing their deterministic clock when a future event is inspected before its matching operation is invoked.

  • #2212 2a3b11b Thanks @pranaygp! - Retry transient workflow replay divergence before classifying repeated divergence as a corrupted event log.

  • #2215 12c35b5 Thanks @pranaygp! - Skip workflow replay when a refreshed event log already contains a terminal run event.

  • Updated dependencies [b8a337c, ddc8a79, 2a3b11b, 3a16272]:

    • @workflow/world-local@5.0.0-beta.13
    • @workflow/world-vercel@5.0.0-beta.11
    • @workflow/errors@5.0.0-beta.7
    • @workflow/world@5.0.0-beta.7

5.0.0-beta.11

Patch Changes

  • #2180 1ee63b8 Thanks @pranaygp! - Harden runtime event pagination against rejected, repeated, or overlapping cursor responses.

  • #2191 8f68d35 Thanks @pranaygp! - Fix forwarded writable stream encryption when child workflows execute on a newer deployment than their parent.

  • Updated dependencies [8f68d35, 7994629]:

    • @workflow/world@5.0.0-beta.6
    • @workflow/world-vercel@5.0.0-beta.10
    • @workflow/errors@5.0.0-beta.6
    • @workflow/world-local@5.0.0-beta.12

5.0.0-beta.10

Patch Changes

  • #2145 8d0928b Thanks @TooTallNate! - Classify SDK-level AES-GCM encryption failures as RUNTIME_ERROR instead of USER_ERROR via a new RuntimeDecryptionError.

  • Updated dependencies [8d0928b, 3128dfc]:

    • @workflow/errors@5.0.0-beta.6
    • @workflow/world-local@5.0.0-beta.11
    • @workflow/world-vercel@5.0.0-beta.9

5.0.0-beta.9

Patch Changes

  • #2150 4b5f017 Thanks @pranaygp! - Treat serialized and cross-realm AbortError step failures as fatal cancellations, and stabilize abort E2E readiness checkpoints.

  • #2157 409b103 Thanks @VaguelySerious! - Allow experimental_setAttributes() to be called from step functions.

  • #2142 ae37315 Thanks @pranaygp! - Prevent failed stream writes from surfacing as unhandled rejections and include request correlation details in stream errors.

  • Updated dependencies [65336df, ae37315]:

    • @workflow/world-local@5.0.0-beta.8
    • @workflow/world-vercel@5.0.0-beta.8

5.0.0-beta.8

Patch Changes

  • #2134 1e6b1fd Thanks @VaguelySerious! - Add experimental_setAttributes() workflow-level helper for attaching string key/value metadata to a workflow run, surfaced as run.attributes

  • #2086 2050656 Thanks @VaguelySerious! - Fix getWritable() returning a new TransformStream per call, which caused racing pipes to reorder chunks when callers acquired a writer per write. Repeat calls within the same step now share a single pipe per (runId, namespace).

  • #2134 1e6b1fd Thanks @VaguelySerious! - Harden workflow error stack remapping for large inline sourcemaps.

  • #1799 503a929 Thanks @TooTallNate! - Use inline sourcemaps for all workspace packages; published packages no longer ship external .js.map files.

  • Updated dependencies [1e6b1fd, 62ec537, b0d0561, 503a929, 657e8bb]:

    • @workflow/world@5.0.0-beta.5
    • @workflow/world-local@5.0.0-beta.7
    • @workflow/world-vercel@5.0.0-beta.7
    • @workflow/errors@5.0.0-beta.5
    • @workflow/serde@5.0.0-beta.2
    • @workflow/utils@5.0.0-beta.3

5.0.0-beta.7

Minor Changes

  • #2059 49da6c5 Thanks @TooTallNate! - A WritableStream from a workflow's getWritable() can now be passed as an argument to a child workflow via start(); the child's writes land on the parent run's stream directly for the full lifetime of the child run.

Patch Changes

  • #2038 dc0be50 Thanks @pranaygp! - Refresh workflow events after completing elapsed waits so concurrent hook events preserve deterministic replay order.

  • #2046 ad71b58 Thanks @pranaygp! - Report corrupted event logs with a distinct CorruptedEventLogError type and CORRUPTED_EVENT_LOG run error code.

  • #2056 9454151 Thanks @VaguelySerious! - Fix spurious "Event cursor missing after initial load" warning

  • #2030 b124365 Thanks @pranaygp! - Validate step, wait, and hook lifecycle events against replay ownership metadata.

  • #2013 2a446af Thanks @TooTallNate! - Exclude inline step execution from the workflow replay timeout. Long-running steps no longer hit REPLAY_TIMEOUT (fixes #2009). Adds a WORKFLOW_REPLAY_TIMEOUT_MS env var override and a new optional World.processExitTriggersQueueRedelivery capability used to gate the runtime's process.exit(1) failure path.

  • #2060 1d3959e Thanks @pranaygp! - Record fatal world response contract failures as non-retryable workflow errors.

  • Updated dependencies [dc0be50, ad71b58, b124365, 2a446af, 1d3959e]:

    • @workflow/world@5.0.0-beta.4
    • @workflow/world-local@5.0.0-beta.6
    • @workflow/world-vercel@5.0.0-beta.6
    • @workflow/errors@5.0.0-beta.4

5.0.0-beta.6

Patch Changes

  • #2012 9d2a926 Thanks @pranaygp! - Expose the active run ID on hook token conflict errors.

  • Updated dependencies [9d2a926, c43e721, c145bf5, 22b5a12]:

    • @workflow/errors@5.0.0-beta.3
    • @workflow/world@5.0.0-beta.3
    • @workflow/world-local@5.0.0-beta.5
    • @workflow/world-vercel@5.0.0-beta.5

5.0.0-beta.5

Major Changes

  • #1851 5f22832 Thanks @TooTallNate! - BREAKING CHANGE: Run and step errors are now serialized through the workflow serialization pipeline, preserving original class identity and cause chains on WorkflowRunFailedError.cause. Pre-upgrade failed runs in the world-postgres legacy error text column surface as error: undefined on read; the original payload is still readable directly from the errorJson column for manual inspection.

Minor Changes

  • #1511 e7ea068 Thanks @TooTallNate! - Add first-class serialization support for built-in Error subclasses (TypeError, RangeError, SyntaxError, URIError, ReferenceError, EvalError, AggregateError) and preserve the cause property on all Error types

  • #1513 74b13cd Thanks @TooTallNate! - Add first-class serialization for FatalError and RetryableError so they round-trip with class identity preserved across all serialization boundaries (including from environments that don't run the SWC plugin)

Patch Changes

  • #1301 aee5699 Thanks @pranaygp! - Drain pending queue items at workflow completion instead of only logging warnings, and implicitly dispose any never-aborted system (abort) hooks at completion so unused AbortController instances don't leave abandoned rows in the hooks table for the run's TTL

  • #1301 aee5699 Thanks @pranaygp! - Fix DOMException not serializing correctly

  • #1924 3535caf Thanks @VaguelySerious! - Fix Promise.race(step, sleep) always blocking until step completed

  • #1849 1203dae Thanks @pranaygp! - Friendlier workflow error messages. New SerializationError, WorkflowBuildError, and structured context-violation classes (e.g. NotInWorkflowContextError) with actionable hints and docs links applied to user-facing throw sites; FatalError.is() recognizes any error with fatal: true so context violations and serialization failures now fail fast instead of burning retry attempts. Runtime logs are namespaced under [workflow-sdk] and gain errorAttribution (user vs sdk) plus class-aware hints

  • #1747 00a011d Thanks @ijjk! - Fix eager Next.js workflow builds with lazy discovery disabled.

  • #1849 1203dae Thanks @pranaygp! - Replace util.inspect's default object dump for runtime structured-log metadata with an opinionated, workflow-aware formatter. The runtime logger uses color-coded metadata blocks.

  • #1301 aee5699 Thanks @pranaygp! - Add serializable AbortController and AbortSignal support across workflow and step boundaries. Workflow code can now construct an AbortController, pass signal to steps, and call abort().

    Behavior change: AbortError thrown from inside a step is now wrapped as FatalError and skips retry semantics. As a result, custom timeouts on fetch inside steps are no longer re-tried by default, and now need to be wrapped in RetryableError to preserve the old behavior.

  • #1299 9f3516e Thanks @TooTallNate! - Refactor serialization.ts into modular serialization/ files. No runtime change.

  • #1935 d0e3f27 Thanks @TooTallNate! - Preserve the this binding of bound step proxies across workflow serialization, so passing useStep(...).bind(thisArg) as a step argument no longer loses the receiver.

  • #1338 8ea1532 Thanks @VaguelySerious! - Merge flow and step routes into a single combined handler that executes steps inline when possible, reducing function invocations and queue overhead.

  • #1951 72911f7 Thanks @VaguelySerious! - Fix world.ts being tree-shaken out of the bundle and unavailable at runtime

  • Updated dependencies [540a2ef, 92dc826, 5eb0b79, 5374148, 1203dae, 1203dae, 5f22832, 2f52d14, 8ea1532, c1163eb, cd50618]:

    • @workflow/errors@5.0.0-beta.2
    • @workflow/world-local@5.0.0-beta.4
    • @workflow/world-vercel@5.0.0-beta.4
    • @workflow/world@5.0.0-beta.2
    • @workflow/utils@5.0.0-beta.2

5.0.0-beta.4

5.0.0-beta.3

Minor Changes

Patch Changes

  • #1848 7d07fab Thanks @pranaygp! - Replace eval in serialization.ts revive() helper with JSON.parse. devalue.stringify() output is always valid JSON (special values are encoded as negative integer sentinels), so JSON.parse is a safe drop-in that eliminates the eval anti-pattern.

  • Updated dependencies [3ad8ee7, 354840e]:

    • @workflow/world-local@5.0.0-beta.3
    • @workflow/world-vercel@5.0.0-beta.3

5.0.0-beta.2

Patch Changes

  • #1716 df115fd Thanks @karthikscale3! - Make encrypted markers clickable to trigger decryption and detect encryption at run level before span selection. Persist features.encryption flag in executionContext at run creation so the UI can detect encryption without a probe fetch.

  • #1740 0810b75 Thanks @VaguelySerious! - When runtime replays exceed 240s, re-try them up to three times, instead of failing immediately

  • #1769 5a42964 Thanks @tomdale! - Embed source content in published sourcemaps.

  • #1778 b7d6595 Thanks @TooTallNate! - Fix false-positive unconsumed step_created errors when replay resumes a for await hook loop and appends more async work after the first promise-queue drain.

  • #1681 ac09f40 Thanks @TooTallNate! - Add clickable Run reference rendering in observability UI

  • #1759 173756d Thanks @TooTallNate! - Rename useworkflow.dev URLs to workflow-sdk.dev

  • Updated dependencies [340c085, 5a42964, 11cfb8f, 173756d]:

    • @workflow/world-vercel@5.0.0-beta.2
    • @workflow/errors@5.0.0-beta.1
    • @workflow/serde@5.0.0-beta.1
    • @workflow/utils@5.0.0-beta.1
    • @workflow/world-local@5.0.0-beta.2

5.0.0-beta.1

Major Changes

  • #1293 66d49c0 Thanks @VaguelySerious! - BREAKING CHANGE: Restructure stream methods on World interface to use world.streams.* namespace with runId as the first parameter. writeToStream(name, runId, chunk) → streams.write(runId, name, chunk), writeToStreamMulti → streams.writeMulti, closeStream → streams.close, readFromStream → streams.get(runId, name, startIndex?), listStreamsByRunId → streams.list(runId).

  • #1632 0a86de3 Thanks @TooTallNate! - BREAKING CHANGE: Remove @workflow/core/private and workflow/internal/private public subpath exports. The SWC compiler plugin no longer generates imports from these paths.

  • #1293 66d49c0 Thanks @VaguelySerious! - Require runId argument for world.steps.get.

Minor Changes

  • #1652 ec517fa Thanks @TooTallNate! - Add features.encryption to WorkflowMetadata returned by getWorkflowMetadata()

  • #1616 71d39d2 Thanks @TooTallNate! - Use custom class serialization for Run across runtime and workflow VM contexts, and add e2e coverage for Run instance boundary roundtrips

  • #1677 9513a81 Thanks @TooTallNate! - Add serialization support for workflow function references

Patch Changes

  • #1658 a5c90ce Thanks @VaguelySerious! - Fix community world E2E tests by adding specVersion to the World interface so start() uses the safe baseline (v2) for worlds that don't declare their supported version

  • #1678 ea97bd6 Thanks @TooTallNate! - Remove redundant hc_ prefix from health check correlationId that caused doubled hc_hc_ in the derived runId and stream name.

  • #942 873b4e2 Thanks @VaguelySerious! - BREAKING CHANGE: Make getWorld and createWorld asynchronous to support ESM dynamic imports for custom world modules. All callers must now await getWorld().

  • Updated dependencies [66d49c0, a5c90ce, 68cf25e, 66d49c0]:

    • @workflow/world@5.0.0-beta.1
    • @workflow/world-local@5.0.0-beta.1
    • @workflow/world-vercel@5.0.0-beta.1
    • @workflow/errors@5.0.0-beta.0

5.0.0-beta.0

Major Changes

Patch Changes

  • Updated dependencies [c5cdfc0]:
    • @workflow/errors@5.0.0-beta.0
    • @workflow/serde@5.0.0-beta.0
    • @workflow/utils@5.0.0-beta.0
    • @workflow/world@5.0.0-beta.0
    • @workflow/world-local@5.0.0-beta.0
    • @workflow/world-vercel@5.0.0-beta.0

4.2.0-beta.78

Patch Changes

  • #1627 5f138f2 Thanks @VaguelySerious! - Bump specVersion to 3 and gate CBOR queue transport on spec version. Old deployments (specVersion < 3) receive JSON queue messages; new deployments receive CBOR. Handler uses dual transport to deserialize both formats. Fixes replay/reenqueue from dashboard to older deployments.

  • #1629 a6bcea9 Thanks @VaguelySerious! - CLI start command probes deployment specVersion via health check before choosing queue transport. Health check always uses JSON transport for compatibility with old deployments.

  • #1533 7e70d18 Thanks @VaguelySerious! - Add streamFlushIntervalMs option to Streamer interface, optional for worlds to allow overwriting the default of 10ms in low-latency environments.

  • #1512 ba916e1 Thanks @TooTallNate! - Add DOMException to the workflow VM context and add first-class serialization support, preserving message, name, and derived code across serialization boundaries

  • #1618 c9b3038 Thanks @VaguelySerious! - fix(core): properly propagate stream cancellation on disconnect

  • #1537 c8dce52 Thanks @VaguelySerious! - Allow workflow invocation to create run if initial storage call in start did not succeed. Send run input through queue to enable this. Allow creating run_created and run_started events together in World, and skip first event list call by returning events directly.

  • #1606 ab872cc Thanks @VaguelySerious! - Make registeredSteps a global singleton to protect against module duplication and caching issues

  • Updated dependencies [5f138f2, 7e70d18, c8dce52, 5b9eb40]:

    • @workflow/world-vercel@4.1.0-beta.49
    • @workflow/world@4.1.0-beta.17
    • @workflow/world-local@4.1.0-beta.51
    • @workflow/errors@4.1.0-beta.20

4.2.0-beta.77

Patch Changes

  • #1591 d8aaf27 Thanks @VaguelySerious! - Fix step contextStorage global potentially seeing dual-instance issues when bundlers create multiple copies of the module.

  • #1367 047c01b Thanks @pranaygp! - Make start() return Run<unknown> with unknown[] args when deploymentId is provided, since the deployed workflow version may have different types

  • Updated dependencies [b30b0dc, 760ebf1]:

    • @workflow/world@4.1.0-beta.16
    • @workflow/world-local@4.1.0-beta.50
    • @workflow/world-vercel@4.1.0-beta.48
    • @workflow/errors@4.1.0-beta.20

4.2.0-beta.76

Patch Changes

  • Updated dependencies [ef2218a]:
    • @workflow/world-local@4.1.0-beta.49
    • @workflow/world-vercel@4.1.0-beta.47

4.2.0-beta.75

Patch Changes

  • #1569 a98f8de Thanks @VaguelySerious! - Combine initial run fetch, event fetch, and run_started event creation

  • #1572 d38114b Thanks @TooTallNate! - Fix resumeHook()/resumeWebhook() failing on workflow runs from pre-encryption deployments by checking the target run's workflowCoreVersion capabilities before encoding the payload

  • #1567 6dc1b78 Thanks @VaguelySerious! - Increase flow route limit to max fluid duration and fail run if a single replay takes too long

  • Updated dependencies [a98f8de, 6dc1b78, 329cdb3]:

    • @workflow/world@4.1.0-beta.15
    • @workflow/world-local@4.1.0-beta.48
    • @workflow/errors@4.1.0-beta.20
    • @workflow/world-vercel@4.1.0-beta.46

4.2.0-beta.74

Patch Changes

4.2.0-beta.73

Patch Changes

  • #1520 8e7083b Thanks @pranaygp! - Add btoa, atob, and Buffer globals to workflow VM context for base64 encoding/decoding

  • #1523 d1391e1 Thanks @pranaygp! - Fix race condition allowing duplicate hook_disposed events for the same hook

  • #1518 c739b99 Thanks @ceolinwill! - Fix getWritable() in step functions to resolve on lock release instead of requiring stream close, preventing Vercel function timeouts

  • Updated dependencies [d1391e1]:

    • @workflow/world-local@4.1.0-beta.46

4.2.0-beta.72

Patch Changes

  • #1448 73a851a Thanks @pranaygp! - Add HookConflictError to @workflow/errors and use it for hook token conflicts instead of WorkflowRuntimeError

  • #1340 84599b7 Thanks @pranaygp! - Add error code classification (USER_ERROR, RUNTIME_ERROR) to run_failed events, improve queue and schema validation error logging

  • #1452 672d919 Thanks @pranaygp! - Fix workflow/step not found errors to fail gracefully instead of causing infinite queue retries

  • #1344 beccbc4 Thanks @pranaygp! - Remove VQS maxDeliveries cap and enforce max delivery limit in workflow/step handlers with graceful failure

  • #1460 78f1b0e Thanks @VaguelySerious! - Support negative startIndex for streaming (e.g. -3 reads last 3 chunks)

  • #1438 da6adf7 Thanks @VaguelySerious! - Improve display when run data has expired

  • #1342 aee035f Thanks @pranaygp! - Replace HTTP status code checks with semantic error types (EntityConflictError, RunExpiredError, ThrottleError, TooEarlyError). BREAKING CHANGE: WorkflowAPIError renamed to WorkflowWorldError.

  • #1470 01bbe66 Thanks @VaguelySerious! - Add getStreamChunks() and getStreamInfo() to the Streamer interface, and getTailIndex() to the readable stream returned by run.getReadable(). WorkflowChatTransport now reads the x-workflow-stream-tail-index response header to resolve negative initialStartIndex values into absolute positions, fixing reconnection retries after a disconnect.

  • #1446 2b07294 Thanks @VaguelySerious! - Ensure open stream flush is await-able in pendingOps

  • Updated dependencies [73a851a, 84599b7, fdbe853, 2ef33d2, d428d66, 672d919, beccbc4, 78f1b0e, aee035f, 741661b, 01bbe66]:

    • @workflow/errors@4.1.0-beta.19
    • @workflow/world-local@4.1.0-beta.45
    • @workflow/world-vercel@4.1.0-beta.45
    • @workflow/world@4.1.0-beta.14

4.2.0-beta.71

Patch Changes

  • #1409 97e4384 Thanks @TooTallNate! - Remove @deprecated tag from deploymentId in StartOptions

  • #1413 dcb0761 Thanks @TooTallNate! - Refactor builtin step functions to use this value serialization instead of explicit parameter passing. Remove unused duplicate builtins file from @workflow/core.

  • #1396 2f0772d Thanks @karthikscale3! - Track Vercel request IDs (x-vercel-id) on all workflow events for correlating request logs with workflow executions

  • #1400 a2c0c7e Thanks @VaguelySerious! - Seed lazy workflow file discovery in NextJS. Require workflow definitions to be in manifest for Vercel environments.

  • #1418 2cc42cb Thanks @VaguelySerious! - Don't fail to queue on 409 responses

  • #1402 f52afe7 Thanks @VaguelySerious! - Reduce log severity for 409/429 logs from warn to info, as they can't be meaningfully acted on by the consumer.

  • Updated dependencies [02ea057, d6e8727, 2f0772d, 0f07403, e902980, 94c14c7]:

    • @workflow/world-local@4.1.0-beta.44
    • @workflow/world-vercel@4.1.0-beta.44
    • @workflow/world@4.1.0-beta.13
    • @workflow/errors@4.1.0-beta.18

4.2.0-beta.70

Patch Changes

  • #1339 7df1385 Thanks @TooTallNate! - Separate infrastructure vs user code error handling in workflow and step runtimes so transient network errors (ECONNRESET, etc.) propagate to the queue for retry instead of incorrectly marking runs as failed

  • #1345 58e67ce Thanks @TooTallNate! - Suppress stale WORKFLOW_VERCEL_* env var warning when running outside Vercel serverless (e.g. CLI, web observability app)

  • Updated dependencies [9feebee]:

    • @workflow/world-local@4.1.0-beta.43

4.2.0-beta.69

Patch Changes

  • #1317 825417a Thanks @TooTallNate! - Support deploymentId: 'latest' in start() options to automatically resolve the most recent deployment ID for the current environment

  • #1336 fb5a500 Thanks @pranaygp! - Add exists getter to Run class for checking if a workflow run exists without throwing

  • Updated dependencies [825417a, 825417a, 3648109, d5bc418]:

    • @workflow/world-vercel@4.1.0-beta.43
    • @workflow/world@4.1.0-beta.12
    • @workflow/world-local@4.1.0-beta.42
    • @workflow/errors@4.1.0-beta.18

4.2.0-beta.68

Patch Changes

  • #1304 83dbd46 Thanks @TooTallNate! - Stop reading WORKFLOW_VERCEL_* env vars at runtime to prevent unintended proxy routing

  • #1318 854a25f Thanks @TooTallNate! - Fix start() not encrypting initial workflow input in external contexts (e2e tests, CLI). The resolved deploymentId was not being passed to getEncryptionKeyForRun, causing it to silently skip encryption when deploymentId was inferred from the environment rather than explicitly provided in options.

  • Updated dependencies [9781afb, 4a6ddd8, d842ce1]:

    • @workflow/world-vercel@4.1.0-beta.42
    • @workflow/world-local@4.1.0-beta.41

4.2.0-beta.67

Patch Changes

  • #1294 c71befe Thanks @pranaygp! - Fix premature workflow suspension when hooks have buffered payloads and a concurrent sleep or incomplete step is pending

  • #1285 36a901d Thanks @TooTallNate! - Add workflowName to getWorkflowMetadata() and stepName to getStepMetadata()

  • Updated dependencies [d8daa2a]:

    • @workflow/world@4.1.0-beta.11
    • @workflow/world-local@4.1.0-beta.40
    • @workflow/world-vercel@4.1.0-beta.41
    • @workflow/errors@4.1.0-beta.18

4.2.0-beta.66

Patch Changes

  • #1290 8b5a388 Thanks @pranaygp! - Support timeoutSeconds: 0 for immediate re-enqueue without arbitrary delay

  • #1283 dff00c9 Thanks @VaguelySerious! - Avoid port inference in Vercel environment

  • Updated dependencies [8b5a388]:

    • @workflow/world-local@4.1.0-beta.39
    • @workflow/world-vercel@4.1.0-beta.40

4.2.0-beta.65

Patch Changes

  • Updated dependencies [456c1aa, 11dcb64]:
    • @workflow/world-local@4.1.0-beta.38
    • @workflow/world@4.1.0-beta.10
    • @workflow/world-vercel@4.1.0-beta.39
    • @workflow/errors@4.1.0-beta.18

4.2.0-beta.64

Minor Changes

  • 30e24d4 Thanks @pranaygp! - BREAKING CHANGE: createWebhook() no longer accepts a token option. Webhook tokens are always randomly generated to prevent unauthorized access to the public webhook endpoint. Use createHook() with resumeHook() for deterministic server-side token patterns.

Patch Changes

  • #1270 adfe8b6 Thanks @pranaygp! - Add HookNotFoundError to @workflow/errors and adopt it across all world backends

  • #1270 adfe8b6 Thanks @pranaygp! - Prevent hooks from being resumed via the public webhook endpoint by default. Add isWebhook option to createHook() to opt-in to public resumption. createWebhook() always sets isWebhook: true.

  • #1251 7618ac3 Thanks @TooTallNate! - Wire AES-GCM encryption into serialization layer with stream support

  • #1246 860531d Thanks @TooTallNate! - Route all event-driven promise resolutions through a sequential queue to ensure deterministic ordering

  • #1254 60bc9d5 Thanks @TooTallNate! - Fix false positive unconsumed event detection during async deserialization and cross-VM promise propagation

  • #1256 bbe40ff Thanks @TooTallNate! - Add encryption-aware o11y for CLI and web UI

  • #1269 a7ae7e9 Thanks @pranaygp! - Improve deterministic VM context seed derivation to incorporate additional run metadata

  • Updated dependencies [adfe8b6, adfe8b6, 02f706f]:

    • @workflow/errors@4.1.0-beta.18
    • @workflow/world-local@4.1.0-beta.37
    • @workflow/world-vercel@4.1.0-beta.38
    • @workflow/world@4.1.0-beta.9

4.1.0-beta.63

Patch Changes

  • #1232 4ab4412 Thanks @pranaygp! - Add Run.wakeUp() method to programmatically interrupt pending sleep() calls

  • #1230 a9fea91 Thanks @ijjk! - Fix deferred build mode for Next.js

  • Updated dependencies [2b1c2bd]:

    • @workflow/world-vercel@4.1.0-beta.37

4.1.0-beta.62

Patch Changes

  • #1172 6f2cbcd Thanks @TooTallNate! - Fix custom Error subclass serialization precedence: move Instance reducer before Error reducer so that Error subclasses with WORKFLOW_SERIALIZE are serialized using custom class serialization instead of the generic Error serialization

  • #1181 02681dc Thanks @pranaygp! - Add hook.dispose() method to explicitly release hook tokens for reuse by other workflows while the current workflow is still running

  • #1185 028a828 Thanks @pranaygp! - Warn when workflow completes with uncommitted operations (unawaited steps, hooks, or sleeps)

  • #1217 e55c636 Thanks @pranaygp! - Upgrade dependencies across all packages

  • Updated dependencies [1cfb8b1, 274ea8b, f3b2e08, e55c636]:

    • @workflow/world-vercel@4.1.0-beta.36
    • @workflow/world-local@4.1.0-beta.36
    • @workflow/utils@4.1.0-beta.13
    • @workflow/world@4.1.0-beta.8
    • @workflow/errors@4.1.0-beta.17

4.1.0-beta.61

Patch Changes

4.1.0-beta.60

Patch Changes

4.1.0-beta.59

Patch Changes

  • #1120 c75de97 Thanks @VaguelySerious! - Handle 409 errors gracefully for step_completed, step_failed, and step_retrying events

  • #956 b65bb07 Thanks @TooTallNate! - Add browser-compatible AES-256-GCM encryption module with importKey, encrypt, and decrypt functions; update all runtime callers to resolve CryptoKey once per run via importKey()

  • Updated dependencies [b65bb07, b65bb07]:

    • @workflow/world-vercel@4.1.0-beta.34
    • @workflow/world@4.1.0-beta.6
    • @workflow/errors@4.1.0-beta.16
    • @workflow/world-local@4.1.0-beta.34

4.1.0-beta.58

Patch Changes

  • #978 0d5323c Thanks @TooTallNate! - Refactor serialization code to be asynchronous

  • #1098 7046610 Thanks @pranaygp! - Auto-inject x-workflow-run-id and x-workflow-step-id VQS headers from queue payload in world-vercel

  • #1055 c2b4fe9 Thanks @pranaygp! - Detect and fatal error on orphaned/invalid events in the event log instead of silently hanging

  • #979 6e72b29 Thanks @TooTallNate! - Add World.getEncryptionKeyForRun() and thread encryption key through serialization layer

  • #999 ea3254e Thanks @TooTallNate! - Separate project ID and project name into distinct env vars (WORKFLOW_VERCEL_PROJECT and WORKFLOW_VERCEL_PROJECT_NAME)

  • #1031 1c11573 Thanks @karthikscale3! - Refactor and enhance web-shared observability UI components and update builders base behavior.

  • #1051 9f77380 Thanks @VaguelySerious! - Fix 429 backoff for workflow runtime API calls

  • #1118 852e3f1 Thanks @VaguelySerious! - Do not re-throw error when multiple workflow invocations race to complete the workflow

  • #1057 5e06a7c Thanks @pranaygp! - Materialize waits as entities to prevent duplicate wait_completed events

    • @workflow/core: Handle 409 conflict gracefully when creating wait_completed events, preventing crashes when multiple concurrent invocations race to complete the same wait
    • @workflow/world: Add Wait type, WaitSchema, and WaitStatusSchema exports; add optional wait field to EventResult
    • @workflow/world-local: Materialize wait entities on wait_created/wait_completed with duplicate detection; clean up waits on terminal run states
    • @workflow/world-postgres: Add workflow_waits table with wait_status enum; materialize wait entities with conditional writes for duplicate prevention; clean up waits on terminal run states
  • Updated dependencies [7046610, c2b4fe9, 6e72b29, ea3254e, 29347b7, 5e06a7c, 5487983, 5487983]:

    • @workflow/world-vercel@4.1.0-beta.33
    • @workflow/errors@4.1.0-beta.16
    • @workflow/world@4.1.0-beta.5
    • @workflow/world-local@4.1.0-beta.33

4.1.0-beta.57

4.1.0-beta.56

Patch Changes

  • #1015 c56dc38 Thanks @TooTallNate! - Extract browser-safe serialization format from @workflow/core and split o11y hydration by environment. Data hydration now happens client-side in the browser, enabling future e2e encryption support.

  • #990 d7d005b Thanks @TooTallNate! - Allow @ in workflow names to support scoped packages

  • #1011 8d117cd Thanks @pranaygp! - Retry 5xx errors from workflow-server in step handler to avoid consuming step attempts on transient infrastructure errors

  • #1020 63caf93 Thanks @TooTallNate! - Add format prefix and length-prefix framing to stream chunks for consistent serialization with step inputs/outputs. Backwards compatible with legacy newline-delimited streams.

  • #992 dc2dc6a Thanks @ijjk! - stop esbuild bundling for deferred step route in Next.js

  • Updated dependencies [63caf93]:

    • @workflow/world-local@4.1.0-beta.32

4.1.0-beta.55

Patch Changes

  • #998 3d770d5 Thanks @ijjk! - Expose workflows manifest under diagnostics folder

  • #976 a5935ab Thanks @ijjk! - Add lazy workflow/step discovery via deferredEntries in next

  • #989 fc4cad6 Thanks @karthikscale3! - Normalize errors cleanly so objects get destructured

  • #966 56f2221 Thanks @VaguelySerious! - Add 429 throttle retry handling and 500 server error retry with exponential backoff to the workflow and step runtimes

  • Updated dependencies [3d770d5, 56f2221]:

    • @workflow/utils@4.1.0-beta.12
    • @workflow/errors@4.1.0-beta.15
    • @workflow/world@4.1.0-beta.4
    • @workflow/world-vercel@4.1.0-beta.32
    • @workflow/world-local@4.1.0-beta.31

4.1.0-beta.54

Patch Changes

  • #924 fcfaf8b Thanks @TooTallNate! - Set stepId property on function in registerStepFunction for serialization support

  • #954 d9e9859 Thanks @TooTallNate! - Generate runId client-side in start() and simplify runId types

    The runId is now generated client-side using ULID before serialization, rather than waiting for the server response. This simplifies the Streamer interface and WorkflowServerWritableStream to accept string instead of string | Promise<string> for runId.

  • #951 f7fd88e Thanks @VaguelySerious! - Tidy health check latency calculation

  • Updated dependencies [d9e9859, aa448c2]:

    • @workflow/world@4.1.0-beta.3
    • @workflow/world-vercel@4.1.0-beta.31
    • @workflow/errors@4.1.0-beta.14
    • @workflow/world-local@4.1.0-beta.30

4.1.0-beta.53

Patch Changes

  • #922 0ce46b9 Thanks @pranaygp! - Add support for custom headers in queue messages

  • #927 f090de1 Thanks @karthikscale3! - Added subpatch exports for runtime modules to allow direct imports in core. Refactored web-shared to be a thin package that exported UI components and world-actions. Updated web package to consume the UI components and world-actions from web-shared.

  • #933 79e988f Thanks @pranaygp! - Add OTEL tracing for event loading and queue timing breakdown using standard OTEL semantic conventions

  • #867 c54ba21 Thanks @TooTallNate! - Add optional writeToStreamMulti function to the World interface

  • #935 e0061b8 Thanks @pranaygp! - Improve logging: consolidate to structured logger, fix log levels, ensure errors/warnings are always visible

  • #873 38e8d55 Thanks @TooTallNate! - Ensure class serialization / deserialization only happens in the proper global context

  • #932 088de0a Thanks @pranaygp! - Improve OpenTelemetry tracing instrumentation

    • Add W3C trace context headers to step queue messages for cross-service trace linking
    • Add peer.service and RPC semantic conventions for external service attribution
    • Add step.hydrate and step.dehydrate spans for argument serialization visibility
    • Add workflow.replay span for workflow event replay tracking
    • Rename queueMessage span to queue.publish following OTEL messaging conventions
    • Add OTEL baggage propagation for workflow context (workflow.run_id, workflow.name)
    • Add span events for milestones: retry.scheduled, step.skipped, step.delayed
    • Enhance error telemetry with recordException() and error categorization (fatal/retryable/transient)
    • Use uppercase span names (WORKFLOW, STEP) for consistency with HTTP spans
    • Add world-local OTEL instrumentation matching world-vercel
  • #947 efb33b2 Thanks @TooTallNate! - Pass class as this context to custom serializer/deserializer methods

  • #932 088de0a Thanks @pranaygp! - Optimize step handler performance and improve server-side validation

    • Skip initial world.steps.get() call in step handler (saves one HTTP round-trip)
    • Add server-side retryAfter validation to local and postgres worlds (HTTP 425 when not reached)
    • Fix HTTP status code for step terminal state: return 409 (Conflict) instead of 410
    • Fix race condition: await step_started event before hydration to ensure correct attempt count
  • Updated dependencies [0ce46b9, c54ba21, 088de0a, 088de0a, 79e988f, 088de0a]:

    • @workflow/world@4.1.0-beta.2
    • @workflow/world-vercel@4.1.0-beta.30
    • @workflow/world-local@4.1.0-beta.29
    • @workflow/errors@4.1.0-beta.14

4.1.0-beta.52

Patch Changes

  • #916 e4e3281 Thanks @VaguelySerious! - Fix circular dependency between runtime.ts and runtime/start.ts that caused issues with Bun's module resolution

4.1.0-beta.51

Minor Changes

  • #621 4966b72 Thanks @pranaygp! - BREAKING: Storage interface is now read-only; all mutations go through events.create()
    • Remove cancel, pause, resume from runs
    • Remove create, update from runs, steps, hooks
    • Add run lifecycle events: run_created, run_started, run_completed, run_failed, run_cancelled
    • Add step_created event type
    • Remove fatal field from step_failed (terminal failure is now implicit)
    • Add step_retrying event with error info for retriable failures

Patch Changes

  • #621 4966b72 Thanks @pranaygp! - Runtime uses event-sourced entity creation

    • Suspension handler creates entities via events.create()
    • Track hasCreatedEvent flag to avoid duplicate event creation on replay
    • Handle hook_conflict events during replay to reject duplicate token hooks
  • #894 a2b688d Thanks @VaguelySerious! - Fix resuming v1 hooks and cancelling/re-running v1 runs from a v2 UI or runtime

  • #884 1f684df Thanks @TooTallNate! - Add a format identifier prefix for serialized data

  • #814 b16a682 Thanks @TooTallNate! - Move "parse-name" into the utils package

  • #833 bd8116d Thanks @TooTallNate! - Remove skipProxy and baseUrl config options, simplify proxy logic

  • #853 1060f9d Thanks @TooTallNate! - BREAKING CHANGE: Change user input/output to be binary data (Uint8Array) at the World interface

    This is part of specVersion 2 changes where serialization of workflow and step data uses binary format instead of JSON arrays. This allows the workflow client to be fully responsible for the data serialization format and enables future enhancements such as encryption and compression without the World implementation needing to care about the underlying data representation.

  • #855 00c7961 Thanks @TooTallNate! - Remove unused getWritable stub function

  • #868 c45bc3f Thanks @pranaygp! - Add SDK version to workflow run executionContext for observability

  • Updated dependencies [4966b72, 26a9833, b59559b, 4966b72, a2b688d, 4966b72, b16a682, bd8116d, 1060f9d, 4966b72, 4966b72, b973b8d, 57f6376, 60a9b76, 4966b72, 4966b72]:

    • @workflow/world@4.1.0-beta.1
    • @workflow/world-local@4.1.0-beta.28
    • @workflow/errors@4.1.0-beta.14
    • @workflow/world-vercel@4.1.0-beta.29
    • @workflow/serde@4.1.0-beta.2
    • @workflow/utils@4.1.0-beta.11

4.0.1-beta.41

Patch Changes

4.0.1-beta.40

Patch Changes

4.0.1-beta.39

Patch Changes

4.0.1-beta.38

Patch Changes

4.0.1-beta.37

Patch Changes

  • #743 61fdb41 Thanks @TooTallNate! - Add queue-based health check feature

  • #773 3dd5b27 Thanks @TooTallNate! - Make resumeHook() accept a Hook object or string

  • #776 49f650c Thanks @Timer! - Fix race condition where step would stay pending forever if process crashed between database write and queue write

  • #678 39e5774 Thanks @TooTallNate! - Fix stream serialization to resolve when user releases lock instead of waiting for stream to close. This prevents Vercel functions from hanging when users incrementally write to streams within steps (e.g., await writer.write(data); writer.releaseLock()). Uses a polling approach to detect when the stream lock is released and all pending writes are flushed.

  • Updated dependencies [61fdb41, 0aa835f]:

    • @workflow/world@4.0.1-beta.13
    • @workflow/errors@4.0.1-beta.13
    • @workflow/world-local@4.0.1-beta.26
    • @workflow/world-vercel@4.0.1-beta.27

4.0.1-beta.36

Patch Changes

  • Updated dependencies [dd3db13]:
    • @workflow/world@4.0.1-beta.12
    • @workflow/world-local@4.0.1-beta.25
    • @workflow/world-vercel@4.0.1-beta.26
    • @workflow/errors@4.0.1-beta.13

4.0.1-beta.35

Patch Changes

4.0.1-beta.34

Patch Changes

  • #703 9b1640d Thanks @TooTallNate! - Do not include initial attempt in step function maxRetries count

  • #712 307f4b0 Thanks @ijjk! - Revert lazy workflow and step discovery

  • Updated dependencies [9b1640d]:

    • @workflow/utils@4.0.1-beta.10
    • @workflow/errors@4.0.1-beta.13
    • @workflow/world-local@4.0.1-beta.24
    • @workflow/world-vercel@4.0.1-beta.25

4.0.1-beta.33

Patch Changes

  • Updated dependencies [2dbe494]:
    • @workflow/world-local@4.0.1-beta.23

4.0.1-beta.32

Patch Changes

  • #455 e3f0390 Thanks @karthikscale3! - Added Control Flow Graph extraction from Workflows and extended manifest.json's schema to incorporate the graph structure into it. Refactored manifest generation to pass manifest as a parameter instead of using instance state. Add e2e tests for manifest validation across all builders.

  • Updated dependencies [e3f0390]:

    • @workflow/world-local@4.0.1-beta.22
    • @workflow/utils@4.0.1-beta.9
    • @workflow/world@4.0.1-beta.11
    • @workflow/errors@4.0.1-beta.12
    • @workflow/world-vercel@4.0.1-beta.24

4.0.1-beta.31

Patch Changes

  • #624 25b02b0 Thanks @VaguelySerious! - Add CORS headers to endpoints health check response

  • Updated dependencies [d9f6a49, 0cf0ac3, c3464bf]:

    • @workflow/world-local@4.0.1-beta.21
    • @workflow/utils@4.0.1-beta.8
    • @workflow/errors@4.0.1-beta.11
    • @workflow/world-vercel@4.0.1-beta.23

4.0.1-beta.30

Patch Changes

  • Updated dependencies [f2d5997]:
    • @workflow/world-local@4.0.1-beta.20

4.0.1-beta.29

Patch Changes

4.0.1-beta.28

Patch Changes

  • #544 ea2a67e Thanks @pranaygp! - perf: parallelize suspension handler and refactor runtime

    • Process hooks first, then steps and waits in parallel to prevent race conditions
    • Refactor runtime.ts into modular files: suspension-handler.ts, step-handler.ts, helpers.ts
    • Add otel attributes for hooks created (workflow.hooks.created) and waits created (workflow.waits.created)
    • Update suspension status from pending_steps to workflow_suspended
  • #625 712f6f8 Thanks @VaguelySerious! - Change serialized stream names from v4 UUIDs to ULIDs

  • Updated dependencies [ce7d428, 712f6f8, ab55ba2, 4bdd3e5]:

    • @workflow/world-local@4.0.1-beta.19
    • @workflow/world-vercel@4.0.1-beta.21
    • @workflow/errors@4.0.1-beta.10

4.0.1-beta.27

Patch Changes

  • #627 deaf019 Thanks @VaguelySerious! - [world-vercel] Allow skipping vercel backend proxy for e2e tests where CLI runs in runtime env

  • #505 b56aae3 Thanks @copilot-swe-agent! - Override setTimeout, setInterval, and related functions in workflow VM context to throw helpful errors suggesting to use sleep instead

  • #613 4d7a393 Thanks @TooTallNate! - Add workflow endpoints health check query parameter

  • Updated dependencies [1ef6b2f, deaf019, b56aae3]:

    • @workflow/utils@4.0.1-beta.7
    • @workflow/world-vercel@4.0.1-beta.20
    • @workflow/errors@4.0.1-beta.9
    • @workflow/world-local@4.0.1-beta.18

4.0.1-beta.26

Patch Changes

  • #588 696e7e3 Thanks @VaguelySerious! - Fix rare case where workflows get stuck due to edge case in step update logic

  • Updated dependencies [c9b8d84]:

    • @workflow/world-local@4.0.1-beta.17
    • @workflow/utils@4.0.1-beta.6
    • @workflow/errors@4.0.1-beta.8
    • @workflow/world-vercel@4.0.1-beta.19

4.0.1-beta.25

Patch Changes

  • #575 161c54c Thanks @VaguelySerious! - Add Web and CLI UI for listing and viewing streams

  • #541 0bbd26f Thanks @pranaygp! - perf: use Map for invocationsQueue (O(1) lookup/delete)

    Replace array-based invocationsQueue with Map for O(1) lookup and delete operations, eliminating O(n²) complexity in high-concurrency workflows.

  • #567 c35b445 Thanks @Schniz! - otel: do not treat WorkflowSuspension errors as errors in the trace, as they symbolize effects and not actual exceptions.

  • #571 d3fd81d Thanks @TooTallNate! - Enhance serialization failure error reporting

  • Updated dependencies [d42a968, c82b467]:

    • @workflow/world-local@4.0.1-beta.16
    • @workflow/world-vercel@4.0.1-beta.18
    • @workflow/world@4.0.1-beta.10
    • @workflow/errors@4.0.1-beta.7

4.0.1-beta.24

Patch Changes

  • Updated dependencies [48b3a12]
  • Updated dependencies [57a2c32]
    • @workflow/world-local@4.0.1-beta.15
    • @workflow/world@4.0.1-beta.9
    • @workflow/errors@4.0.1-beta.7
    • @workflow/world-vercel@4.0.1-beta.17

4.0.1-beta.23

Patch Changes

  • Updated dependencies [c8fa70a]
    • @workflow/world-vercel@4.0.1-beta.16

4.0.1-beta.22

Patch Changes

  • 02c41cc: Set UI name of default-export-workflows to the filename, instead of "__default"

4.0.1-beta.21

Patch Changes

  • 2f0840b: Better error when passing an invalid workflow value to start()
  • Updated dependencies [e9494d5]
    • @workflow/world-vercel@4.0.1-beta.15

4.0.1-beta.20

Patch Changes

  • 0f1645b: Ignore rejections in waitedUntil promise
  • bdde1bd: track queue overhead with opentelemetry
  • 8d4562e: Rename leftover references to "embedded world" to be "local world"
  • Updated dependencies [bc9b628]
  • Updated dependencies [34f3f86]
  • Updated dependencies [cd451e0]
  • Updated dependencies [6e8e828]
  • Updated dependencies [10c5b91]
  • Updated dependencies [bdde1bd]
  • Updated dependencies [2faddf3]
  • Updated dependencies [8d4562e]
    • @workflow/utils@4.0.1-beta.5
    • @workflow/world-local@4.0.1-beta.14
    • @workflow/world@4.0.1-beta.8
    • @workflow/errors@4.0.1-beta.7
    • @workflow/world-vercel@4.0.1-beta.14

4.0.1-beta.19

Patch Changes

  • 07800c2: Support closure variables for serialized step functions
  • fb9fd0f: Add support for closure scope vars in step functions
  • Updated dependencies [fb9fd0f]
  • Updated dependencies [40057db]
    • @workflow/world@4.0.1-beta.7
    • @workflow/world-local@4.0.1-beta.13
    • @workflow/errors@4.0.1-beta.6
    • @workflow/world-vercel@4.0.1-beta.13

4.0.1-beta.18

Patch Changes

  • Updated dependencies [6889dac]
    • @workflow/world-vercel@4.0.1-beta.12

4.0.1-beta.17

Patch Changes

  • Updated dependencies [2c438c3]
  • Updated dependencies [edb69c3]
    • @workflow/world-vercel@4.0.1-beta.11
    • @workflow/world-local@4.0.1-beta.12
    • @workflow/utils@4.0.1-beta.4
    • @workflow/errors@4.0.1-beta.6

4.0.1-beta.16

Patch Changes

  • 3436629: Fix bugs in streamer (empty chunk handling and cloning chunks)
  • 9961140: Fix hydration of eventData for sleep calls
  • 73b6c68: Remove suppressUndefinedRejection from BaseBuilder
  • Updated dependencies [3436629]
    • @workflow/world-local@4.0.1-beta.11

4.0.1-beta.15

Patch Changes

  • 3d99d6d: Update @vercel/oidc and @vercel/queue to fix expired OIDC token edge case
  • Updated dependencies [3d99d6d]
    • @workflow/world-vercel@4.0.1-beta.10
    • @workflow/world-local@5.0.0-beta.10

4.0.1-beta.14

Patch Changes

  • 6e41c90: Allow step retrying if it fails without proper cleanup

4.0.1-beta.13

Patch Changes

  • 2fde24e: Use inline sourcemaps to prevent SWC read import error
  • 4b70739: Require specifying runId when writing to stream
  • Updated dependencies [4b70739]
    • @workflow/world-vercel@4.0.1-beta.9
    • @workflow/world-local@5.0.0-beta.9
    • @workflow/world@4.0.1-beta.6
    • @workflow/errors@4.0.1-beta.5

4.0.1-beta.12

Patch Changes

  • 5eb588a: Remove step function identifier transform out of swc-plugin and into useStep() runtime function

  • 00b0bb9: Implement the world's structured error interface

  • 85ce8e0: add waitUntil wrapping for toplevel commands for transaction-like behavior

    when deployed on Vercel or other serverless providers, we must signal that we need to wait until operations are done before the function can halt the request.

    This means that we can't rely on discrete operations (like Queue.queue or Storage calls), and instead wrap the entire start function (which calls multiple discrete operations) in a single await waitUntil call.

  • b97b6bf: Lock all dependencies in our packages

  • f8e5d10: Support serializing step function references

  • 6be03f3: Use "stepId" instead of Symbol.for("STEP_FUNCTION_NAME_SYMBOL") for annotating step functions

  • f07b2da: Transform step functions to single useStep() calls

  • Updated dependencies [aa015af]

  • Updated dependencies [00b0bb9]

  • Updated dependencies [b97b6bf]

  • Updated dependencies [00b0bb9]

  • Updated dependencies [00b0bb9]

  • Updated dependencies [00b0bb9]

  • Updated dependencies [79480f2]

    • @workflow/world-local@5.0.0-beta.8
    • @workflow/world-vercel@4.0.1-beta.8
    • @workflow/errors@4.0.1-beta.5
    • @workflow/utils@4.0.1-beta.3
    • @workflow/world@4.0.1-beta.5

4.0.1-beta.11

Patch Changes

  • 8208b53: Fix sourcemap error tracing in workflows
  • aac1b6c: Make process.env in workflow context a readonly clone
  • 6373ab5: BREAKING: resumeHook() now throws errors (including when a Hook is not found for a given "token") instead of returning null
  • Updated dependencies [2b880f9]
  • Updated dependencies [2dca0d4]
  • Updated dependencies [68363b2]
    • @workflow/world-local@4.0.1-beta.7
    • @workflow/world-vercel@4.0.1-beta.7

4.0.1-beta.10

Patch Changes

  • 7013f29: BREAKING: Change RetryableError "retryAfter" option number value to represent milliseconds instead of seconds. Previously, numeric values were interpreted as seconds; now they are interpreted as milliseconds. This aligns with JavaScript conventions for durations (like setTimeout and setInterval).
  • a28bc37: Make @standard-schema/spec be a regular dependency
  • 809e0fe: Add support for specifying milliseconds in sleep()
  • adf0cfe: Add automatic port discovery
  • 5c0268b: Add Standard Schema support and runtime validation to defineHook()
  • 0b3e89e: Fix event data serialization for observability
  • 7a47eb8: Deprecate deploymentId in StartOptions with warning that it should not be set by users
  • Updated dependencies [bf170ad]
  • Updated dependencies [adf0cfe]
    • @workflow/utils@4.0.1-beta.2
    • @workflow/world-local@4.0.1-beta.6
    • @workflow/errors@4.0.1-beta.4
    • @workflow/world-vercel@4.0.1-beta.6

4.0.1-beta.9

Patch Changes

  • 9f56434: Add support for getWritable directly in step functions

4.0.1-beta.8

Patch Changes

  • 4a821fc: Fix Windows path handling by normalizing backslashes to forward slashes in workflow IDs

4.0.1-beta.7

Patch Changes

  • 05714f7: Add sveltekit workflow integration
  • Updated dependencies [05714f7]
    • @workflow/world-local@4.0.1-beta.5

4.0.1-beta.6

Patch Changes

  • 10309c3: Downgrade @types/node to v22.19.0
  • f973954: Update license to Apache 2.0
  • Updated dependencies [10309c3]
  • Updated dependencies [f973954]
    • @workflow/world-local@4.0.1-beta.4
    • @workflow/world-vercel@4.0.1-beta.5
    • @workflow/errors@4.0.1-beta.3
    • @workflow/world@4.0.1-beta.4

4.0.1-beta.5

Patch Changes

  • 796fafd: Remove isInstanceOf() function and utilize is() method on Error subclasses instead
  • 70be894: Implement sleep() natively into the workflow runtime
  • 20d51f0: Respect the retryAfter property in the step function callback handler
  • Updated dependencies [20d51f0]
  • Updated dependencies [796fafd]
  • Updated dependencies [20d51f0]
  • Updated dependencies [20d51f0]
  • Updated dependencies [70be894]
    • @workflow/world-vercel@4.0.1-beta.4
    • @workflow/errors@4.0.1-beta.2
    • @workflow/world-local@4.0.1-beta.3
    • @workflow/world@4.0.1-beta.3

4.0.1-beta.4

Patch Changes

  • 6504e42: Add support for bigint serialization
  • Updated dependencies [e367046]
    • @workflow/world-vercel@4.0.1-beta.3

4.0.1-beta.3

Patch Changes

  • 57419e5: Improve type-safety to start when no args are provided
  • Updated dependencies [d3a4ed3]
  • Updated dependencies [d3a4ed3]
  • Updated dependencies [66225bf]
  • Updated dependencies [7868434]
    • @workflow/world@4.0.1-beta.2
    • @workflow/world-local@4.0.1-beta.2
    • @workflow/world-vercel@4.0.1-beta.2

4.0.1-beta.2

Patch Changes

  • 854feb4: Handle multiple step_started events in event log
  • f1c6bc5: Throw an error when the event log is corrupted

4.0.1-beta.1

Patch Changes

  • 57ebfcb: Fix seedrandom not being listed in dependencies
  • 1408293: Add "description" field to package.json file
  • e46294f: Add "license" and "repository" fields to package.json file
  • Updated dependencies [1408293]
  • Updated dependencies [8422a32]
  • Updated dependencies [e46294f]
    • @workflow/world-vercel@4.0.1-beta.1
    • @workflow/world-local@4.0.1-beta.1
    • @workflow/errors@4.0.1-beta.1
    • @workflow/world@4.0.1-beta.1

4.0.1-beta.0

Patch Changes

  • fcf63d0: Initial publish
  • Updated dependencies [fcf63d0]
    • @workflow/world-vercel@4.0.1-beta.0
    • @workflow/world-local@4.0.1-beta.0
    • @workflow/errors@4.0.1-beta.0
    • @workflow/world@4.0.1-beta.0