workflow 5.0.0-beta.4 → 5.0.0-beta.40

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 (227) hide show
  1. package/README.md +63 -20
  2. package/dist/api-workflow.d.ts +1 -1
  3. package/dist/api-workflow.d.ts.map +1 -1
  4. package/dist/api-workflow.js +1 -1
  5. package/dist/api.d.ts +5 -1
  6. package/dist/api.d.ts.map +1 -1
  7. package/dist/api.js +12 -2
  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 +17 -0
  12. package/dist/internal/builtins.d.ts.map +1 -1
  13. package/dist/internal/builtins.js +65 -1
  14. package/dist/internal/errors.d.ts +1 -1
  15. package/dist/internal/errors.d.ts.map +1 -1
  16. package/dist/internal/errors.js +2 -2
  17. package/dist/nest-builder.d.ts +2 -0
  18. package/dist/nest-builder.d.ts.map +1 -0
  19. package/dist/nest-builder.js +2 -0
  20. package/dist/nest-vercel-builder.d.ts +2 -0
  21. package/dist/nest-vercel-builder.d.ts.map +1 -0
  22. package/dist/nest-vercel-builder.js +2 -0
  23. package/dist/observability.d.ts +1 -1
  24. package/dist/observability.js +2 -2
  25. package/dist/runtime.d.ts +2 -1
  26. package/dist/runtime.d.ts.map +1 -1
  27. package/dist/runtime.js +5 -2
  28. package/docs/ai/chat-session-modeling.mdx +7 -3
  29. package/docs/ai/defining-tools.mdx +2 -2
  30. package/docs/ai/index.mdx +30 -25
  31. package/docs/ai/message-queueing.mdx +10 -10
  32. package/docs/ai/resumable-streams.mdx +9 -1
  33. package/docs/api-reference/index.mdx +24 -0
  34. package/docs/api-reference/meta.json +8 -0
  35. package/docs/api-reference/vitest/index.mdx +28 -7
  36. package/docs/api-reference/workflow/create-hook.mdx +79 -0
  37. package/docs/api-reference/workflow/create-webhook.mdx +1 -0
  38. package/docs/api-reference/workflow/define-hook.mdx +26 -24
  39. package/docs/api-reference/workflow/fatal-error.mdx +29 -7
  40. package/docs/api-reference/workflow/fetch.mdx +8 -4
  41. package/docs/api-reference/workflow/index.mdx +3 -0
  42. package/docs/api-reference/workflow/set-attributes.mdx +61 -0
  43. package/docs/api-reference/workflow/sleep.mdx +1 -1
  44. package/docs/api-reference/workflow-ai/durable-agent.mdx +7 -45
  45. package/docs/api-reference/workflow-ai/index.mdx +2 -2
  46. package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +44 -1
  47. package/docs/api-reference/workflow-api/get-hook-by-token.mdx +9 -0
  48. package/docs/api-reference/workflow-api/get-run.mdx +25 -0
  49. package/docs/api-reference/workflow-api/index.mdx +6 -8
  50. package/docs/api-reference/workflow-api/resume-hook.mdx +60 -1
  51. package/docs/api-reference/workflow-api/resume-webhook.mdx +6 -4
  52. package/docs/api-reference/workflow-api/start.mdx +39 -6
  53. package/docs/api-reference/workflow-astro/index.mdx +18 -0
  54. package/docs/api-reference/workflow-astro/meta.json +4 -0
  55. package/docs/api-reference/workflow-astro/workflow.mdx +45 -0
  56. package/docs/api-reference/workflow-errors/hook-conflict-error.mdx +60 -0
  57. package/docs/api-reference/workflow-errors/index.mdx +88 -0
  58. package/docs/api-reference/workflow-errors/meta.json +6 -0
  59. package/docs/api-reference/workflow-errors/precondition-failed-error.mdx +68 -0
  60. package/docs/api-reference/workflow-errors/run-not-supported-error.mdx +58 -0
  61. package/docs/api-reference/workflow-errors/workflow-error.mdx +52 -0
  62. package/docs/api-reference/workflow-errors/workflow-run-failed-error.mdx +16 -6
  63. package/docs/api-reference/workflow-errors/workflow-run-not-completed-error.mdx +58 -0
  64. package/docs/api-reference/workflow-errors/workflow-runtime-error.mdx +58 -0
  65. package/docs/api-reference/workflow-globals.mdx +4 -1
  66. package/docs/api-reference/workflow-nest/configure-workflow-controller.mdx +33 -0
  67. package/docs/api-reference/workflow-nest/index.mdx +31 -0
  68. package/docs/api-reference/workflow-nest/meta.json +9 -0
  69. package/docs/api-reference/workflow-nest/nest-local-builder.mdx +64 -0
  70. package/docs/api-reference/workflow-nest/workflow-controller.mdx +40 -0
  71. package/docs/api-reference/workflow-nest/workflow-module.mdx +74 -0
  72. package/docs/api-reference/workflow-next/with-workflow.mdx +56 -2
  73. package/docs/api-reference/workflow-nitro/index.mdx +60 -0
  74. package/docs/api-reference/workflow-nuxt/index.mdx +48 -0
  75. package/docs/api-reference/workflow-observability/hydrate-data.mdx +35 -0
  76. package/docs/api-reference/workflow-observability/hydrate-resource-io.mdx +62 -0
  77. package/docs/api-reference/workflow-observability/index.mdx +64 -0
  78. package/docs/api-reference/workflow-observability/meta.json +11 -0
  79. package/docs/api-reference/workflow-observability/observability-revivers.mdx +50 -0
  80. package/docs/api-reference/workflow-observability/parse-class-name.mdx +41 -0
  81. package/docs/api-reference/workflow-observability/parse-step-name.mdx +40 -0
  82. package/docs/api-reference/workflow-observability/parse-workflow-name.mdx +55 -0
  83. package/docs/api-reference/workflow-runtime/create-world.mdx +39 -0
  84. package/docs/api-reference/workflow-runtime/get-world-handlers.mdx +44 -0
  85. package/docs/api-reference/{workflow-api → workflow-runtime}/get-world.mdx +7 -10
  86. package/docs/api-reference/workflow-runtime/health-check.mdx +50 -0
  87. package/docs/api-reference/workflow-runtime/index.mdx +43 -0
  88. package/docs/api-reference/workflow-runtime/meta.json +12 -0
  89. package/docs/api-reference/workflow-runtime/set-world.mdx +49 -0
  90. package/docs/api-reference/workflow-runtime/workflow-entrypoint.mdx +42 -0
  91. package/docs/api-reference/workflow-runtime/world/analytics.mdx +138 -0
  92. package/docs/api-reference/{workflow-api → workflow-runtime}/world/index.mdx +10 -10
  93. package/docs/api-reference/workflow-runtime/world/meta.json +4 -0
  94. package/docs/api-reference/{workflow-api → workflow-runtime}/world/queue.mdx +8 -6
  95. package/docs/api-reference/{workflow-api → workflow-runtime}/world/storage.mdx +18 -5
  96. package/docs/api-reference/{workflow-api → workflow-runtime}/world/streams.mdx +2 -2
  97. package/docs/api-reference/workflow-serde/index.mdx +0 -1
  98. package/docs/api-reference/workflow-serde/workflow-deserialize.mdx +1 -2
  99. package/docs/api-reference/workflow-serde/workflow-serialize.mdx +2 -2
  100. package/docs/api-reference/workflow-sveltekit/index.mdx +18 -0
  101. package/docs/api-reference/workflow-sveltekit/meta.json +4 -0
  102. package/docs/api-reference/workflow-sveltekit/workflow-plugin.mdx +42 -0
  103. package/docs/api-reference/workflow-vite/index.mdx +18 -0
  104. package/docs/api-reference/workflow-vite/meta.json +4 -0
  105. package/docs/api-reference/workflow-vite/workflow.mdx +48 -0
  106. package/docs/changelog/attributes-mvp.mdx +380 -0
  107. package/docs/changelog/eager-processing.mdx +269 -0
  108. package/docs/changelog/index.mdx +3 -1
  109. package/docs/changelog/lazy-event-creation.md +127 -0
  110. package/docs/changelog/meta.json +9 -1
  111. package/docs/changelog/resilient-resume.mdx +22 -0
  112. package/docs/changelog/resilient-start.mdx +31 -283
  113. package/docs/changelog/step-message-ownership.mdx +360 -0
  114. package/docs/changelog/turbo-mode.md +87 -0
  115. package/docs/comparisons/index.mdx +66 -0
  116. package/docs/comparisons/meta.json +11 -0
  117. package/docs/comparisons/workflow-sdk-vs-aws-agentcore.mdx +55 -0
  118. package/docs/comparisons/workflow-sdk-vs-aws-step-functions.mdx +111 -0
  119. package/docs/comparisons/workflow-sdk-vs-cloudflare-workflows.mdx +71 -0
  120. package/docs/comparisons/workflow-sdk-vs-inngest.mdx +102 -0
  121. package/docs/comparisons/workflow-sdk-vs-temporal.mdx +123 -0
  122. package/docs/comparisons/workflow-sdk-vs-trigger-dev.mdx +103 -0
  123. package/docs/configuration/build-and-diagnostics.mdx +70 -0
  124. package/docs/configuration/cli-and-web-ui.mdx +182 -0
  125. package/docs/configuration/framework-options.mdx +165 -0
  126. package/docs/configuration/index.mdx +32 -0
  127. package/docs/configuration/meta.json +12 -0
  128. package/docs/configuration/runtime-tuning.mdx +276 -0
  129. package/docs/configuration/worlds.mdx +275 -0
  130. package/docs/cookbook/advanced/child-workflows.mdx +203 -256
  131. package/docs/cookbook/advanced/meta.json +1 -1
  132. package/docs/cookbook/advanced/publishing-libraries.mdx +33 -24
  133. package/docs/cookbook/advanced/serializable-steps.mdx +12 -4
  134. package/docs/cookbook/advanced/upgrading-workflows.mdx +199 -0
  135. package/docs/cookbook/agent-patterns/agent-cancellation.mdx +34 -75
  136. package/docs/cookbook/agent-patterns/durable-agent.mdx +14 -142
  137. package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +11 -3
  138. package/docs/cookbook/common-patterns/batching.mdx +4 -0
  139. package/docs/cookbook/common-patterns/idempotency.mdx +40 -52
  140. package/docs/cookbook/common-patterns/rate-limiting.mdx +5 -1
  141. package/docs/cookbook/common-patterns/saga.mdx +6 -2
  142. package/docs/cookbook/common-patterns/scheduling.mdx +12 -0
  143. package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +4 -0
  144. package/docs/cookbook/common-patterns/timeouts.mdx +6 -1
  145. package/docs/cookbook/common-patterns/webhooks.mdx +4 -0
  146. package/docs/cookbook/common-patterns/workflow-composition.mdx +19 -16
  147. package/docs/cookbook/index.mdx +3 -3
  148. package/docs/cookbook/integrations/ai-sdk.mdx +64 -28
  149. package/docs/cookbook/integrations/chat-sdk.mdx +17 -0
  150. package/docs/cookbook/integrations/sandbox.mdx +17 -0
  151. package/docs/{deploying/index.mdx → deploying.mdx} +7 -7
  152. package/docs/errors/abort-signal-timeout-in-workflow.mdx +84 -0
  153. package/docs/errors/corrupted-event-log.mdx +5 -5
  154. package/docs/errors/deployment-mismatch.mdx +71 -0
  155. package/docs/errors/fetch-in-workflow.mdx +4 -0
  156. package/docs/errors/hook-conflict.mdx +60 -4
  157. package/docs/errors/index.mdx +1 -35
  158. package/docs/errors/node-js-module-in-workflow.mdx +4 -0
  159. package/docs/errors/replay-divergence.mdx +27 -0
  160. package/docs/errors/runtime-decryption-failed.mdx +77 -0
  161. package/docs/errors/serialization-failed.mdx +4 -0
  162. package/docs/errors/start-invalid-workflow-function.mdx +4 -0
  163. package/docs/errors/step-executed-multiple-times.mdx +23 -0
  164. package/docs/errors/step-not-registered.mdx +1 -1
  165. package/docs/errors/timeout-in-workflow.mdx +4 -0
  166. package/docs/errors/webhook-response-not-sent.mdx +4 -0
  167. package/docs/foundations/cancellation.mdx +459 -0
  168. package/docs/foundations/errors-and-retries.mdx +7 -3
  169. package/docs/foundations/hooks.mdx +29 -0
  170. package/docs/foundations/idempotency.mdx +243 -11
  171. package/docs/foundations/index.mdx +1 -23
  172. package/docs/foundations/meta.json +3 -1
  173. package/docs/foundations/serialization.mdx +77 -41
  174. package/docs/foundations/starting-workflows.mdx +79 -2
  175. package/docs/foundations/streaming.mdx +14 -23
  176. package/docs/foundations/versioning.mdx +263 -0
  177. package/docs/getting-started/astro.mdx +12 -2
  178. package/docs/getting-started/express.mdx +6 -2
  179. package/docs/getting-started/fastify.mdx +6 -2
  180. package/docs/getting-started/hono.mdx +6 -2
  181. package/docs/getting-started/index.mdx +16 -10
  182. package/docs/getting-started/meta.json +4 -1
  183. package/docs/getting-started/nestjs.mdx +77 -3
  184. package/docs/getting-started/next.mdx +12 -6
  185. package/docs/getting-started/nitro.mdx +28 -2
  186. package/docs/getting-started/nuxt.mdx +6 -2
  187. package/docs/getting-started/python.mdx +24 -18
  188. package/docs/getting-started/react-router/index.mdx +33 -0
  189. package/docs/getting-started/react-router/meta.json +5 -0
  190. package/docs/getting-started/react-router/v7.mdx +237 -0
  191. package/docs/getting-started/react-router/v8.mdx +232 -0
  192. package/docs/getting-started/sveltekit.mdx +12 -2
  193. package/docs/getting-started/tanstack-start.mdx +245 -0
  194. package/docs/getting-started/vite.mdx +6 -2
  195. package/docs/how-it-works/cancellation.mdx +287 -0
  196. package/docs/how-it-works/code-transform.mdx +21 -17
  197. package/docs/how-it-works/encryption.mdx +5 -5
  198. package/docs/how-it-works/event-sourcing.mdx +6 -6
  199. package/docs/how-it-works/framework-integrations.mdx +96 -337
  200. package/docs/how-it-works/meta.json +2 -1
  201. package/docs/internal/index.mdx +21 -0
  202. package/docs/internal/meta.json +10 -0
  203. package/docs/internal/nitro-native-build.mdx +38 -0
  204. package/docs/internal/nitro-web-ui.mdx +24 -0
  205. package/docs/internal/serializable-abort-controller.mdx +148 -0
  206. package/docs/meta.json +2 -2
  207. package/docs/observability/attributes.mdx +112 -0
  208. package/docs/observability/index.mdx +20 -1
  209. package/docs/observability/meta.json +1 -1
  210. package/docs/observability/tracing.mdx +124 -0
  211. package/docs/testing/index.mdx +2 -2
  212. package/package.json +17 -13
  213. package/docs/api-reference/workflow-api/world/meta.json +0 -4
  214. package/docs/api-reference/workflow-api/world/observability.mdx +0 -164
  215. package/docs/cookbook/advanced/distributed-abort-controller.mdx +0 -318
  216. package/docs/deploying/building-a-world.mdx +0 -251
  217. package/docs/deploying/meta.json +0 -4
  218. package/docs/deploying/world/local-world.mdx +0 -84
  219. package/docs/deploying/world/meta.json +0 -4
  220. package/docs/deploying/world/postgres-world.mdx +0 -222
  221. package/docs/deploying/world/vercel-world.mdx +0 -179
  222. package/docs/migration-guides/index.mdx +0 -34
  223. package/docs/migration-guides/meta.json +0 -9
  224. package/docs/migration-guides/migrating-from-aws-step-functions.mdx +0 -363
  225. package/docs/migration-guides/migrating-from-inngest.mdx +0 -314
  226. package/docs/migration-guides/migrating-from-temporal.mdx +0 -318
  227. package/docs/migration-guides/migrating-from-trigger-dev.mdx +0 -337
@@ -9,10 +9,15 @@ related:
9
9
  - /docs/foundations/workflows-and-steps
10
10
  ---
11
11
 
12
+ <CopyPrompt
13
+ text="In this NestJS app, run `npm i workflow @workflow/nest` and `npm i -D @swc/cli @swc/core`. Configure `nest-cli.json` with `compilerOptions.builder: &quot;swc&quot;` and `deleteOutDir: true`. Run `npx @workflow/nest init`, add `.swcrc` to `.gitignore`, and set package scripts `prebuild: &quot;npx @workflow/nest init --force&quot;` and `start:dev: &quot;npx @workflow/nest init --force && nest start --watch&quot;`. Import `WorkflowModule.forRoot()` from `@workflow/nest` in `src/app.module.ts` (use `{ moduleType: &quot;commonjs&quot;, distDir: &quot;dist&quot; }` if compiling CommonJS). Create `src/workflows/user-signup.ts` with `&quot;use workflow&quot;`, `sleep`, and `&quot;use step&quot;` helpers. Add a `POST /signup` controller method that reads `email`, calls `start(handleUserSignup, [email])` from `workflow/api`, and returns JSON. Run `npm run start:dev`, call `curl -X POST --json '{&quot;email&quot;:&quot;hello@example.com&quot;}' http://localhost:3000/signup`, and inspect with `npx workflow web` or `npx workflow inspect runs`."
14
+ />
15
+
12
16
  This guide will walk through setting up your first workflow in a NestJS app. Along the way, you'll learn more about the concepts that are fundamental to using the Workflow SDK in your own projects.
13
17
 
14
18
  <Callout>
15
- NestJS integration is experimental and not yet supported for deployment to Vercel.
19
+ NestJS integration is experimental. Deployment to Vercel is supported via the
20
+ `workflow-nest build --vercel` command — see [Deploy to Vercel](#deploy-to-vercel) below.
16
21
  </Callout>
17
22
 
18
23
  ---
@@ -284,7 +289,7 @@ async function sendOnboardingEmail(user: { id: string; email: string }) {
284
289
 
285
290
  Taking a look at this code:
286
291
 
287
- - Business logic lives inside **steps**. When a step is invoked inside a **workflow**, it gets enqueued to run on a separate request while the workflow is suspended, just like `sleep`.
292
+ - Business logic lives inside **steps**. When a workflow invokes a step, the workflow suspends while the step runs with full Node.js access. The combined handler may execute it inline; queued retries and continuations return through the same flow route.
288
293
  - If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count).
289
294
  - Steps can throw a `FatalError` if an error is intentional and should not be retried.
290
295
 
@@ -357,6 +362,66 @@ npx workflow inspect runs
357
362
 
358
363
  </Step>
359
364
 
365
+ <Step>
366
+
367
+ ## Deploy to Vercel
368
+
369
+ Because NestJS is not a Vercel-native framework, the Workflow SDK produces a
370
+ [Build Output API](https://vercel.com/docs/build-output-api) directory for you. This emits the
371
+ workflow queue-consumer function (registered with `experimentalTriggers` so Vercel's queue can
372
+ discover it) alongside your NestJS app as a catch-all function. Without it, workflow runs stay
373
+ `pending` because nothing consumes the queue.
374
+
375
+ Add a Vercel-specific entry module that default-exports your Nest app's underlying Node handler:
376
+
377
+ ```typescript title="_vercel/entry.ts" lineNumbers
378
+ import 'reflect-metadata';
379
+ import { NestFactory } from '@nestjs/core';
380
+ import type { NestExpressApplication } from '@nestjs/platform-express';
381
+ import express from 'express';
382
+ import { AppModule } from '../dist/app.module.js';
383
+
384
+ let ready: Promise<express.Express> | undefined;
385
+
386
+ async function createHandler() {
387
+ const app = await NestFactory.create<NestExpressApplication>(AppModule, {
388
+ bodyParser: false,
389
+ });
390
+ app.use(express.json());
391
+ await app.init();
392
+ return app.getHttpAdapter().getInstance();
393
+ }
394
+
395
+ export default async function handler(req: express.Request, res: express.Response) {
396
+ ready ??= createHandler();
397
+ return (await ready)(req, res);
398
+ }
399
+ ```
400
+
401
+ Skip the in-process build on Vercel (the bundles are pre-built) by passing `skipBuild` when
402
+ `VERCEL` is set:
403
+
404
+ {/* @skip-typecheck - config snippet, WorkflowModule imported above */}
405
+ ```typescript title="src/app.module.ts"
406
+ WorkflowModule.forRoot({ skipBuild: Boolean(process.env.VERCEL) });
407
+ ```
408
+
409
+ Then set your build command so the Build Output is produced after `nest build`:
410
+
411
+ ```json title="package.json" lineNumbers
412
+ {
413
+ "scripts": {
414
+ "vercel-build": "workflow-nest init --force && nest build && workflow-nest build --vercel --dirs src/workflows --entry _vercel/entry.ts"
415
+ }
416
+ }
417
+ ```
418
+
419
+ Deploy as usual. `workflow-nest build --vercel` runs automatically on Vercel (it also detects the
420
+ `VERCEL` environment variable), writing `.vercel/output` with the consumer function so your runs
421
+ execute instead of staying `pending`.
422
+
423
+ </Step>
424
+
360
425
  </Steps>
361
426
 
362
427
  ---
@@ -386,6 +451,15 @@ WorkflowModule.forRoot({
386
451
  // Only used when moduleType is 'commonjs'
387
452
  // Should match the outDir in your tsconfig.json
388
453
  distDir: 'dist',
454
+
455
+ // Source maps on generated workflow bundles (default: 'inline' in
456
+ // development, false in production).
457
+ // Accepts the same values as esbuild's sourcemap option: true, false,
458
+ // 'inline', 'linked', 'external', 'both'. Set to false for smaller
459
+ // function bundles (useful for staying under the Vercel 250MB function
460
+ // size limit) at the cost of stack traces pointing at generated code.
461
+ // Can also be set via the WORKFLOW_SOURCEMAP environment variable.
462
+ sourcemap: 'inline',
389
463
  });
390
464
  ```
391
465
 
@@ -396,7 +470,7 @@ WorkflowModule.forRoot({
396
470
  If you see this error:
397
471
 
398
472
  ```
399
- 'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive.
473
+ 'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
400
474
  ```
401
475
 
402
476
  Check both of these first:
@@ -7,9 +7,13 @@ prerequisites:
7
7
  - /docs/getting-started
8
8
  related:
9
9
  - /docs/api-reference/workflow-next
10
- - /docs/deploying/world/vercel-world
10
+ - /worlds/vercel
11
11
  ---
12
12
 
13
+ <CopyPrompt
14
+ text="In this Next.js app, run `npm i workflow`. Wrap `next.config.ts` with `withWorkflow` from `workflow/next`. If the app has `proxy.ts` or middleware, exclude `.well-known/workflow/` from its matcher. Add `workflows/user-signup.ts` exporting `handleUserSignup(email)` with `&quot;use workflow&quot;`, `sleep` from `workflow`, and `&quot;use step&quot;` helper functions that create a user, send a welcome email, and send an onboarding email. Add `app/api/signup/route.ts` with a POST handler that reads `{ email }`, calls `start(handleUserSignup, [email])` from `workflow/api`, and returns JSON. Run `npm run dev`, trigger `curl -X POST --json '{&quot;email&quot;:&quot;hello@example.com&quot;}' http://localhost:3000/api/signup`, and inspect with `npx workflow web` or `npx workflow inspect runs`."
15
+ />
16
+
13
17
  <Steps>
14
18
 
15
19
  <Step>
@@ -75,9 +79,9 @@ To enable helpful hints in your IDE, setup the workflow plugin in `tsconfig.json
75
79
  </Accordion>
76
80
 
77
81
  <Accordion type="single" collapsible>
78
- <AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
82
+ <AccordionItem value="configure-proxy-handler" className="[&_h3]:my-0">
79
83
  <AccordionTrigger className="text-sm">
80
- ### Configure Proxy Handler (if applicable)
84
+ <h3 id="configure-proxy-handler">Configure Proxy Handler (if applicable)</h3>
81
85
  </AccordionTrigger>
82
86
  <AccordionContent className="[&_p]:my-2">
83
87
 
@@ -85,7 +89,9 @@ If your Next.js app has a [proxy handler](https://nextjs.org/docs/app/api-refere
85
89
  (formerly known as "middleware"), you'll need to update the matcher pattern to exclude Workflow's
86
90
  internal paths to prevent the proxy handler from running on them.
87
91
 
88
- Add `.well-known/workflow/*` to your middleware's exclusion list:
92
+ If you see `[local world] Queue operation failed` with `Cannot perform ArrayBuffer.prototype.slice on a detached ArrayBuffer`, your proxy matcher is still intercepting Workflow's internal `POST /.well-known/workflow/v1/flow` request. This is especially easy to miss in Next.js 16, where `proxy.ts` replaced `middleware.ts`.
93
+
94
+ Add `.well-known/workflow/*` to your matcher exclusion list:
89
95
 
90
96
  ```typescript title="proxy.ts" lineNumbers
91
97
  import { NextResponse } from "next/server";
@@ -186,7 +192,7 @@ async function sendOnboardingEmail(user: { id: string; email: string}) {
186
192
 
187
193
  Taking a look at this code:
188
194
 
189
- * Business logic lives inside **steps**. When a step is invoked inside a **workflow**, it gets enqueued to run on a separate request while the workflow is suspended, just like `sleep`.
195
+ * Business logic lives inside **steps**. When a workflow invokes a step, the workflow suspends while the step runs with full Node.js access. The combined handler may execute it inline; queued retries and continuations return through the same flow route.
190
196
  * If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count).
191
197
  * Steps can throw a `FatalError` if an error is intentional and should not be retried.
192
198
 
@@ -310,7 +316,7 @@ Without this configuration, you may experience intermittent issues where workflo
310
316
  If you see this error:
311
317
 
312
318
  ```
313
- 'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive.
319
+ 'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
314
320
  ```
315
321
 
316
322
  Check both of these first:
@@ -9,6 +9,10 @@ related:
9
9
  - /docs/foundations/workflows-and-steps
10
10
  ---
11
11
 
12
+ <CopyPrompt
13
+ text="In this Nitro app, run `npm i workflow`. In `nitro.config.ts`, use `defineConfig` from `nitro`, set `serverDir: &quot;./server&quot;`, and add `modules: [&quot;workflow/nitro&quot;]`. Add the TypeScript plugin `{ &quot;name&quot;: &quot;workflow&quot; }` to `tsconfig.json` if TypeScript is used. Create `workflows/user-signup.ts` with `handleUserSignup(email)`, `&quot;use workflow&quot;`, `sleep` from `workflow`, and `&quot;use step&quot;` helpers. Add `server/api/signup.post.ts` using `defineEventHandler` from `nitro/h3` and `start` from `workflow/api` to start the workflow from `{ email }`. Run `npm run dev`, call `curl -X POST --json '{&quot;email&quot;:&quot;hello@example.com&quot;}' http://localhost:3000/api/signup`, then inspect with `npx workflow web` or `npx workflow inspect runs`."
14
+ />
15
+
12
16
  <Steps>
13
17
 
14
18
  <Step>
@@ -46,6 +50,28 @@ export default defineConfig({
46
50
 
47
51
  ```
48
52
 
53
+ ### Module options
54
+
55
+ The `workflow/nitro` module reads its options from `workflow` on your Nitro config.
56
+
57
+ ```typescript title="nitro.config.ts" lineNumbers
58
+ import { defineConfig } from "nitro";
59
+
60
+ export default defineConfig({
61
+ modules: ["workflow/nitro"],
62
+ workflow: {
63
+ runtime: "nodejs22.x",
64
+ sourcemap: "inline",
65
+ },
66
+ });
67
+ ```
68
+
69
+ | Option | Type | Default | Description |
70
+ | --- | --- | --- | --- |
71
+ | `dirs` | `string[]` | — | Directories to scan for workflows and steps. By default, `workflows/` is scanned from the project root and all layer source directories. |
72
+ | `runtime` | `string` | `'nodejs22.x'` | Node.js runtime version for Vercel Functions (e.g. `'nodejs22.x'`, `'nodejs24.x'`). |
73
+ | `sourcemap` | `boolean \| 'inline' \| 'linked' \| 'external' \| 'both'` | `'inline'` (dev) / `false` (prod) | Controls source maps on generated workflow bundles. Accepts the same values as esbuild's `sourcemap` option. Defaults to `'inline'` in development and `false` in production (smaller function bundles — helps stay under the Vercel 250MB function size limit). Set it explicitly, or use the `WORKFLOW_SOURCEMAP` environment variable, to override in either environment. |
74
+
49
75
  <Accordion type="single" collapsible>
50
76
  <AccordionItem value="typescript-intellisense" className="[&_h3]:my-0">
51
77
  <AccordionTrigger className="[&_p]:my-0 text-lg [&_p]:text-foreground">
@@ -146,7 +172,7 @@ async function sendOnboardingEmail(user: { id: string; email: string }) {
146
172
 
147
173
  Taking a look at this code:
148
174
 
149
- - Business logic lives inside **steps**. When a step is invoked inside a **workflow**, it gets enqueued to run on a separate request while the workflow is suspended, just like `sleep`.
175
+ - Business logic lives inside **steps**. When a workflow invokes a step, the workflow suspends while the step runs with full Node.js access. The combined handler may execute it inline; queued retries and continuations return through the same flow route.
150
176
  - If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count).
151
177
  - Steps can throw a `FatalError` if an error is intentional and should not be retried.
152
178
 
@@ -235,7 +261,7 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b
235
261
  If you see this error:
236
262
 
237
263
  ```
238
- 'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive.
264
+ 'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
239
265
  ```
240
266
 
241
267
  Check both of these first:
@@ -9,6 +9,10 @@ related:
9
9
  - /docs/foundations/workflows-and-steps
10
10
  ---
11
11
 
12
+ <CopyPrompt
13
+ text="In this Nuxt app, run `npm i workflow`. In `nuxt.config.ts`, add `modules: [&quot;workflow/nuxt&quot;]` and keep `compatibilityDate: &quot;latest&quot;`. Create `workflows/user-signup.ts` exporting `handleUserSignup(email)` with `&quot;use workflow&quot;`, `sleep` from `workflow`, and `&quot;use step&quot;` helpers that create a user and send emails. Add `server/api/signup.post.ts` using `defineEventHandler` from `h3` or `nitro/h3` and `start` from `workflow/api` to read `{ email }` and start the workflow. Run `npm run dev`, call `curl -X POST --json '{&quot;email&quot;:&quot;hello@example.com&quot;}' http://localhost:3000/api/signup`, and inspect with `npx workflow web` or `npx workflow inspect runs`."
14
+ />
15
+
12
16
  <Steps>
13
17
 
14
18
  <Step>
@@ -145,7 +149,7 @@ async function sendOnboardingEmail(user: { id: string; email: string }) {
145
149
 
146
150
  Taking a look at this code:
147
151
 
148
- - Business logic lives inside **steps**. When a step is invoked inside a **workflow**, it gets enqueued to run on a separate request while the workflow is suspended, just like `sleep`.
152
+ - Business logic lives inside **steps**. When a workflow invokes a step, the workflow suspends while the step runs with full Node.js access. The combined handler may execute it inline; queued retries and continuations return through the same flow route.
149
153
  - If a step throws an error, like in `sendWelcomeEmail`, the step will automatically be retried until it succeeds (or hits the step's max retry count).
150
154
  - Steps can throw a `FatalError` if an error is intentional and should not be retried.
151
155
 
@@ -236,7 +240,7 @@ Check the [Deploying](/docs/deploying) section to learn how your workflows can b
236
240
  If you see this error:
237
241
 
238
242
  ```
239
- 'start' received an invalid workflow function. Ensure the Workflow Development Kit is configured correctly and the function includes a 'use workflow' directive.
243
+ 'start' received an invalid workflow function. Ensure the Workflow SDK is configured correctly and the function includes a 'use workflow' directive.
240
244
  ```
241
245
 
242
246
  Check both of these first:
@@ -10,34 +10,31 @@ related:
10
10
  - /docs/foundations/workflows-and-steps
11
11
  ---
12
12
 
13
+ <CopyPrompt
14
+ text="In this Python project, add `requires-python = &quot;&gt;=3.12&quot;` and `dependencies = [&quot;vercel&quot;]` under `[project]` in `pyproject.toml`. Add `[[tool.vercel.workflows]]` with `entrypoint = &quot;app.workflows:wf&quot;`. Create `app/workflow.py` with `from vercel import workflow` and `wf = workflow.Workflows()`. Create `app/workflows/ai_content_workflow.py` importing `wf`, define `@wf.workflow async def ai_content_workflow(*, topic: str)`, and call step functions such as `generate_draft` and `summarize_draft`. Export `wf` from `app/workflows/__init__.py` and import the workflow module so its definitions are registered. Mark step functions with `@wf.step`, use `await workflow.sleep(&quot;7 days&quot;)` for durable delays where needed, and use a `workflow.BaseHook` Pydantic model plus `.wait(token=...)` and `.resume(token)` for external approval events. Verify the workflow entrypoint uses the `module:object` format and points to the exported `Workflows` registry."
15
+ />
16
+
13
17
  <Callout type="warn">
14
- The Python SDK is currently in **beta**. APIs and behavior may change. For the latest documentation and updates, see the [official Vercel Workflow Python documentation](https://vercel.com/docs/workflow/python?language=py).
18
+ The Python SDK is currently in **beta**. APIs and behavior may change. For the latest documentation and updates, see the [official Vercel Workflow Python documentation](https://vercel.com/docs/workflows/python).
15
19
  </Callout>
16
20
 
17
21
  You can build durable workflows in Python using the [`vercel` Python SDK](https://pypi.org/project/vercel/). Your workflow code can pause, resume, and maintain state, just like the JavaScript and TypeScript Workflow SDK.
18
22
 
19
23
  ## Getting Started
20
24
 
21
- Install the `vercel` package:
22
-
23
- ```bash filename="Terminal"
24
- pip install vercel
25
- ```
25
+ Add the `vercel` package and workflow entrypoint to `pyproject.toml`:
26
26
 
27
- Configure `experimentalServices` in your `vercel.json`:
27
+ ```toml filename="pyproject.toml"
28
+ [project]
29
+ requires-python = ">=3.12"
30
+ dependencies = ["vercel"]
28
31
 
29
- ```json filename="vercel.json"
30
- {
31
- "experimentalServices": {
32
- "ai_content_workflow": {
33
- "type": "worker",
34
- "entrypoint": "app/workflows/ai_content_workflow.py",
35
- "topics": ["__wkf_*"]
36
- }
37
- }
38
- }
32
+ [[tool.vercel.workflows]]
33
+ entrypoint = "app.workflows:wf"
39
34
  ```
40
35
 
36
+ The workflow `entrypoint` uses the `module:object` format and points to the exported `Workflows` registry.
37
+
41
38
  ## Workflows
42
39
 
43
40
  A workflow is a stateful function that coordinates multi-step logic over time. Create a `Workflows` instance and use the `@wf.workflow` decorator to mark a function as durable:
@@ -62,6 +59,15 @@ async def ai_content_workflow(*, topic: str):
62
59
  }
63
60
  ```
64
61
 
62
+ Export the registry from the workflow package and import the module containing your workflow so its definitions are registered:
63
+
64
+ ```python filename="app/workflows/__init__.py"
65
+ from app.workflow import wf
66
+ from app.workflows import ai_content_workflow
67
+
68
+ __all__ = ["ai_content_workflow", "wf"]
69
+ ```
70
+
65
71
  Under the hood, the workflow compiles into a route that orchestrates execution. All inputs and outputs are recorded in an event log. If a deploy or crash happens, the system replays execution deterministically from where it stopped.
66
72
 
67
73
  ## Steps
@@ -156,7 +162,7 @@ When a hook receives data, the workflow resumes automatically. You don&apos;t ne
156
162
 
157
163
  ## Learn More
158
164
 
159
- For comprehensive documentation, examples, and the latest updates, visit the [official Vercel Workflow Python documentation](https://vercel.com/docs/workflow/python).
165
+ For comprehensive documentation, examples, and the latest updates, visit the [official Vercel Workflow Python documentation](https://vercel.com/docs/workflows/python).
160
166
 
161
167
  ## Next Steps
162
168
 
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: React Router
3
+ description: Run durable workflows in a React Router framework-mode app using Nitro.
4
+ type: overview
5
+ summary: Choose your React Router version and connect React Router, Nitro, and Workflow SDK.
6
+ related:
7
+ - /docs/getting-started/nitro
8
+ - /docs/getting-started/vite
9
+ - /docs/foundations/workflows-and-steps
10
+ ---
11
+
12
+ React Router framework mode builds the browser application and its server-rendering code, but it still needs a server to receive requests. [Nitro](https://v3.nitro.build) provides that server. Workflow SDK integrates with Nitro to add the durable workflow routes and build artifacts.
13
+
14
+ The three pieces share one Vite build:
15
+
16
+ 1. **React Router** builds your routes, loaders, actions, and browser assets.
17
+ 2. **Nitro** runs the React Router request handler and any routes in `server/routes`.
18
+ 3. **Workflow SDK** finds files with `"use workflow"` and `"use step"`, then adds its runtime routes to Nitro.
19
+
20
+ Choose the guide that matches your React Router major version:
21
+
22
+ <AutoCards />
23
+
24
+ <Callout>
25
+ These guides require **Nitro v3**. Nitro v2 does not provide the Vite
26
+ environment integration used by this setup.
27
+ </Callout>
28
+
29
+ ## What the bridge does
30
+
31
+ The setup adds a small `server/ssr.ts` file. It turns React Router's generated server build into a standard Fetch API handler that Nitro can run. The Vite config then points Nitro's server and public output at the same `build` directory React Router uses.
32
+
33
+ This is configuration in your application, not a separate React Router adapter. Your React Router routes remain React Router routes, while Nitro owns the HTTP server and Workflow SDK uses Nitro's lifecycle and routing.
@@ -0,0 +1,5 @@
1
+ {
2
+ "title": "React Router",
3
+ "pages": ["v7", "v8"],
4
+ "defaultOpen": true
5
+ }
@@ -0,0 +1,237 @@
1
+ ---
2
+ title: React Router v7
3
+ description: Add durable workflows to a React Router v7 framework-mode app using Nitro v3.
4
+ type: guide
5
+ summary: Enable the Vite Environment API and configure React Router v7, Nitro v3, and Workflow SDK.
6
+ prerequisites:
7
+ - /docs/getting-started/react-router
8
+ related:
9
+ - /docs/getting-started/nitro
10
+ - /docs/foundations/workflows-and-steps
11
+ ---
12
+
13
+ This guide starts with an existing React Router v7 framework-mode app. It is verified with v7.18.1; if your config does not recognize `v8_viteEnvironmentApi`, update to the latest v7 release.
14
+
15
+ <Steps>
16
+
17
+ <Step>
18
+
19
+ ## Install Nitro and Workflow SDK
20
+
21
+ <Tabs items={["npm", "pnpm", "bun", "yarn"]} defaultValue="pnpm">
22
+
23
+ <Tab value="npm">
24
+
25
+ ```bash
26
+ npm install nitro workflow
27
+ ```
28
+
29
+ </Tab>
30
+
31
+ <Tab value="pnpm">
32
+
33
+ ```bash
34
+ pnpm add nitro workflow
35
+ ```
36
+
37
+ </Tab>
38
+
39
+ <Tab value="bun">
40
+
41
+ ```bash
42
+ bun add nitro workflow
43
+ ```
44
+
45
+ </Tab>
46
+
47
+ <Tab value="yarn">
48
+
49
+ ```bash
50
+ yarn add nitro workflow
51
+ ```
52
+
53
+ </Tab>
54
+
55
+ </Tabs>
56
+
57
+ This integration requires Nitro v3.
58
+
59
+ </Step>
60
+
61
+ <Step>
62
+
63
+ ## Enable the Vite Environment API
64
+
65
+ React Router v7 keeps the Vite Environment API behind a future flag. Enable the required flag and set an explicit build directory:
66
+
67
+ ```typescript title="react-router.config.ts" lineNumbers
68
+ import type { Config } from "@react-router/dev/config";
69
+
70
+ export default {
71
+ ssr: true,
72
+ buildDirectory: "build", // [!code highlight]
73
+ future: {
74
+ v8_viteEnvironmentApi: true, // [!code highlight]
75
+ },
76
+ } satisfies Config;
77
+ ```
78
+
79
+ </Step>
80
+
81
+ <Step>
82
+
83
+ ## Create the React Router server handler
84
+
85
+ Create `server/ssr.ts`:
86
+
87
+ ```typescript title="server/ssr.ts" lineNumbers
88
+ import { createRequestHandler } from "react-router";
89
+
90
+ export default {
91
+ fetch: createRequestHandler(
92
+ () => import("virtual:react-router/server-build"),
93
+ import.meta.env.MODE,
94
+ ),
95
+ };
96
+ ```
97
+
98
+ This adapts React Router's generated server build to the Fetch API handler Nitro expects.
99
+
100
+ </Step>
101
+
102
+ <Step>
103
+
104
+ ## Configure Vite
105
+
106
+ Update `vite.config.ts`:
107
+
108
+ ```typescript title="vite.config.ts" lineNumbers
109
+ import { reactRouter } from "@react-router/dev/vite";
110
+ import { nitro } from "nitro/vite";
111
+ import { defineConfig } from "vite";
112
+ import { workflow } from "workflow/vite";
113
+ import reactRouterConfig from "./react-router.config";
114
+
115
+ export default defineConfig({
116
+ plugins: [
117
+ reactRouter(),
118
+ nitro({
119
+ serverDir: "./server",
120
+ output: {
121
+ dir: reactRouterConfig.buildDirectory,
122
+ serverDir: `${reactRouterConfig.buildDirectory}/server`,
123
+ publicDir: `${reactRouterConfig.buildDirectory}/client`,
124
+ },
125
+ }),
126
+ workflow({ dirs: ["workflows"] }),
127
+ ],
128
+ environments: {
129
+ ssr: {
130
+ build: {
131
+ rollupOptions: {
132
+ input: "./server/ssr.ts",
133
+ },
134
+ },
135
+ },
136
+ },
137
+ });
138
+ ```
139
+
140
+ Keep `dirs: ["workflows"]` so subsequent builds do not scan generated files under `build`. Place `reactRouter()` before `nitro()` in the plugin array.
141
+
142
+ </Step>
143
+
144
+ <Step>
145
+
146
+ ## Create a workflow
147
+
148
+ Create `workflows/greeting.ts`:
149
+
150
+ ```typescript title="workflows/greeting.ts" lineNumbers
151
+ export async function greetingWorkflow(name: string) {
152
+ "use workflow";
153
+
154
+ return greet(name);
155
+ }
156
+
157
+ async function greet(name: string) {
158
+ "use step";
159
+
160
+ return `Hello, ${name}!`;
161
+ }
162
+ ```
163
+
164
+ </Step>
165
+
166
+ <Step>
167
+
168
+ ## Start the workflow from a Nitro route
169
+
170
+ Create `server/routes/api/greeting.post.ts`:
171
+
172
+ ```typescript title="server/routes/api/greeting.post.ts" lineNumbers
173
+ import { defineHandler } from "nitro";
174
+ import { start } from "workflow/api";
175
+ import { greetingWorkflow } from "../../../workflows/greeting";
176
+
177
+ export default defineHandler(async (event) => {
178
+ const { name } = (await event.req.json()) as { name: string };
179
+ const run = await start(greetingWorkflow, [name]);
180
+
181
+ return { runId: run.runId };
182
+ });
183
+ ```
184
+
185
+ React Router continues to handle your application routes. Nitro handles this server route at `POST /api/greeting`, as well as Workflow SDK's internal routes.
186
+
187
+ </Step>
188
+
189
+ <Step>
190
+
191
+ ## Run the app
192
+
193
+ Start the development server:
194
+
195
+ ```bash
196
+ pnpm vite dev
197
+ ```
198
+
199
+ Then start a workflow:
200
+
201
+ ```bash
202
+ curl -X POST \
203
+ -H "content-type: application/json" \
204
+ -d '{"name":"Workflow"}' \
205
+ http://localhost:3000/api/greeting
206
+ ```
207
+
208
+ Build and start the production server:
209
+
210
+ ```bash
211
+ pnpm vite build
212
+ node ./build/server/index.mjs
213
+ ```
214
+
215
+ You can inspect local runs with `pnpm workflow web`.
216
+
217
+ </Step>
218
+
219
+ </Steps>
220
+
221
+ ## Troubleshooting
222
+
223
+ ### Vite reports an invalid SSR input or `path.replace is not a function`
224
+
225
+ Set `future.v8_viteEnvironmentApi` to `true` in `react-router.config.ts`.
226
+
227
+ ### React Router pages return 404
228
+
229
+ Check that the `ssr` environment input points to `./server/ssr.ts`.
230
+
231
+ ### A second build tries to compile files under `build/server`
232
+
233
+ Use `workflow({ dirs: ["workflows"] })`, remove the existing `build` directory once, and rebuild.
234
+
235
+ ### `vite build` finishes output but does not exit
236
+
237
+ Use `workflow@5.0.0-beta.33` or later with Nitro v3.