workflow 5.0.0-beta.5 → 5.0.0-beta.51

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 (256) hide show
  1. package/README.md +68 -23
  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 +3 -3
  6. package/dist/api.d.ts.map +1 -1
  7. package/dist/api.js +5 -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 +20 -3
  12. package/dist/internal/builtins.d.ts.map +1 -1
  13. package/dist/internal/builtins.js +68 -4
  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 +4 -1
  28. package/docs/ai/chat-session-modeling.mdx +176 -422
  29. package/docs/ai/defining-tools.mdx +6 -7
  30. package/docs/ai/human-in-the-loop.mdx +11 -11
  31. package/docs/ai/index.mdx +71 -75
  32. package/docs/ai/message-queueing.mdx +71 -110
  33. package/docs/ai/meta.json +1 -0
  34. package/docs/ai/resumable-streams.mdx +40 -28
  35. package/docs/ai/sleep-and-delays.mdx +10 -10
  36. package/docs/ai/streaming-updates-from-tools.mdx +6 -6
  37. package/docs/api-reference/index.mdx +25 -1
  38. package/docs/api-reference/meta.json +8 -0
  39. package/docs/api-reference/vitest/index.mdx +9 -15
  40. package/docs/api-reference/workflow/create-hook.mdx +89 -10
  41. package/docs/api-reference/workflow/create-webhook.mdx +16 -15
  42. package/docs/api-reference/workflow/define-hook.mdx +35 -33
  43. package/docs/api-reference/workflow/fatal-error.mdx +30 -8
  44. package/docs/api-reference/workflow/fetch.mdx +14 -10
  45. package/docs/api-reference/workflow/get-step-metadata.mdx +2 -2
  46. package/docs/api-reference/workflow/get-workflow-metadata.mdx +3 -3
  47. package/docs/api-reference/workflow/get-writable.mdx +7 -7
  48. package/docs/api-reference/workflow/index.mdx +4 -1
  49. package/docs/api-reference/workflow/retryable-error.mdx +1 -1
  50. package/docs/api-reference/workflow/set-attributes.mdx +61 -0
  51. package/docs/api-reference/workflow/sleep.mdx +4 -4
  52. package/docs/api-reference/workflow-ai/durable-agent.mdx +63 -101
  53. package/docs/api-reference/workflow-ai/index.mdx +5 -5
  54. package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +67 -24
  55. package/docs/api-reference/workflow-api/get-hook-by-token.mdx +26 -12
  56. package/docs/api-reference/workflow-api/get-run.mdx +43 -8
  57. package/docs/api-reference/workflow-api/index.mdx +6 -10
  58. package/docs/api-reference/workflow-api/resume-hook.mdx +73 -12
  59. package/docs/api-reference/workflow-api/resume-webhook.mdx +11 -9
  60. package/docs/api-reference/workflow-api/start.mdx +60 -13
  61. package/docs/api-reference/workflow-astro/index.mdx +18 -0
  62. package/docs/api-reference/workflow-astro/meta.json +4 -0
  63. package/docs/api-reference/workflow-astro/workflow.mdx +45 -0
  64. package/docs/api-reference/workflow-errors/entity-conflict-error.mdx +4 -4
  65. package/docs/api-reference/workflow-errors/hook-conflict-error.mdx +60 -0
  66. package/docs/api-reference/workflow-errors/hook-not-found-error.mdx +8 -8
  67. package/docs/api-reference/workflow-errors/index.mdx +88 -0
  68. package/docs/api-reference/workflow-errors/meta.json +6 -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 +6 -6
  78. package/docs/api-reference/workflow-errors/workflow-run-failed-error.mdx +5 -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 +14 -10
  84. package/docs/api-reference/workflow-nest/configure-workflow-controller.mdx +33 -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 +40 -0
  89. package/docs/api-reference/workflow-nest/workflow-module.mdx +74 -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 +50 -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 +98 -34
  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 +380 -0
  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 +70 -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 +381 -0
  149. package/docs/configuration/worlds.mdx +313 -0
  150. package/docs/cookbook/advanced/child-workflows.mdx +211 -264
  151. package/docs/cookbook/advanced/meta.json +6 -1
  152. package/docs/cookbook/advanced/publishing-libraries.mdx +65 -56
  153. package/docs/cookbook/advanced/serializable-steps.mdx +48 -68
  154. package/docs/cookbook/advanced/upgrading-workflows.mdx +199 -0
  155. package/docs/cookbook/agent-patterns/agent-cancellation.mdx +78 -60
  156. package/docs/cookbook/agent-patterns/durable-agent.mdx +23 -131
  157. package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +180 -195
  158. package/docs/cookbook/common-patterns/batching.mdx +18 -14
  159. package/docs/cookbook/common-patterns/idempotency.mdx +41 -53
  160. package/docs/cookbook/common-patterns/rate-limiting.mdx +8 -4
  161. package/docs/cookbook/common-patterns/saga.mdx +23 -19
  162. package/docs/cookbook/common-patterns/scheduling.mdx +34 -22
  163. package/docs/cookbook/common-patterns/sequential-and-parallel.mdx +29 -25
  164. package/docs/cookbook/common-patterns/timeouts.mdx +26 -21
  165. package/docs/cookbook/common-patterns/webhooks.mdx +10 -6
  166. package/docs/cookbook/common-patterns/workflow-composition.mdx +30 -27
  167. package/docs/cookbook/index.mdx +22 -21
  168. package/docs/cookbook/integrations/ai-sdk.mdx +86 -48
  169. package/docs/cookbook/integrations/chat-sdk.mdx +50 -33
  170. package/docs/cookbook/integrations/sandbox.mdx +62 -45
  171. package/docs/deploying.mdx +95 -0
  172. package/docs/errors/abort-signal-timeout-in-workflow.mdx +16 -12
  173. package/docs/errors/corrupted-event-log.mdx +39 -18
  174. package/docs/errors/deployment-mismatch.mdx +71 -0
  175. package/docs/errors/fetch-in-workflow.mdx +15 -14
  176. package/docs/errors/hook-conflict.mdx +69 -13
  177. package/docs/errors/index.mdx +2 -36
  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 +42 -11
  192. package/docs/foundations/hooks.mdx +64 -35
  193. package/docs/foundations/idempotency.mdx +244 -12
  194. package/docs/foundations/index.mdx +1 -23
  195. package/docs/foundations/meta.json +2 -1
  196. package/docs/foundations/serialization.mdx +21 -22
  197. package/docs/foundations/starting-workflows.mdx +106 -30
  198. package/docs/foundations/streaming.mdx +108 -60
  199. package/docs/foundations/versioning.mdx +263 -0
  200. package/docs/foundations/workflows-and-steps.mdx +9 -9
  201. package/docs/getting-started/astro.mdx +22 -18
  202. package/docs/getting-started/express.mdx +15 -11
  203. package/docs/getting-started/fastify.mdx +15 -11
  204. package/docs/getting-started/hono.mdx +15 -11
  205. package/docs/getting-started/index.mdx +10 -3
  206. package/docs/getting-started/meta.json +3 -1
  207. package/docs/getting-started/nestjs.mdx +87 -20
  208. package/docs/getting-started/next.mdx +22 -16
  209. package/docs/getting-started/nitro.mdx +22 -18
  210. package/docs/getting-started/nuxt.mdx +15 -11
  211. package/docs/getting-started/python.mdx +190 -41
  212. package/docs/getting-started/react-router/index.mdx +33 -0
  213. package/docs/getting-started/react-router/meta.json +5 -0
  214. package/docs/getting-started/react-router/v7.mdx +237 -0
  215. package/docs/getting-started/react-router/v8.mdx +232 -0
  216. package/docs/getting-started/sveltekit.mdx +20 -16
  217. package/docs/getting-started/tanstack-start.mdx +17 -13
  218. package/docs/getting-started/vite.mdx +15 -11
  219. package/docs/how-it-works/cancellation.mdx +63 -63
  220. package/docs/how-it-works/code-transform.mdx +83 -67
  221. package/docs/how-it-works/encryption.mdx +30 -26
  222. package/docs/how-it-works/event-sourcing.mdx +125 -34
  223. package/docs/how-it-works/framework-integrations.mdx +96 -337
  224. package/docs/how-it-works/understanding-directives.mdx +22 -22
  225. package/docs/internal/index.mdx +6 -4
  226. package/docs/internal/meta.json +6 -1
  227. package/docs/internal/nitro-native-build.mdx +38 -0
  228. package/docs/internal/nitro-web-ui.mdx +24 -0
  229. package/docs/internal/serializable-abort-controller.mdx +7 -7
  230. package/docs/meta.json +3 -2
  231. package/docs/observability/attributes.mdx +134 -0
  232. package/docs/observability/index.mdx +32 -10
  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 +36 -36
  237. package/docs/testing/server-based.mdx +10 -10
  238. package/docs/whats-new.mdx +186 -0
  239. package/package.json +17 -14
  240. package/docs/api-reference/workflow-api/world/index.mdx +0 -58
  241. package/docs/api-reference/workflow-api/world/meta.json +0 -4
  242. package/docs/api-reference/workflow-api/world/observability.mdx +0 -164
  243. package/docs/api-reference/workflow-api/world/queue.mdx +0 -86
  244. package/docs/deploying/building-a-world.mdx +0 -251
  245. package/docs/deploying/index.mdx +0 -95
  246. package/docs/deploying/meta.json +0 -4
  247. package/docs/deploying/world/local-world.mdx +0 -84
  248. package/docs/deploying/world/meta.json +0 -4
  249. package/docs/deploying/world/postgres-world.mdx +0 -224
  250. package/docs/deploying/world/vercel-world.mdx +0 -179
  251. package/docs/migration-guides/index.mdx +0 -34
  252. package/docs/migration-guides/meta.json +0 -9
  253. package/docs/migration-guides/migrating-from-aws-step-functions.mdx +0 -363
  254. package/docs/migration-guides/migrating-from-inngest.mdx +0 -314
  255. package/docs/migration-guides/migrating-from-temporal.mdx +0 -318
  256. package/docs/migration-guides/migrating-from-trigger-dev.mdx +0 -337
@@ -9,7 +9,11 @@ related:
9
9
  - /docs/ai/resumable-streams
10
10
  ---
11
11
 
12
- A chat transport implementation for the AI SDK that provides reliable message streaming with automatic reconnection to interrupted streams. This transport is a drop-in replacement for the default AI SDK transport, enabling seamless recovery from network issues, page refreshes, or Vercel Function timeouts.
12
+ <Callout type="warn">
13
+ `WorkflowChatTransport` from `@workflow/ai` is deprecated. AI SDK ships a 1:1 port, so use [`WorkflowChatTransport` from `@ai-sdk/workflow`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#resumable-streaming-with-workflowchattransport) instead. This reference is kept for existing applications that still import it from `@workflow/ai`.
14
+ </Callout>
15
+
16
+ `WorkflowChatTransport` is an AI SDK chat transport that automatically reconnects to interrupted streams. It replaces the default AI SDK transport and recovers from network issues, page refreshes, or Vercel Functions timeouts.
13
17
 
14
18
  <Callout>
15
19
  `WorkflowChatTransport` implements the [`ChatTransport`](https://ai-sdk.dev/docs/ai-sdk-ui/transport) interface from the AI SDK and is designed to work with workflow-based chat applications. It requires endpoints that return the `x-workflow-run-id` header to enable stream resumption.
@@ -34,7 +38,7 @@ export default function Chat() {
34
38
  }
35
39
  ```
36
40
 
37
- ## API Signature
41
+ ## API signature
38
42
 
39
43
  ### Class
40
44
 
@@ -52,27 +56,27 @@ import type { WorkflowChatTransportOptions } from "@workflow/ai";
52
56
  export default WorkflowChatTransportOptions;`}
53
57
  />
54
58
 
55
- ## Key Features
59
+ ## Key features
56
60
 
57
- - **Automatic Reconnection**: Automatically recovers from interrupted streams with configurable retry limits
58
- - **Workflow Integration**: Seamlessly works with workflow-based endpoints that provide the `x-workflow-run-id` header
59
- - **Customizable Requests**: Allows intercepting and modifying requests via `prepareSendMessagesRequest` and `prepareReconnectToStreamRequest`
60
- - **Stream Callbacks**: Provides hooks for tracking chat lifecycle via `onChatSendMessage` and `onChatEnd`
61
- - **Custom Fetch**: Supports custom fetch implementations for advanced use cases
61
+ - **Automatic reconnection**: Recovers from interrupted streams with configurable retry limits.
62
+ - **Workflow integration**: Works with workflow-based endpoints that provide the `x-workflow-run-id` header.
63
+ - **Customizable requests**: Allows intercepting and modifying requests through `prepareSendMessagesRequest` and `prepareReconnectToStreamRequest`.
64
+ - **Stream callbacks**: Provides hooks for tracking the chat lifecycle through `onChatSendMessage` and `onChatEnd`.
65
+ - **Custom fetch**: Supports custom fetch implementations for advanced use cases.
62
66
 
63
- ## Good to Know
67
+ ## Good to know
64
68
 
65
- - The transport expects chat endpoints to return the `x-workflow-run-id` header in the response to enable stream resumption
66
- - By default, the transport posts to `/api/chat` and reconnects via `/api/chat/{runId}/stream`
67
- - The `onChatSendMessage` callback receives the full response object, allowing you to extract and store the workflow run ID for session resumption
68
- - Stream interruptions are automatically detected when a "finish" chunk is not received in the initial response
69
- - The `maxConsecutiveErrors` option controls how many reconnection attempts are made before giving up (default: 3)
70
- - `initialStartIndex` (constructor option) sets the default chunk position for the **first** reconnection attempt (e.g. after a page refresh). Subsequent retries within the same reconnection loop always resume from the last received chunk. Negative values (e.g. `-20`) read from the end of the stream, which is useful for showing only recent output without replaying the full conversation. `startIndex` (per-call option on `reconnectToStream`) overrides `initialStartIndex` for a single reconnection
71
- - When using a negative `initialStartIndex`, the reconnection endpoint must return the `x-workflow-stream-tail-index` response header (via `readable.getTailIndex()`). The transport reads this header to compute absolute chunk positions for retries. Without it, startIndex is assumed to be 0, replaying the entire stream
69
+ - The transport expects chat endpoints to return the `x-workflow-run-id` header in the response to enable stream resumption.
70
+ - By default, the transport posts to `/api/chat` and reconnects through `/api/chat/{runId}/stream`.
71
+ - The `onChatSendMessage` callback receives the full response object, allowing you to extract and store the workflow run ID for session resumption.
72
+ - Stream interruptions are automatically detected when a `finish` chunk is not received in the initial response.
73
+ - The `maxConsecutiveErrors` option controls how many reconnection attempts are made before giving up (default: 3).
74
+ - `initialStartIndex` (constructor option) sets the default chunk position for the **first** reconnection attempt (for example, after a page refresh). Subsequent retries within the same reconnection loop always resume from the last received chunk. Negative values (for example, `-20`) read from the end of the stream, which is useful for showing only recent output without replaying the full conversation. `startIndex` (per-call option on `reconnectToStream`) overrides `initialStartIndex` for a single reconnection.
75
+ - When using a negative `initialStartIndex`, the reconnection endpoint must return the `x-workflow-stream-tail-index` response header (through `readable.getTailIndex()`). The transport reads this header to compute absolute chunk positions for retries. Without it, `startIndex` is assumed to be `0`, replaying the entire stream.
72
76
 
73
77
  ## Examples
74
78
 
75
- ### Basic Chat Setup
79
+ ### Basic chat setup
76
80
 
77
81
  ```typescript
78
82
  "use client";
@@ -115,7 +119,7 @@ export default function BasicChat() {
115
119
  }
116
120
  ```
117
121
 
118
- ### With Session Persistence and Resumption
122
+ ### With session persistence and resumption
119
123
 
120
124
  ```typescript
121
125
  "use client";
@@ -183,7 +187,7 @@ export default function ChatWithResumption() {
183
187
  }
184
188
  ```
185
189
 
186
- ### With Custom Request Configuration
190
+ ### With custom request configuration
187
191
 
188
192
  ```typescript
189
193
  "use client";
@@ -250,9 +254,48 @@ export default function ChatWithCustomConfig() {
250
254
  }
251
255
  ```
252
256
 
253
- ## See Also
257
+ ## Mid-part resumes
258
+
259
+ A workflow stream is a flat sequence of chunks, but the AI SDK's user interface (UI) protocol groups chunks into logical parts: a `text-start` opens a text part that subsequent `text-delta`s extend and a `text-end` closes, and the same shape applies to `reasoning-*` and `tool-input-*`. The AI SDK client enforces that grammar: a `reasoning-delta` whose `reasoning-start` was never seen throws and breaks the chat.
260
+
261
+ A non-zero `startIndex` (in particular a negative `initialStartIndex`) resolves to a chunk offset with no awareness of those part boundaries, so it can land in the middle of an open part. When that happens, `WorkflowChatTransport` will **drop chunks that reference a part it didn't see a start for** and log a one-time warning. The chat keeps working, but any partial part overlapping the resume cursor is discarded. Tool calls are an exception: `tool-input-available` / `tool-input-error` chunks are self-contained (they carry the full input), so a tool call is recovered as soon as one of those chunks appears in the resumed window. Only its streamed input deltas are lost.
262
+
263
+ To preserve those partial parts, rewind to a step boundary on the server before returning the readable. `start-step` / `finish-step` chunks are the natural seams: no UI part is ever open across them. Sketch:
264
+
265
+ {/*@skip-typecheck: incomplete code sample*/}
266
+
267
+ ```typescript title="app/api/chat/[id]/stream/route.ts"
268
+ const run = getRun(id);
269
+ const tailIndex = await run.getReadable().getTailIndex();
270
+
271
+ let resolved = startIndex < 0
272
+ ? Math.max(0, tailIndex + 1 + startIndex)
273
+ : startIndex;
274
+
275
+ if (startIndex !== 0) {
276
+ // Walk back from `resolved` to the most recent start-step (or chunk 0),
277
+ // capping the lookback so a single huge step can't trigger an unbounded scan.
278
+ const LOOKBACK = 200;
279
+ const probe = run.getReadable({ startIndex: Math.max(0, resolved - LOOKBACK) });
280
+ let i = Math.max(0, resolved - LOOKBACK);
281
+ let lastBoundary = i;
282
+ for await (const chunk of probe as unknown as AsyncIterable<{ type: string }>) {
283
+ if (i >= resolved) break;
284
+ if (chunk.type === "start-step") lastBoundary = i;
285
+ i++;
286
+ }
287
+ resolved = lastBoundary;
288
+ }
289
+
290
+ return createUIMessageStreamResponse({
291
+ stream: run.getReadable({ startIndex: resolved }),
292
+ headers: { "x-workflow-stream-tail-index": String(tailIndex) },
293
+ });
294
+ ```
295
+
296
+ ## See also
254
297
 
255
- - [DurableAgent](/docs/api-reference/workflow-ai/durable-agent) - Building durable AI agents within workflows
256
- - [AI SDK `useChat` Documentation](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat) - Using `useChat` with custom transports
257
- - [Workflows and Steps](/docs/foundations/workflows-and-steps) - Understanding workflow fundamentals
258
- - ["flight-booking-app" Example](https://github.com/vercel/workflow-examples/tree/main/flight-booking-app) - An example application which uses `WorkflowChatTransport`
298
+ - [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent): Build durable, resumable AI agents (replaces `DurableAgent`)
299
+ - [AI SDK `useChat` documentation](https://ai-sdk.dev/docs/reference/ai-sdk-ui/use-chat): Use `useChat` with custom transports
300
+ - [Workflows and Steps](/docs/foundations/workflows-and-steps): Understand workflow fundamentals
301
+ - [`flight-booking-app` example](https://github.com/vercel/workflow-examples/tree/main/flight-booking-app): View an example application that uses `WorkflowChatTransport`
@@ -5,14 +5,26 @@ type: reference
5
5
  summary: Use getHookByToken to look up a hook's metadata and associated workflow run before resuming it.
6
6
  prerequisites:
7
7
  - /docs/foundations/hooks
8
+ related:
9
+ - /docs/foundations/idempotency
8
10
  ---
9
11
 
10
12
  Retrieves a hook by its unique token, returning the associated workflow run information and any metadata that was set when the hook was created. This function is useful for inspecting hook details before deciding whether to resume a workflow.
11
13
 
14
+ When `experimental_minRetention` is set, this function continues to return the Hook after its workflow ends until retention ends. That Hook cannot be resumed. Use `getRun(hook.runId)` to inspect the finished run.
15
+
12
16
  <Callout type="warn">
13
17
  `getHookByToken` is a runtime function that must be called from outside a workflow function.
14
18
  </Callout>
15
19
 
20
+ <Callout type="info">
21
+ `hook.metadata` is a getter that returns a Promise, so `await` it to read the value. Hydrating metadata can add extra network round trips, so that work is deferred to first access and the lookup itself stays a single read. Awaiting it on a hook with no metadata resolves `undefined` and performs no extra work, and repeat reads are free.
22
+ </Callout>
23
+
24
+ <Callout type="info">
25
+ Looking up a deterministic hook token is useful in hook-based idempotency flows, but it is only an advisory check. If no hook exists yet, another request can still start the same workflow before your `start()` call registers its hook. Use the lookup to avoid obvious duplicate starts, and handle the race inside the workflow by checking `await hook.getConflict()` before duplicate-sensitive work. On a conflict it resolves with the run that owns the token, so the duplicate can route the caller to the active owner. If duplicates must be rejected before a workflow body runs, keep a durable request record until native atomic start-and-hook registration exists. See [Run idempotency](/docs/foundations/idempotency#run-idempotency).
26
+ </Callout>
27
+
16
28
  ```typescript lineNumbers
17
29
  import { getHookByToken } from "workflow/api";
18
30
 
@@ -23,7 +35,7 @@ export async function POST(request: Request) {
23
35
  }
24
36
  ```
25
37
 
26
- ## API Signature
38
+ ## API signature
27
39
 
28
40
  ### Parameters
29
41
 
@@ -40,14 +52,14 @@ Returns a `Promise<Hook>` that resolves to:
40
52
 
41
53
  <TSDoc
42
54
  definition={`
43
- import type { Hook } from "@workflow/world";
55
+ import type { Hook } from "workflow/api";
44
56
  export default Hook;`}
45
57
  showSections={["returns"]}
46
58
  />
47
59
 
48
60
  ## Examples
49
61
 
50
- ### Basic Hook Lookup
62
+ ### Basic hook lookup
51
63
 
52
64
  Retrieve hook information before resuming:
53
65
 
@@ -62,7 +74,7 @@ export async function POST(request: Request) {
62
74
  const hook = await getHookByToken(token); // [!code highlight]
63
75
 
64
76
  console.log("Resuming workflow run:", hook.runId);
65
- console.log("Hook metadata:", hook.metadata);
77
+ console.log("Hook metadata:", await hook.metadata); // [!code highlight]
66
78
 
67
79
  // Then resume the hook with the payload
68
80
  await resumeHook(token, data);
@@ -77,7 +89,7 @@ export async function POST(request: Request) {
77
89
  }
78
90
  ```
79
91
 
80
- ### Validating Hook Before Resume
92
+ ### Validating hook before resume
81
93
 
82
94
  Use `getHookByToken` to validate hook ownership or metadata before resuming:
83
95
 
@@ -89,7 +101,8 @@ export async function POST(request: Request) {
89
101
 
90
102
  try {
91
103
  const hook = await getHookByToken(token); // [!code highlight]
92
- const metadata = hook.metadata as { allowedUserId?: string } | undefined;
104
+ // `metadata` is a Promise, so awaiting it hydrates the stored value.
105
+ const metadata = (await hook.metadata) as { allowedUserId?: string } | undefined; // [!code highlight]
93
106
 
94
107
  // Validate that the hook metadata matches the user
95
108
  if (metadata?.allowedUserId !== userId) {
@@ -107,7 +120,7 @@ export async function POST(request: Request) {
107
120
  }
108
121
  ```
109
122
 
110
- ### Checking Hook Environment
123
+ ### Checking hook environment
111
124
 
112
125
  Verify the hook belongs to the expected environment:
113
126
 
@@ -136,7 +149,7 @@ export async function POST(request: Request) {
136
149
  }
137
150
  ```
138
151
 
139
- ### Logging Hook Information
152
+ ### Logging hook information
140
153
 
141
154
  Log hook details for debugging or auditing:
142
155
 
@@ -173,8 +186,9 @@ export async function POST(request: Request) {
173
186
  }
174
187
  ```
175
188
 
176
- ## Related Functions
189
+ ## Related functions
177
190
 
178
- - [`resumeHook()`](/docs/api-reference/workflow-api/resume-hook) - Resume a hook with a payload.
179
- - [`createHook()`](/docs/api-reference/workflow/create-hook) - Create a hook in a workflow.
180
- - [`defineHook()`](/docs/api-reference/workflow/define-hook) - Type-safe hook helper.
191
+ - [`resumeHook()`](/docs/api-reference/workflow-api/resume-hook): Resume a hook with a payload.
192
+ - [`createHook()`](/docs/api-reference/workflow/create-hook): Create a hook in a workflow.
193
+ - [`defineHook()`](/docs/api-reference/workflow/define-hook): Type-safe hook helper.
194
+ - [Idempotency](/docs/foundations/idempotency): Deduplicate step side effects and workflow starts.
@@ -5,19 +5,25 @@ type: reference
5
5
  summary: Use getRun to check a workflow run's status and metadata without blocking on completion.
6
6
  prerequisites:
7
7
  - /docs/foundations/starting-workflows
8
+ related:
9
+ - /docs/foundations/idempotency
8
10
  ---
9
11
 
10
- Retrieves the workflow run metadata and status information for a given run ID. This function provides immediate access to workflow run details without waiting for completion, making it ideal for status checking and monitoring.
12
+ Retrieves workflow run metadata and status information for a given run ID. This function provides immediate access to workflow run details without waiting for completion.
11
13
 
12
14
  Use this function when you need to check workflow status, get timing information, or access workflow metadata without blocking on workflow completion.
13
15
 
16
+ <Callout type="info">
17
+ `getRun()` retrieves a run when you already have its `runId`. It does not look up runs by a business key. For retried requests that should route to one active workflow, use a deterministic hook token and [`getHookByToken()`](/docs/api-reference/workflow-api/get-hook-by-token). After a hook conflict, `HookConflictError.conflictingRunId` can be passed to `getRun()` to inspect, stream, or return the active owner. See [Run idempotency](/docs/foundations/idempotency#run-idempotency).
18
+ </Callout>
19
+
14
20
  ```typescript lineNumbers
15
21
  import { getRun } from "workflow/api";
16
22
 
17
23
  const run = getRun("my-run-id");
18
24
  ```
19
25
 
20
- ## API Signature
26
+ ## API signature
21
27
 
22
28
  ### Parameters
23
29
 
@@ -41,7 +47,7 @@ showSections={["returns"]}
41
47
 
42
48
  #### WorkflowReadableStream
43
49
 
44
- `run.getReadable()` returns a `WorkflowReadableStream` a standard `ReadableStream` extended with a `getTailIndex()` helper:
50
+ `run.getReadable()` returns a `WorkflowReadableStream`, a standard `ReadableStream` extended with a `getTailIndex()` helper:
45
51
 
46
52
  <TSDoc
47
53
  definition={`
@@ -59,6 +65,16 @@ import type { WorkflowReadableStreamOptions } from "workflow/api";
59
65
  export default WorkflowReadableStreamOptions;`}
60
66
  />
61
67
 
68
+ #### WorkflowRunWritableStreamOptions
69
+
70
+ <TSDoc
71
+ definition={`
72
+ import type { WorkflowRunWritableStreamOptions } from "workflow/api";
73
+ export default WorkflowRunWritableStreamOptions;`}
74
+ />
75
+
76
+ Use `run.writable` for the default stream or `run.getWritable(options)` to configure it. See [Writing to another run's stream](/docs/foundations/streaming#writing-to-another-runs-stream) for lifecycle details.
77
+
62
78
  #### StopSleepOptions
63
79
 
64
80
  <TSDoc
@@ -77,7 +93,7 @@ export default StopSleepResult;`}
77
93
 
78
94
  ## Examples
79
95
 
80
- ### Check if a Run Exists
96
+ ### Check if a run exists
81
97
 
82
98
  Use the `exists` getter to check whether a workflow run exists without throwing when the run is not found:
83
99
 
@@ -106,7 +122,7 @@ export async function GET(req: Request) {
106
122
  }
107
123
  ```
108
124
 
109
- ### Basic Status Check
125
+ ### Basic status check
110
126
 
111
127
  Check the current status of a workflow run:
112
128
 
@@ -135,7 +151,7 @@ export async function GET(req: Request) {
135
151
  }
136
152
  ```
137
153
 
138
- ### Wake Up a Sleeping Workflow
154
+ ### Wake up a sleeping workflow
139
155
 
140
156
  Interrupt pending `sleep()` calls to resume a workflow early. This is useful for testing workflows or building custom UIs that let users skip wait periods:
141
157
 
@@ -164,6 +180,25 @@ const { stoppedCount } = await run.wakeUp({
164
180
  });
165
181
  ```
166
182
 
167
- ## Related Functions
183
+ ### Cancel a run
184
+
185
+ Cancel a workflow run. You can pass an optional free-text `cancelReason` (up to 512 characters) that is recorded on the run's cancellation event and shown in the run detail view:
186
+
187
+ ```typescript lineNumbers
188
+ import { getRun } from "workflow/api";
189
+
190
+ export async function POST(req: Request) {
191
+ const { runId } = await req.json();
192
+ const run = getRun(runId);
193
+
194
+ await run.cancel({ cancelReason: "Superseded by a newer submission" }); // [!code highlight]
195
+
196
+ return Response.json({ cancelled: true });
197
+ }
198
+ ```
199
+
200
+ The options object is optional: `await run.cancel()` cancels the run without recording a reason.
201
+
202
+ ## Related functions
168
203
 
169
- - [`start()`](/docs/api-reference/workflow-api/start) - Start a new workflow and get its run ID.
204
+ - [`start()`](/docs/api-reference/workflow-api/start): Start a new workflow and get its run ID.
@@ -1,16 +1,14 @@
1
1
  ---
2
2
  title: "workflow/api"
3
- description: Runtime functions to inspect runs, start workflows, and access world data.
3
+ description: Runtime functions to inspect runs, start workflows, and manage hooks.
4
4
  type: overview
5
5
  summary: Explore runtime functions for starting workflows, inspecting runs, and managing hooks.
6
6
  ---
7
7
 
8
- API reference for runtime functions from the `workflow/api` package.
8
+ The `workflow/api` package provides runtime functions to inspect runs, start new runs, and manage hooks.
9
9
 
10
10
  ## Functions
11
11
 
12
- The API package is for access and introspection of workflow data to inspect runs, start new runs, or access anything else directly accessible by the world.
13
-
14
12
  <Cards>
15
13
  <Card href="/docs/api-reference/workflow-api/start" title="start()">
16
14
  Start/enqueue a new workflow run.
@@ -27,10 +25,8 @@ The API package is for access and introspection of workflow data to inspect runs
27
25
  <Card href="/docs/api-reference/workflow-api/get-run" title="getRun()">
28
26
  Get workflow run status and metadata without waiting for completion.
29
27
  </Card>
30
- <Card href="/docs/api-reference/workflow-api/get-world" title="getWorld()">
31
- Async: resolve the World instance for storage, queuing, and streaming backends.
32
- </Card>
33
- <Card href="/docs/api-reference/workflow-api/world" title="World SDK">
34
- Low-level API for inspecting runs, steps, events, hooks, streams, and queues.
35
- </Card>
36
28
  </Cards>
29
+
30
+ <Callout type="info">
31
+ Looking for `getWorld()` and the World SDK? They are exported from `workflow/runtime`. See the [`workflow/runtime` reference](/docs/api-reference/workflow-runtime).
32
+ </Callout>
@@ -7,11 +7,16 @@ prerequisites:
7
7
  - /docs/foundations/hooks
8
8
  related:
9
9
  - /docs/api-reference/workflow-api/resume-webhook
10
+ - /docs/foundations/idempotency
10
11
  ---
11
12
 
12
13
  Resumes a workflow run by sending a payload to a hook identified by its token.
13
14
 
14
- It creates a `hook_received` event and re-triggers the workflow to continue execution.
15
+ It durably writes the `hook_received` event and only then publishes a workflow wake. The call resolves only after both operations succeed, in that order.
16
+
17
+ `resumeHook()` throws `HookNotFoundError` when no hook holds the token or when its `hook_received` write is refused because the hook was disposed or the run ended. See [durable hook resume](/docs/changelog/lazy-hook-resume).
18
+
19
+ If `resumeHook()` throws any other error, the outcome is ambiguous only in dispatch, never in durability: the event may already be durable even though the workflow wake failed, and any later wake of the run delivers it. Calling `resumeHook()` again creates a new `resumeId` and can append a second `hook_received`. Callers that need at-most-once behavior across separate invocations must retain and deduplicate their own request key.
15
20
 
16
21
  <Callout type="warn">
17
22
  `resumeHook` is a runtime function that must be called from outside a workflow function.
@@ -34,7 +39,7 @@ export async function POST(request: Request) {
34
39
  }
35
40
  ```
36
41
 
37
- ## API Signature
42
+ ## API signature
38
43
 
39
44
  ### Parameters
40
45
 
@@ -47,18 +52,18 @@ showSections={["parameters"]}
47
52
 
48
53
  ### Returns
49
54
 
50
- Returns a `Promise<Hook>` that resolves to:
55
+ Returns a `Promise<ResumedHook>`, a `Hook` (from `workflow/api`) extended with an optional `resilientResume` flag. Resolving means the payload is durably recorded as `hook_received` and the workflow wake was accepted. `resilientResume` is retained for source compatibility and is no longer set by any path. Resuming never reads the hook's metadata, so the resolved hook's `metadata` is a Promise that hydrates on first access, exactly as with [`getHookByToken()`](/docs/api-reference/workflow-api/get-hook-by-token): `await hook.metadata` to read it. The resolved hook:
51
56
 
52
57
  <TSDoc
53
58
  definition={`
54
- import type { Hook } from "@workflow/world";
59
+ import type { Hook } from "workflow/api";
55
60
  export default Hook;`}
56
61
  showSections={["returns"]}
57
62
  />
58
63
 
59
64
  ## Examples
60
65
 
61
- ### Basic API Route
66
+ ### Basic API route
62
67
 
63
68
  Using `resumeHook` in a basic API route to resume a hook:
64
69
 
@@ -81,7 +86,7 @@ export async function POST(request: Request) {
81
86
  }
82
87
  ```
83
88
 
84
- ### With Type Safety
89
+ ### With type safety
85
90
 
86
91
  Defining a payload type and using `resumeHook` to resume a hook with type safety:
87
92
 
@@ -109,7 +114,7 @@ export async function POST(request: Request) {
109
114
  }
110
115
  ```
111
116
 
112
- ### Server Action (Next.js)
117
+ ### Server action (Next.js)
113
118
 
114
119
  Using `resumeHook` in Next.js server actions to resume a hook:
115
120
 
@@ -128,7 +133,7 @@ export async function approveRequest(token: string, approved: boolean) {
128
133
  }
129
134
  ```
130
135
 
131
- ### Webhook Handler
136
+ ### Webhook handler
132
137
 
133
138
  Using `resumeHook` in a generic webhook handler to resume a hook:
134
139
 
@@ -155,8 +160,64 @@ export async function POST(request: Request) {
155
160
  }
156
161
  ```
157
162
 
158
- ## Related Functions
163
+ ### Resume or start
164
+
165
+ A common endpoint shape is "resume or start": one route that resumes the active workflow run for a business key if one exists, or starts a new run otherwise. This comes up when the workflow uses a deterministic hook token as its idempotency key, for example, one active run per order or conversation.
166
+
167
+ `resumeHook()` is the resume half of that flow. Try it first; if it throws `HookNotFoundError`, no active run owns the token yet, so start the workflow. One subtlety: `start()` returns before the new run executes and registers its hook, so you cannot resume immediately after starting. Retry the resume until the hook is registered: if you drop the payload and only start the workflow, the data from this request is lost.
168
+
169
+ ```typescript lineNumbers
170
+ import { resumeHook, start } from "workflow/api";
171
+ import { HookNotFoundError } from "workflow/errors";
172
+ import { processOrder } from "./workflows/process-order";
173
+
174
+ type OrderRequest = { confirmed: boolean };
175
+
176
+ async function resumeWithRetry(token: string, payload: OrderRequest) {
177
+ for (let attempt = 0; attempt < 5; attempt++) {
178
+ try {
179
+ return await resumeHook(token, payload); // [!code highlight]
180
+ } catch (error) {
181
+ if (!HookNotFoundError.is(error)) throw error;
182
+ await new Promise((resolve) => setTimeout(resolve, 100));
183
+ }
184
+ }
185
+
186
+ throw new Error("Workflow did not register its hook in time");
187
+ }
188
+
189
+ export async function POST(request: Request) {
190
+ const { orderId, confirmed } = await request.json();
191
+ const token = `order:${orderId}`;
192
+ const payload = { confirmed };
193
+
194
+ try {
195
+ // An active run already owns this token: resume it.
196
+ const hook = await resumeHook(token, payload); // [!code highlight]
197
+ return Response.json({ runId: hook.runId, reused: true });
198
+ } catch (error) {
199
+ if (!HookNotFoundError.is(error)) throw error;
200
+ }
201
+
202
+ // No hook yet: start a new run, then retry the resume so this
203
+ // request's payload still reaches the workflow.
204
+ const run = await start(processOrder, [orderId]); // [!code highlight]
205
+ const resumed = await resumeWithRetry(token, payload);
206
+
207
+ // A concurrent request can win the race between `start()` and hook
208
+ // registration; the resume always reaches the actual active owner.
209
+ return Response.json({
210
+ runId: resumed.runId,
211
+ reused: resumed.runId !== run.runId,
212
+ });
213
+ }
214
+ ```
215
+
216
+ See [Run idempotency](/docs/foundations/idempotency#run-idempotency) for the full pattern, including how the workflow claims the token with `hook.getConflict()` and how concurrent starts converge on one active owner.
217
+
218
+ ## Related functions
159
219
 
160
- - [`getHookByToken()`](/docs/api-reference/workflow-api/get-hook-by-token) - Get hook details before resuming.
161
- - [`createHook()`](/docs/api-reference/workflow/create-hook) - Create a hook in a workflow.
162
- - [`defineHook()`](/docs/api-reference/workflow/define-hook) - Type-safe hook helper.
220
+ - [`getHookByToken()`](/docs/api-reference/workflow-api/get-hook-by-token): Get hook details before resuming.
221
+ - [`createHook()`](/docs/api-reference/workflow/create-hook): Create a hook in a workflow.
222
+ - [`defineHook()`](/docs/api-reference/workflow/define-hook): Type-safe hook helper.
223
+ - [Idempotency](/docs/foundations/idempotency): Deduplicate step side effects and workflow starts.
@@ -11,7 +11,7 @@ related:
11
11
 
12
12
  Resumes a workflow run by sending an HTTP `Request` to a webhook identified by its token.
13
13
 
14
- This function creates a `hook_received` event and re-triggers the workflow to continue execution. It's designed to be called from API routes or server actions that receive external HTTP requests.
14
+ This function publishes a workflow invocation carrying the request; the runtime creates the `hook_received` event from it and continues execution. It's designed to be called from API routes or server actions that receive external HTTP requests.
15
15
 
16
16
  <Callout type="warn">
17
17
  `resumeWebhook` is a runtime function that must be called from outside a workflow function.
@@ -37,7 +37,7 @@ export async function POST(request: Request) {
37
37
  }
38
38
  ```
39
39
 
40
- ## API Signature
40
+ ## API signature
41
41
 
42
42
  ### Parameters
43
43
 
@@ -50,16 +50,18 @@ showSections={['parameters']}
50
50
 
51
51
  ### Returns
52
52
 
53
- Returns a `Promise<Response>` that resolves to:
53
+ Returns a `Promise<Response>` that resolves to one of:
54
54
 
55
- - `Response`: The HTTP response from the workflow's `respondWith()` call
55
+ - A `202 Accepted` response when the webhook was created in the default mode (no `respondWith` option).
56
+ - The exact `Response` object configured via `createWebhook({ respondWith: new Response(...) })`.
57
+ - The workflow's manual `Response` when the webhook was created with `createWebhook({ respondWith: "manual" })` and a step calls `request.respondWith(response)`.
56
58
 
57
- Throws an error if the webhook token is not found or invalid.
59
+ Throws [`HookNotFoundError`](/docs/api-reference/workflow-errors/hook-not-found-error) if the token does not match an active webhook.
58
60
 
59
- ## Usage Note
61
+ ## Usage note
60
62
 
61
63
  <Callout type="warn">
62
- In most cases, you should not need to call `resumeWebhook()` directly. When you use `createWebhook()`, the framework automatically generates a random webhook token and provides a public URL at `/.well-known/workflow/v1/webhook/:token`. External systems can send HTTP requests directly to that URL.
64
+ In most cases, you should not need to call `resumeWebhook()` directly. When you use `createWebhook()`, the framework automatically generates a webhook token and provides a public URL at `/.well-known/workflow/v1/webhook/:token`. External systems can send HTTP requests directly to that URL.
63
65
 
64
66
  For server-side hook resumption with deterministic tokens, use [`resumeHook()`](/docs/api-reference/workflow-api/resume-hook) with [`createHook()`](/docs/api-reference/workflow/create-hook) instead.
65
67
  </Callout>
@@ -81,14 +83,14 @@ export async function POST(request: Request) {
81
83
 
82
84
  try {
83
85
  const response = await resumeWebhook(token, request); // [!code highlight]
84
- return response; // Returns the workflow's custom response
86
+ return response; // 202 Accepted, a configured static Response, or a manual workflow response
85
87
  } catch (error) {
86
88
  return new Response("Webhook not found", { status: 404 });
87
89
  }
88
90
  }
89
91
  ```
90
92
 
91
- ## Related Functions
93
+ ## Related functions
92
94
 
93
95
  - [`createWebhook()`](/docs/api-reference/workflow/create-webhook) - Create a webhook in a workflow
94
96
  - [`resumeHook()`](/docs/api-reference/workflow-api/resume-hook) - Resume a hook with arbitrary payload