workflow 5.0.0-beta.9 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/README.md +68 -23
  2. package/dist/api-workflow.d.ts +3 -1
  3. package/dist/api-workflow.d.ts.map +1 -1
  4. package/dist/api-workflow.js +2 -1
  5. package/dist/api.d.ts +5 -4
  6. package/dist/api.d.ts.map +1 -1
  7. package/dist/api.js +6 -7
  8. package/dist/index.d.ts +1 -0
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +6 -1
  11. package/dist/internal/builtins.d.ts +4 -4
  12. package/dist/internal/builtins.js +6 -6
  13. package/dist/internal/errors.d.ts +1 -1
  14. package/dist/internal/errors.d.ts.map +1 -1
  15. package/dist/internal/errors.js +2 -2
  16. package/dist/nest-builder.d.ts +2 -0
  17. package/dist/nest-builder.d.ts.map +1 -0
  18. package/dist/nest-builder.js +2 -0
  19. package/dist/nest-vercel-builder.d.ts +2 -0
  20. package/dist/nest-vercel-builder.d.ts.map +1 -0
  21. package/dist/nest-vercel-builder.js +2 -0
  22. package/dist/runtime.d.ts +2 -1
  23. package/dist/runtime.d.ts.map +1 -1
  24. package/dist/runtime.js +4 -1
  25. package/docs/advanced/dynamic-workflows.mdx +224 -0
  26. package/docs/ai/chat-session-modeling.mdx +176 -422
  27. package/docs/ai/defining-tools.mdx +6 -7
  28. package/docs/ai/human-in-the-loop.mdx +11 -11
  29. package/docs/ai/index.mdx +67 -72
  30. package/docs/ai/message-queueing.mdx +71 -110
  31. package/docs/ai/meta.json +1 -0
  32. package/docs/ai/resumable-streams.mdx +40 -28
  33. package/docs/ai/sleep-and-delays.mdx +10 -10
  34. package/docs/ai/streaming-updates-from-tools.mdx +6 -6
  35. package/docs/api-reference/index.mdx +25 -1
  36. package/docs/api-reference/meta.json +8 -0
  37. package/docs/api-reference/vitest/index.mdx +68 -15
  38. package/docs/api-reference/workflow/create-hook.mdx +166 -10
  39. package/docs/api-reference/workflow/create-webhook.mdx +16 -15
  40. package/docs/api-reference/workflow/define-hook.mdx +37 -33
  41. package/docs/api-reference/workflow/fatal-error.mdx +30 -8
  42. package/docs/api-reference/workflow/fetch.mdx +14 -10
  43. package/docs/api-reference/workflow/get-step-metadata.mdx +2 -2
  44. package/docs/api-reference/workflow/get-workflow-metadata.mdx +3 -3
  45. package/docs/api-reference/workflow/get-writable.mdx +7 -7
  46. package/docs/api-reference/workflow/index.mdx +3 -3
  47. package/docs/api-reference/workflow/retryable-error.mdx +1 -1
  48. package/docs/api-reference/workflow/set-attributes.mdx +63 -0
  49. package/docs/api-reference/workflow/sleep.mdx +4 -4
  50. package/docs/api-reference/workflow-ai/durable-agent.mdx +63 -101
  51. package/docs/api-reference/workflow-ai/index.mdx +5 -5
  52. package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +67 -24
  53. package/docs/api-reference/workflow-api/get-hook-by-token.mdx +28 -12
  54. package/docs/api-reference/workflow-api/get-run.mdx +43 -8
  55. package/docs/api-reference/workflow-api/index.mdx +8 -9
  56. package/docs/api-reference/workflow-api/register-lifecycle-hooks.mdx +87 -0
  57. package/docs/api-reference/workflow-api/resume-hook.mdx +73 -12
  58. package/docs/api-reference/workflow-api/resume-webhook.mdx +11 -9
  59. package/docs/api-reference/workflow-api/start.mdx +107 -12
  60. package/docs/api-reference/workflow-astro/index.mdx +18 -0
  61. package/docs/api-reference/workflow-astro/meta.json +4 -0
  62. package/docs/api-reference/workflow-astro/workflow.mdx +45 -0
  63. package/docs/api-reference/workflow-errors/entity-conflict-error.mdx +4 -4
  64. package/docs/api-reference/workflow-errors/hook-conflict-error.mdx +60 -0
  65. package/docs/api-reference/workflow-errors/hook-force-claimed-error.mdx +70 -0
  66. package/docs/api-reference/workflow-errors/hook-not-found-error.mdx +8 -8
  67. package/docs/api-reference/workflow-errors/index.mdx +91 -0
  68. package/docs/api-reference/workflow-errors/meta.json +7 -0
  69. package/docs/api-reference/workflow-errors/precondition-failed-error.mdx +68 -0
  70. package/docs/api-reference/workflow-errors/run-expired-error.mdx +2 -2
  71. package/docs/api-reference/workflow-errors/run-not-supported-error.mdx +58 -0
  72. package/docs/api-reference/workflow-errors/step-not-registered-error.mdx +5 -5
  73. package/docs/api-reference/workflow-errors/throttle-error.mdx +2 -2
  74. package/docs/api-reference/workflow-errors/too-early-error.mdx +2 -2
  75. package/docs/api-reference/workflow-errors/workflow-error.mdx +52 -0
  76. package/docs/api-reference/workflow-errors/workflow-not-registered-error.mdx +5 -6
  77. package/docs/api-reference/workflow-errors/workflow-run-cancelled-error.mdx +13 -6
  78. package/docs/api-reference/workflow-errors/workflow-run-failed-error.mdx +12 -5
  79. package/docs/api-reference/workflow-errors/workflow-run-not-completed-error.mdx +58 -0
  80. package/docs/api-reference/workflow-errors/workflow-run-not-found-error.mdx +4 -4
  81. package/docs/api-reference/workflow-errors/workflow-runtime-error.mdx +58 -0
  82. package/docs/api-reference/workflow-errors/workflow-world-error.mdx +8 -8
  83. package/docs/api-reference/workflow-globals.mdx +15 -11
  84. package/docs/api-reference/workflow-nest/configure-workflow-controller.mdx +37 -0
  85. package/docs/api-reference/workflow-nest/index.mdx +31 -0
  86. package/docs/api-reference/workflow-nest/meta.json +9 -0
  87. package/docs/api-reference/workflow-nest/nest-local-builder.mdx +64 -0
  88. package/docs/api-reference/workflow-nest/workflow-controller.mdx +46 -0
  89. package/docs/api-reference/workflow-nest/workflow-module.mdx +134 -0
  90. package/docs/api-reference/workflow-next/with-workflow.mdx +39 -17
  91. package/docs/api-reference/workflow-nitro/index.mdx +60 -0
  92. package/docs/api-reference/workflow-nuxt/index.mdx +48 -0
  93. package/docs/api-reference/workflow-observability/hydrate-data.mdx +35 -0
  94. package/docs/api-reference/workflow-observability/hydrate-resource-io.mdx +62 -0
  95. package/docs/api-reference/workflow-observability/index.mdx +62 -0
  96. package/docs/api-reference/workflow-observability/meta.json +11 -0
  97. package/docs/api-reference/workflow-observability/observability-revivers.mdx +50 -0
  98. package/docs/api-reference/workflow-observability/parse-class-name.mdx +41 -0
  99. package/docs/api-reference/workflow-observability/parse-step-name.mdx +40 -0
  100. package/docs/api-reference/workflow-observability/parse-workflow-name.mdx +55 -0
  101. package/docs/api-reference/workflow-runtime/create-world.mdx +39 -0
  102. package/docs/api-reference/workflow-runtime/get-world-handlers.mdx +44 -0
  103. package/docs/api-reference/{workflow-api → workflow-runtime}/get-world.mdx +11 -14
  104. package/docs/api-reference/workflow-runtime/health-check.mdx +51 -0
  105. package/docs/api-reference/workflow-runtime/index.mdx +41 -0
  106. package/docs/api-reference/workflow-runtime/meta.json +12 -0
  107. package/docs/api-reference/workflow-runtime/set-world.mdx +51 -0
  108. package/docs/api-reference/workflow-runtime/workflow-entrypoint.mdx +43 -0
  109. package/docs/api-reference/workflow-runtime/world/analytics.mdx +315 -0
  110. package/docs/api-reference/workflow-runtime/world/index.mdx +60 -0
  111. package/docs/api-reference/workflow-runtime/world/meta.json +4 -0
  112. package/docs/api-reference/workflow-runtime/world/queue.mdx +88 -0
  113. package/docs/api-reference/{workflow-api → workflow-runtime}/world/storage.mdx +104 -35
  114. package/docs/api-reference/{workflow-api → workflow-runtime}/world/streams.mdx +8 -8
  115. package/docs/api-reference/workflow-serde/index.mdx +1 -2
  116. package/docs/api-reference/workflow-serde/workflow-deserialize.mdx +3 -4
  117. package/docs/api-reference/workflow-serde/workflow-serialize.mdx +8 -8
  118. package/docs/api-reference/workflow-sveltekit/index.mdx +18 -0
  119. package/docs/api-reference/workflow-sveltekit/meta.json +4 -0
  120. package/docs/api-reference/workflow-sveltekit/workflow-plugin.mdx +42 -0
  121. package/docs/api-reference/workflow-vite/index.mdx +18 -0
  122. package/docs/api-reference/workflow-vite/meta.json +4 -0
  123. package/docs/api-reference/workflow-vite/workflow.mdx +48 -0
  124. package/docs/changelog/attributes-mvp.mdx +53 -41
  125. package/docs/changelog/batched-event-writes.mdx +79 -0
  126. package/docs/changelog/eager-processing.mdx +110 -436
  127. package/docs/changelog/index.mdx +4 -2
  128. package/docs/changelog/lazy-event-creation.md +127 -0
  129. package/docs/changelog/lazy-hook-resume.mdx +78 -0
  130. package/docs/changelog/meta.json +11 -1
  131. package/docs/changelog/resilient-resume.mdx +32 -0
  132. package/docs/changelog/resilient-start.mdx +33 -285
  133. package/docs/changelog/step-message-ownership.mdx +360 -0
  134. package/docs/changelog/turbo-mode.md +87 -0
  135. package/docs/comparisons/index.mdx +66 -0
  136. package/docs/comparisons/meta.json +11 -0
  137. package/docs/comparisons/workflow-sdk-vs-aws-agentcore.mdx +55 -0
  138. package/docs/comparisons/workflow-sdk-vs-aws-step-functions.mdx +111 -0
  139. package/docs/comparisons/workflow-sdk-vs-cloudflare-workflows.mdx +71 -0
  140. package/docs/comparisons/workflow-sdk-vs-inngest.mdx +102 -0
  141. package/docs/comparisons/workflow-sdk-vs-temporal.mdx +123 -0
  142. package/docs/comparisons/workflow-sdk-vs-trigger-dev.mdx +104 -0
  143. package/docs/configuration/build-and-diagnostics.mdx +79 -0
  144. package/docs/configuration/cli-and-web-ui.mdx +241 -0
  145. package/docs/configuration/framework-options.mdx +165 -0
  146. package/docs/configuration/index.mdx +32 -0
  147. package/docs/configuration/meta.json +12 -0
  148. package/docs/configuration/runtime-tuning.mdx +399 -0
  149. package/docs/configuration/worlds.mdx +315 -0
  150. package/docs/cookbook/advanced/child-workflows.mdx +33 -25
  151. package/docs/cookbook/advanced/publishing-libraries.mdx +65 -56
  152. package/docs/cookbook/advanced/serializable-steps.mdx +48 -68
  153. package/docs/cookbook/advanced/upgrading-workflows.mdx +35 -31
  154. package/docs/cookbook/agent-patterns/agent-cancellation.mdx +78 -60
  155. package/docs/cookbook/agent-patterns/durable-agent.mdx +23 -135
  156. package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +180 -195
  157. package/docs/cookbook/common-patterns/batching.mdx +20 -14
  158. package/docs/cookbook/common-patterns/idempotency.mdx +41 -53
  159. package/docs/cookbook/common-patterns/rate-limiting.mdx +8 -4
  160. package/docs/cookbook/common-patterns/saga.mdx +23 -19
  161. package/docs/cookbook/common-patterns/scheduling.mdx +30 -22
  162. package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +29 -25
  163. package/docs/cookbook/common-patterns/timeouts.mdx +26 -21
  164. package/docs/cookbook/common-patterns/webhooks.mdx +10 -6
  165. package/docs/cookbook/common-patterns/workflow-composition.mdx +27 -17
  166. package/docs/cookbook/index.mdx +22 -22
  167. package/docs/cookbook/integrations/ai-sdk.mdx +63 -48
  168. package/docs/cookbook/integrations/chat-sdk.mdx +46 -33
  169. package/docs/cookbook/integrations/sandbox.mdx +58 -45
  170. package/docs/deploying.mdx +106 -0
  171. package/docs/errors/abort-signal-timeout-in-workflow.mdx +16 -12
  172. package/docs/errors/corrupted-event-log.mdx +39 -18
  173. package/docs/errors/deployment-mismatch.mdx +71 -0
  174. package/docs/errors/fetch-in-workflow.mdx +15 -14
  175. package/docs/errors/hook-conflict.mdx +38 -11
  176. package/docs/errors/hook-force-claimed.mdx +96 -0
  177. package/docs/errors/index.mdx +24 -37
  178. package/docs/errors/node-js-module-in-workflow.mdx +9 -5
  179. package/docs/errors/replay-divergence.mdx +27 -0
  180. package/docs/errors/run-expired.mdx +85 -0
  181. package/docs/errors/runtime-decryption-failed.mdx +77 -0
  182. package/docs/errors/serialization-failed.mdx +44 -12
  183. package/docs/errors/start-invalid-workflow-function.mdx +9 -5
  184. package/docs/errors/step-executed-multiple-times.mdx +23 -0
  185. package/docs/errors/step-not-registered.mdx +6 -6
  186. package/docs/errors/timeout-in-workflow.mdx +12 -8
  187. package/docs/errors/webhook-invalid-respond-with-value.mdx +18 -18
  188. package/docs/errors/webhook-response-not-sent.mdx +20 -16
  189. package/docs/errors/workflow-not-registered.mdx +5 -5
  190. package/docs/foundations/cancellation.mdx +31 -32
  191. package/docs/foundations/errors-and-retries.mdx +54 -11
  192. package/docs/foundations/hooks.mdx +98 -35
  193. package/docs/foundations/idempotency.mdx +267 -12
  194. package/docs/foundations/index.mdx +1 -26
  195. package/docs/foundations/serialization.mdx +22 -22
  196. package/docs/foundations/starting-workflows.mdx +104 -30
  197. package/docs/foundations/streaming.mdx +108 -60
  198. package/docs/foundations/versioning.mdx +4 -4
  199. package/docs/foundations/workflows-and-steps.mdx +9 -9
  200. package/docs/getting-started/astro.mdx +22 -18
  201. package/docs/getting-started/express.mdx +15 -11
  202. package/docs/getting-started/fastify.mdx +15 -11
  203. package/docs/getting-started/hono.mdx +15 -11
  204. package/docs/getting-started/index.mdx +10 -3
  205. package/docs/getting-started/meta.json +3 -1
  206. package/docs/getting-started/nestjs.mdx +264 -21
  207. package/docs/getting-started/next.mdx +18 -14
  208. package/docs/getting-started/nitro.mdx +22 -18
  209. package/docs/getting-started/nuxt.mdx +15 -11
  210. package/docs/getting-started/python.mdx +190 -41
  211. package/docs/getting-started/react-router/index.mdx +33 -0
  212. package/docs/getting-started/react-router/meta.json +5 -0
  213. package/docs/getting-started/react-router/v7.mdx +237 -0
  214. package/docs/getting-started/react-router/v8.mdx +232 -0
  215. package/docs/getting-started/sveltekit.mdx +20 -16
  216. package/docs/getting-started/tanstack-start.mdx +17 -13
  217. package/docs/getting-started/vite.mdx +15 -11
  218. package/docs/how-it-works/cancellation.mdx +63 -63
  219. package/docs/how-it-works/code-transform.mdx +82 -66
  220. package/docs/how-it-works/encryption.mdx +30 -26
  221. package/docs/how-it-works/event-sourcing.mdx +132 -35
  222. package/docs/how-it-works/framework-integrations.mdx +96 -337
  223. package/docs/how-it-works/understanding-directives.mdx +22 -22
  224. package/docs/internal/index.mdx +6 -4
  225. package/docs/internal/meta.json +6 -1
  226. package/docs/internal/nitro-native-build.mdx +38 -0
  227. package/docs/internal/nitro-web-ui.mdx +24 -0
  228. package/docs/internal/serializable-abort-controller.mdx +7 -7
  229. package/docs/meta.json +4 -2
  230. package/docs/observability/attributes.mdx +91 -21
  231. package/docs/observability/index.mdx +29 -15
  232. package/docs/observability/lifecycle-hooks.mdx +95 -0
  233. package/docs/observability/meta.json +1 -1
  234. package/docs/observability/retention.mdx +95 -0
  235. package/docs/observability/tracing.mdx +124 -0
  236. package/docs/testing/index.mdx +120 -38
  237. package/docs/testing/server-based.mdx +10 -10
  238. package/docs/whats-new.mdx +190 -0
  239. package/docs/worlds/building-a-world.mdx +538 -0
  240. package/docs/worlds/local.mdx +129 -0
  241. package/docs/worlds/meta.json +10 -0
  242. package/docs/worlds/postgres.mdx +424 -0
  243. package/docs/worlds/upgrading-to-v5.mdx +162 -0
  244. package/docs/worlds/vercel.mdx +345 -0
  245. package/package.json +17 -14
  246. package/docs/api-reference/workflow/experimental-set-attributes.mdx +0 -63
  247. package/docs/api-reference/workflow-api/world/index.mdx +0 -58
  248. package/docs/api-reference/workflow-api/world/meta.json +0 -4
  249. package/docs/api-reference/workflow-api/world/observability.mdx +0 -164
  250. package/docs/api-reference/workflow-api/world/queue.mdx +0 -86
  251. package/docs/deploying/building-a-world.mdx +0 -251
  252. package/docs/deploying/index.mdx +0 -95
  253. package/docs/deploying/meta.json +0 -4
  254. package/docs/deploying/world/local-world.mdx +0 -84
  255. package/docs/deploying/world/meta.json +0 -4
  256. package/docs/deploying/world/postgres-world.mdx +0 -224
  257. package/docs/deploying/world/vercel-world.mdx +0 -181
  258. package/docs/migration-guides/index.mdx +0 -34
  259. package/docs/migration-guides/meta.json +0 -9
  260. package/docs/migration-guides/migrating-from-aws-step-functions.mdx +0 -358
  261. package/docs/migration-guides/migrating-from-inngest.mdx +0 -304
  262. package/docs/migration-guides/migrating-from-temporal.mdx +0 -313
  263. package/docs/migration-guides/migrating-from-trigger-dev.mdx +0 -328
@@ -15,11 +15,11 @@ All function arguments and return values passed between workflow and step functi
15
15
  The serialization system ensures that all data persists correctly across workflow suspensions and resumptions, enabling durable execution.
16
16
  </Callout>
17
17
 
18
- ## Supported Serializable Types
18
+ ## Supported serializable types
19
19
 
20
20
  The following types can be serialized and passed through workflow functions:
21
21
 
22
- **Standard JSON Types:**
22
+ **Standard JSON types:**
23
23
 
24
24
  - `string`
25
25
  - `number`
@@ -28,12 +28,13 @@ The following types can be serialized and passed through workflow functions:
28
28
  - Arrays of serializable values
29
29
  - Objects with string keys and serializable values
30
30
 
31
- **Extended Types:**
31
+ **Extended types:**
32
32
 
33
33
  - `undefined`
34
34
  - `bigint`
35
35
  - `ArrayBuffer`
36
36
  - `BigInt64Array`, `BigUint64Array`
37
+ - `DataView`
37
38
  - `Date`
38
39
  - `Float32Array`, `Float64Array`
39
40
  - `Int8Array`, `Int16Array`, `Int32Array`
@@ -58,7 +59,7 @@ These types have special handling and are explained in detail in the sections be
58
59
  - `AbortController`
59
60
  - `AbortSignal`
60
61
 
61
- ## Pass-by-Value Semantics
62
+ ## Pass-by-value semantics
62
63
 
63
64
  **Parameters are passed by value, not by reference.** Steps receive deserialized copies of data. Mutations inside a step won't affect the original in the workflow.
64
65
 
@@ -81,7 +82,7 @@ async function updateUserStep(user: { id: string; name: string; email: string })
81
82
  }
82
83
  ```
83
84
 
84
- **Correct - return the modified data:**
85
+ **Correct, return the modified data:**
85
86
 
86
87
  ```typescript title="workflows/correct-mutation.ts" lineNumbers
87
88
  export async function updateUserWorkflow(userId: string) {
@@ -100,7 +101,7 @@ async function updateUserStep(user: { id: string; name: string; email: string })
100
101
  }
101
102
  ```
102
103
 
103
- **Custom Classes:**
104
+ **Custom classes:**
104
105
 
105
106
  - Class instances that implement [`WORKFLOW_SERIALIZE` and `WORKFLOW_DESERIALIZE`](#custom-class-serialization)
106
107
 
@@ -110,7 +111,7 @@ async function updateUserStep(user: { id: string; name: string; email: string })
110
111
 
111
112
  For complete information about using streams in workflows, including patterns for AI streaming, file processing, and progress updates, see the [Streaming Guide](/docs/foundations/streaming).
112
113
 
113
- ## Request & Response
114
+ ## Request & response
114
115
 
115
116
  The Web API [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) APIs are supported by the serialization system,
116
117
  and can be passed around between workflow and step functions similarly to other data types.
@@ -140,7 +141,7 @@ export async function handleWebhookWorkflow() {
140
141
  }
141
142
  ```
142
143
 
143
- ### Using `fetch` in Workflows
144
+ ### Using `fetch` in workflows
144
145
 
145
146
  Because `Request` and `Response` are serializable, Workflow SDK provides a `fetch` function that can be used directly in workflow functions:
146
147
 
@@ -158,7 +159,7 @@ export async function apiWorkflow() {
158
159
  }
159
160
  ```
160
161
 
161
- The implementation is straightforward - `fetch` from workflow is a step function that wraps the standard `fetch`:
162
+ The `fetch` implementation from `workflow` is a step function that wraps the standard `fetch`:
162
163
 
163
164
  ```typescript title="Implementation" lineNumbers
164
165
  export async function fetch(...args: Parameters<typeof globalThis.fetch>) {
@@ -202,11 +203,11 @@ async function fetchData(signal: AbortSignal) {
202
203
 
203
204
  For usage patterns including timeouts, parallel cancellation, user-triggered cancellation, and run cancellation, see the [Cancellation Guide](/docs/foundations/cancellation). For details on the hook and stream backing that makes this work, see [How Cancellation Works](/docs/how-it-works/cancellation).
204
205
 
205
- ## Custom Class Serialization
206
+ ## Custom class serialization
206
207
 
207
208
  By default, custom class instances cannot be serialized because the serialization system doesn't know how to reconstruct them. You can make your classes serializable by implementing two static methods using special symbols from the `@workflow/serde` package.
208
209
 
209
- ### Basic Example
210
+ ### Basic example
210
211
 
211
212
  {/* @expect-error:2351 */}
212
213
 
@@ -256,13 +257,13 @@ async function doublePoint(point: Point) {
256
257
  }
257
258
  ```
258
259
 
259
- ### How It Works
260
+ ### How it works
260
261
 
261
262
  1. **`WORKFLOW_SERIALIZE`**: A static method that receives a class instance and returns serializable data (primitives, plain objects, arrays, etc.)
262
263
 
263
264
  2. **`WORKFLOW_DESERIALIZE`**: A static method that receives the serialized data and returns a new class instance
264
265
 
265
- 3. **Automatic Registration**: The SWC compiler plugin automatically detects classes that implement these symbols and registers them for serialization. Each class receives a deterministic `classId` derived from its file path and class name, and is registered into the global `Symbol.for("workflow-class-registry")` registry at build time — no manual registration step is required
266
+ 3. **Automatic Registration**: The SWC compiler plugin automatically detects classes that implement these symbols and registers them for serialization. Each class receives a deterministic `classId` derived from its file path and class name, and is registered into the global `Symbol.for("workflow-class-registry")` registry at build time. No manual registration step is required
266
267
 
267
268
  ### Requirements
268
269
 
@@ -279,12 +280,12 @@ The `WORKFLOW_SERIALIZE` and `WORKFLOW_DESERIALIZE` methods run inside the workf
279
280
  - No non-deterministic operations (like `Math.random()` or `Date.now()`)
280
281
  - No external network calls
281
282
 
282
- Keep these methods simple and focused on data transformation only.
283
+ Keep these methods focused on data transformation only.
283
284
  </Callout>
284
285
 
285
- ### Instance Methods as Steps
286
+ ### Instance methods as steps
286
287
 
287
- In practice, many classes have methods that need Node.js APIs, perform network calls, or interact with databases — operations that are not allowed in the `"use workflow"` execution context. You can make these methods workflow-compatible by adding `"use step"` to them. The SWC compiler will strip the method bodies from the workflow bundle and replace them with proxy functions that invoke the method as a step — with full Node.js runtime access. The `this` context (the class instance) is automatically serialized and deserialized across the workflow/step boundary.
288
+ In practice, many classes have methods that need Node.js APIs, perform network calls, or interact with databases, operations that are not allowed in the `"use workflow"` execution context. You can make these methods workflow-compatible by adding `"use step"` to them. The SWC compiler will strip the method bodies from the workflow bundle and replace them with proxy functions that invoke the method as a step, with full Node.js runtime access. The `this` context (the class instance) is automatically serialized and deserialized across the workflow/step boundary.
288
289
 
289
290
  This requires the class to implement `WORKFLOW_SERIALIZE` and `WORKFLOW_DESERIALIZE`, so that the instance can be passed to the step execution context.
290
291
 
@@ -301,7 +302,7 @@ class Order {
301
302
  public createdAt: Date
302
303
  ) {}
303
304
 
304
- // Custom serialization — data must be serializable types
305
+ // Custom serialization: data must be serializable types
305
306
  static [WORKFLOW_SERIALIZE](instance: Order) { // [!code highlight]
306
307
  return { // [!code highlight]
307
308
  id: instance.id, // [!code highlight]
@@ -329,7 +330,7 @@ class Order {
329
330
  }
330
331
 
331
332
  // Instance methods with "use step" run as step functions
332
- // with full Node.js access — `this` is automatically serialized
333
+ // with full Node.js access; `this` is automatically serialized
333
334
  async save(): Promise<void> {
334
335
  "use step"; // [!code highlight]
335
336
  await db.orders.insert({ // [!code highlight]
@@ -355,7 +356,7 @@ class Order {
355
356
  }
356
357
  ```
357
358
 
358
- The class can then be used naturally inside a workflow function. Instance methods marked with `"use step"` are each executed as a step — with automatic caching, retry semantics, and full Node.js runtime access. Methods _without_ `"use step"` run directly in the workflow context, so they must follow the same constraints as workflow functions:
359
+ The class can then be used naturally inside a workflow function. Instance methods marked with `"use step"` are each executed as a step, with automatic caching, retry semantics, and full Node.js runtime access. Methods _without_ `"use step"` run directly in the workflow context, so they must follow the same constraints as workflow functions:
359
360
 
360
361
  {/* @expect-error:2693 */}
361
362
 
@@ -369,7 +370,7 @@ export async function processOrderWorkflow(
369
370
 
370
371
  const order = new Order(orderId, items, new Date()); // [!code highlight]
371
372
 
372
- // Runs in the workflow context — no "use step" needed
373
+ // Runs in the workflow context; no "use step" needed
373
374
  const itemCount = order.total(); // [!code highlight]
374
375
 
375
376
  // Each "use step" instance method call runs as a separate step
@@ -380,7 +381,7 @@ export async function processOrderWorkflow(
380
381
  }
381
382
  ```
382
383
 
383
- Note that [pass-by-value semantics](#pass-by-value-semantics) also apply to the `this` context of `"use step"` instance methods. Modifying instance properties inside a step method will not affect the original instance in the workflow. If you need to update instance state, return `this` from the step method and re-assign the variable in the workflow:
384
+ [Pass-by-value semantics](#pass-by-value-semantics) also apply to the `this` context of `"use step"` instance methods. Modifying instance properties inside a step method will not affect the original instance in the workflow. If you need to update instance state, return `this` from the step method and re-assign the variable in the workflow:
384
385
 
385
386
  {/* @expect-error:2351 */}
386
387
 
@@ -408,4 +409,3 @@ export async function processOrderWorkflow() {
408
409
  order = await order.addItem("Widget", 3); // [!code highlight]
409
410
  }
410
411
  ```
411
-
@@ -1,5 +1,5 @@
1
1
  ---
2
- title: Starting Workflows
2
+ title: Starting workflows
3
3
  description: Trigger workflow execution with the start() function and track progress with Run objects.
4
4
  type: guide
5
5
  summary: Trigger workflows and track their execution using the start() function.
@@ -9,11 +9,11 @@ related:
9
9
  - /docs/api-reference/workflow-api/start
10
10
  ---
11
11
 
12
- Once you've defined your workflow functions, you need to trigger them to begin execution. This is done using the `start()` function from `workflow/api`, which enqueues a new workflow run and returns a `Run` object that you can use to track its progress.
12
+ After you define a workflow function, use the `start()` function from `workflow/api` to trigger it. The function enqueues a new workflow run and returns a `Run` object for tracking its progress.
13
13
 
14
- ## The `start()` Function
14
+ ## The `start()` function
15
15
 
16
- The [`start()`](/docs/api-reference/workflow-api/start) function is used to programmatically trigger workflow executions from runtime contexts like API routes, Server Actions, or any server-side code. In v5, you can also call `start()` from inside a workflow function when you want to spawn a child run or continue work in a new run.
16
+ The [`start()`](/docs/api-reference/workflow-api/start) function programmatically triggers workflow executions from runtime contexts such as API routes, Server Actions, or other server-side code. In v5, you can also call `start()` inside a workflow function to spawn a child run or continue work in a new run.
17
17
 
18
18
  ```typescript lineNumbers
19
19
  import { start } from "workflow/api";
@@ -32,20 +32,21 @@ export async function POST(request: Request) {
32
32
  }
33
33
  ```
34
34
 
35
- **Key Points:**
35
+ **Key points:**
36
36
 
37
- - `start()` returns immediately after enqueuing the workflow - it doesn't wait for completion
37
+ - `start()` returns immediately after enqueuing the workflow. It doesn't wait for completion
38
38
  - The first argument is your workflow function
39
39
  - The second argument is an array of arguments to pass to the workflow (optional if the workflow takes no arguments)
40
40
  - All arguments must be [serializable](/docs/foundations/serialization)
41
+ - On Worlds with a regional dimension, the optional `region` option pins the new run's storage, queuing, and streams to a specific region. See [Multi-region on the Vercel World](/worlds/vercel#multi-region)
41
42
 
42
- **Learn more**: [`start()` API Reference](/docs/api-reference/workflow-api/start)
43
+ **Learn more**: [`start()` API reference](/docs/api-reference/workflow-api/start)
43
44
 
44
45
  <Callout type="info">
45
46
  For parent-child workflow patterns, see [Workflow Composition](/cookbook/common-patterns/workflow-composition). For long-lived workflows that intentionally hand off to newer deployments with `deploymentId: "latest"`, see [Versioning](/docs/foundations/versioning).
46
47
  </Callout>
47
48
 
48
- ## The `Run` Object
49
+ ## The `Run` object
49
50
 
50
51
  When you call `start()`, it returns a [`Run`](/docs/api-reference/workflow-api/start#returns) object that provides access to the workflow's status and results.
51
52
 
@@ -65,24 +66,55 @@ const status = await run.status; // "running" | "completed" | "failed"
65
66
  const result = await run.returnValue;
66
67
  ```
67
68
 
68
- **Key Properties:**
69
+ **Key properties:**
69
70
 
70
- - `runId` - Unique identifier for this workflow run
71
- - `status` - Current status of the workflow (async)
72
- - `returnValue` - The value returned by the workflow function (async, blocks until completion)
73
- - `readable` - ReadableStream for streaming updates from the workflow
71
+ - `runId`: Unique identifier for this workflow run
72
+ - `status`: Current status of the workflow (async)
73
+ - `returnValue`: The value returned by the workflow function (async, blocks until completion)
74
+ - `readable`: `ReadableStream` for streaming updates from the workflow
74
75
 
75
76
  <Callout type="info">
76
- Most `Run` properties are async getters that return promises. You need to `await` them to get their values. For a complete list of properties and methods, see the API reference below.
77
+ Most `Run` properties are async getters that return promises. `await` them to get their values. For a complete list of properties and methods, see the API reference below.
77
78
  </Callout>
78
79
 
79
- **Learn more**: [`Run` API Reference](/docs/api-reference/workflow-api/start#returns)
80
+ **Learn more**: [`Run` API reference](/docs/api-reference/workflow-api/start#returns)
80
81
 
81
- ## Common Patterns
82
+ ## Common patterns
82
83
 
83
- ### Fire and Forget
84
+ ### Starting workflows from workflow functions
84
85
 
85
- The most common pattern is to start a workflow and immediately return, letting it execute in the background:
86
+ You can also call `start()` directly inside workflow functions to spawn child workflows. For choosing between this and awaiting a workflow function directly, see [Workflow Composition](/cookbook/common-patterns/workflow-composition).
87
+
88
+ ```typescript lineNumbers
89
+ import { start } from "workflow/api";
90
+ import { childWorkflow } from "./workflows/child";
91
+
92
+ export async function parentWorkflow(inputValue: number) {
93
+ "use workflow";
94
+
95
+ const childRun = await start(childWorkflow, [inputValue]); // [!code highlight]
96
+
97
+ // childRun is a full Run object. Use it like normal.
98
+ const childResult = await childRun.returnValue;
99
+ return { childRunId: childRun.runId, childResult };
100
+ }
101
+ ```
102
+
103
+ When you call `start()` inside a workflow function, it automatically executes through an internal step to maintain deterministic replay. The returned `Run` object works as it does outside workflows. Properties such as `.runId`, `.status`, and `.returnValue`, and methods such as `.cancel()`, are all available. Each property access or method call executes as a separate step.
104
+
105
+ If the child run fails or is canceled, `await childRun.returnValue` throws [`WorkflowRunFailedError`](/docs/api-reference/workflow-errors/workflow-run-failed-error) or [`WorkflowRunCancelledError`](/docs/api-reference/workflow-errors/workflow-run-cancelled-error) on the first attempt.
106
+
107
+ <Callout type="info">
108
+ Inside workflow functions, each `Run` property access (e.g., `run.status`, `run.returnValue`) triggers a workflow step. This means each access is recorded in the event log and replayed deterministically.
109
+ </Callout>
110
+
111
+ <Callout type="warn">
112
+ Awaiting `returnValue` polls the child run every second, and the polling step holds its worker slot open until the child finishes. Size worker-based Worlds to cover the peak number of these polls in flight. If the child workflow is long-running, spawn it without awaiting `returnValue` and have it resume a [hook](/docs/foundations/hooks) when it completes. See the [`startAndWait()` pattern](/cookbook/advanced/child-workflows).
113
+ </Callout>
114
+
115
+ ### Fire and forget
116
+
117
+ Start a workflow and immediately return to let it execute in the background:
86
118
 
87
119
  ```typescript lineNumbers
88
120
  import { start } from "workflow/api";
@@ -100,7 +132,7 @@ export async function POST(request: Request) {
100
132
  }
101
133
  ```
102
134
 
103
- ### Wait for Completion
135
+ ### Wait for completion
104
136
 
105
137
  If you need to wait for the workflow to complete before responding:
106
138
 
@@ -119,12 +151,12 @@ export async function POST(request: Request) {
119
151
  ```
120
152
 
121
153
  <Callout type="warn">
122
- Be cautious when waiting for `returnValue` - if your workflow takes a long time, your API route may timeout.
154
+ Waiting for `returnValue` can cause your API route to time out if the workflow takes a long time.
123
155
  </Callout>
124
156
 
125
- ### Stream Updates to Client
157
+ ### Stream updates to client
126
158
 
127
- Stream real-time updates from your workflow as it executes, without waiting for completion:
159
+ Stream updates from your workflow as it executes without waiting for completion:
128
160
 
129
161
  ```typescript lineNumbers
130
162
  import { start } from "workflow/api";
@@ -148,7 +180,7 @@ export async function POST(request: Request) {
148
180
  }
149
181
  ```
150
182
 
151
- Your workflow can obtain a writable stream using [`getWritable()`](/docs/api-reference/workflow/get-writable):
183
+ Your workflow can write to the stream using [`getWritable()`](/docs/api-reference/workflow/get-writable):
152
184
 
153
185
  ```typescript lineNumbers
154
186
  import { getWritable } from "workflow";
@@ -182,12 +214,12 @@ async function streamContentToClient(
182
214
  ```
183
215
 
184
216
  <Callout type="info">
185
- Streams are particularly useful for AI workflows where you want to show progress to users in real-time, or for long-running processes that produce intermediate results.
217
+ Use streams to show users real-time progress from AI workflows or intermediate results from long-running processes.
186
218
  </Callout>
187
219
 
188
- **Learn more**: [Streaming in Workflows](/docs/foundations/serialization#streaming)
220
+ **Learn more**: [Streaming in workflows](/docs/foundations/serialization#streaming)
189
221
 
190
- ### Check Status Later
222
+ ### Check status later
191
223
 
192
224
  You can retrieve a workflow run later using its `runId` with [`getRun()`](/docs/api-reference/workflow-api/get-run):
193
225
 
@@ -213,10 +245,52 @@ export async function GET(request: Request) {
213
245
  }
214
246
  ```
215
247
 
216
- ## Next Steps
248
+ ### Recursive and repeating workflows
249
+
250
+ A workflow can start a new instance of itself. This pattern prevents a single long-running workflow from accumulating too many events. Large event logs are slower to replay, more expensive to store, and harder to inspect in the UI. Breaking work into smaller runs that chain together keeps each run lean.
251
+
252
+ ```typescript lineNumbers
253
+ import { start } from "workflow/api";
254
+ declare function fetchBatch(cursor?: string): Promise<{ items: string[]; nextCursor?: string }>; // @setup
255
+ declare function processBatch(items: string[]): Promise<void>; // @setup
256
+
257
+ export async function processQueue(cursor?: string) {
258
+ "use workflow";
259
+
260
+ const { items, nextCursor } = await fetchBatch(cursor);
261
+ await processBatch(items);
262
+
263
+ if (nextCursor) {
264
+ // Continue processing in a new workflow run
265
+ await start(processQueue, [nextCursor]); // [!code highlight]
266
+ }
267
+ }
268
+ ```
269
+
270
+ This pattern also enables **repeating cron-like workflows**. A workflow can complete its work, sleep, and then schedule a new instance of itself. This creates an indefinite chain without allowing any single run to grow too large:
271
+
272
+ ```typescript lineNumbers
273
+ import { sleep } from "workflow";
274
+ import { start } from "workflow/api";
275
+ declare function refreshMetrics(): Promise<void>; // @setup
276
+
277
+ export async function syncDashboard() {
278
+ "use workflow";
279
+
280
+ await refreshMetrics();
281
+ await sleep("1h");
282
+
283
+ // Schedule the next run
284
+ await start(syncDashboard); // [!code highlight]
285
+ }
286
+ ```
287
+
288
+ #### Starting against the latest deployment
289
+
290
+ By default a chained run starts on the same deployment as its parent. For workflows that chain over long periods, pass [`deploymentId: "latest"`](/docs/api-reference/workflow-api/start#using-deploymentid-latest) so the next run picks up new code. [Versioning](/docs/foundations/versioning#self-upgrading-workflows) covers this pattern in full, including how the serialized state acts as the migration boundary between versions.
217
291
 
218
- Now that you understand how to start workflows and track their execution:
292
+ ## Next steps
219
293
 
220
294
  - Browse the [Cookbook](/cookbook) for copy-paste recipes covering composition, scheduling, timeouts, and more
221
- - Explore [Errors & Retrying](/docs/foundations/errors-and-retries) to handle failures gracefully
222
- - Check the [`start()` API Reference](/docs/api-reference/workflow-api/start) for complete details
295
+ - Explore [Errors and retrying](/docs/foundations/errors-and-retries) to handle failures
296
+ - Check the [`start()` API reference](/docs/api-reference/workflow-api/start) for complete details