workflow 4.4.0 → 4.6.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.
- package/docs/ai/resumable-streams.mdx +4 -0
- package/docs/api-reference/index.mdx +24 -0
- package/docs/api-reference/meta.json +8 -0
- package/docs/api-reference/vitest/index.mdx +0 -6
- package/docs/api-reference/workflow/create-hook.mdx +32 -0
- package/docs/api-reference/workflow/create-webhook.mdx +1 -0
- package/docs/api-reference/workflow-ai/workflow-chat-transport.mdx +39 -0
- package/docs/api-reference/workflow-api/index.mdx +6 -8
- package/docs/api-reference/workflow-api/start.mdx +2 -0
- package/docs/api-reference/workflow-errors/meta.json +5 -0
- package/docs/api-reference/workflow-next/with-workflow.mdx +26 -4
- package/docs/api-reference/workflow-serde/index.mdx +0 -1
- package/docs/api-reference/workflow-serde/workflow-deserialize.mdx +1 -2
- package/docs/api-reference/workflow-serde/workflow-serialize.mdx +1 -2
- package/docs/deploying/world/postgres-world.mdx +33 -1
- package/docs/deploying/world/vercel-world.mdx +2 -0
- package/docs/errors/index.mdx +3 -0
- package/docs/foundations/hooks.mdx +29 -0
- package/docs/foundations/streaming.mdx +7 -1
- package/docs/foundations/versioning.mdx +1 -1
- package/docs/how-it-works/encryption.mdx +2 -2
- package/docs/how-it-works/event-sourcing.mdx +2 -2
- package/docs/observability/index.mdx +13 -0
- package/docs/v4/api-reference/workflow-astro/index.mdx +18 -0
- package/docs/v4/api-reference/workflow-astro/meta.json +4 -0
- package/docs/v4/api-reference/workflow-astro/workflow.mdx +37 -0
- package/docs/v4/api-reference/workflow-errors/hook-conflict-error.mdx +60 -0
- package/docs/v4/api-reference/workflow-errors/run-not-supported-error.mdx +58 -0
- package/docs/v4/api-reference/workflow-errors/workflow-error.mdx +52 -0
- package/docs/v4/api-reference/workflow-errors/workflow-run-not-completed-error.mdx +58 -0
- package/docs/v4/api-reference/workflow-errors/workflow-runtime-error.mdx +58 -0
- package/docs/v4/api-reference/workflow-nest/configure-workflow-controller.mdx +33 -0
- package/docs/v4/api-reference/workflow-nest/index.mdx +31 -0
- package/docs/v4/api-reference/workflow-nest/meta.json +9 -0
- package/docs/v4/api-reference/workflow-nest/nest-local-builder.mdx +63 -0
- package/docs/v4/api-reference/workflow-nest/workflow-controller.mdx +40 -0
- package/docs/v4/api-reference/workflow-nest/workflow-module.mdx +73 -0
- package/docs/v4/api-reference/workflow-nitro/index.mdx +58 -0
- package/docs/v4/api-reference/workflow-nuxt/index.mdx +48 -0
- package/docs/v4/api-reference/workflow-observability/hydrate-data.mdx +35 -0
- package/docs/v4/api-reference/workflow-observability/hydrate-resource-io.mdx +62 -0
- package/docs/v4/api-reference/workflow-observability/index.mdx +64 -0
- package/docs/v4/api-reference/workflow-observability/meta.json +11 -0
- package/docs/v4/api-reference/workflow-observability/observability-revivers.mdx +50 -0
- package/docs/v4/api-reference/workflow-observability/parse-class-name.mdx +41 -0
- package/docs/v4/api-reference/workflow-observability/parse-step-name.mdx +40 -0
- package/docs/v4/api-reference/workflow-observability/parse-workflow-name.mdx +55 -0
- package/docs/v4/api-reference/workflow-runtime/create-world.mdx +43 -0
- package/docs/v4/api-reference/workflow-runtime/get-world-handlers.mdx +44 -0
- package/docs/v4/api-reference/workflow-runtime/get-world.mdx +124 -0
- package/docs/v4/api-reference/workflow-runtime/health-check.mdx +50 -0
- package/docs/v4/api-reference/workflow-runtime/index.mdx +46 -0
- package/docs/v4/api-reference/workflow-runtime/meta.json +13 -0
- package/docs/v4/api-reference/workflow-runtime/set-world.mdx +49 -0
- package/docs/v4/api-reference/workflow-runtime/step-entrypoint.mdx +39 -0
- package/docs/v4/api-reference/workflow-runtime/workflow-entrypoint.mdx +42 -0
- package/docs/{api-reference/workflow-api → v4/api-reference/workflow-runtime}/world/index.mdx +5 -8
- package/docs/v4/api-reference/workflow-runtime/world/meta.json +4 -0
- package/docs/v4/api-reference/workflow-runtime/world/queue.mdx +86 -0
- package/docs/{api-reference/workflow-api → v4/api-reference/workflow-runtime}/world/storage.mdx +4 -4
- package/docs/v4/api-reference/workflow-runtime/world/streams.mdx +216 -0
- package/docs/v4/api-reference/workflow-sveltekit/index.mdx +18 -0
- package/docs/v4/api-reference/workflow-sveltekit/meta.json +4 -0
- package/docs/v4/api-reference/workflow-sveltekit/workflow-plugin.mdx +34 -0
- package/docs/v4/api-reference/workflow-vite/index.mdx +18 -0
- package/docs/v4/api-reference/workflow-vite/meta.json +4 -0
- package/docs/v4/api-reference/workflow-vite/workflow.mdx +47 -0
- package/docs/v4/errors/step-executed-multiple-times.mdx +23 -0
- package/docs/v5/api-reference/workflow-astro/index.mdx +18 -0
- package/docs/v5/api-reference/workflow-astro/meta.json +4 -0
- package/docs/v5/api-reference/workflow-astro/workflow.mdx +45 -0
- package/docs/v5/api-reference/workflow-errors/hook-conflict-error.mdx +60 -0
- package/docs/v5/api-reference/workflow-errors/run-not-supported-error.mdx +58 -0
- package/docs/v5/api-reference/workflow-errors/workflow-error.mdx +52 -0
- package/docs/v5/api-reference/workflow-errors/workflow-run-not-completed-error.mdx +58 -0
- package/docs/v5/api-reference/workflow-errors/workflow-runtime-error.mdx +58 -0
- package/docs/v5/api-reference/workflow-nest/configure-workflow-controller.mdx +33 -0
- package/docs/v5/api-reference/workflow-nest/index.mdx +31 -0
- package/docs/v5/api-reference/workflow-nest/meta.json +9 -0
- package/docs/v5/api-reference/workflow-nest/nest-local-builder.mdx +64 -0
- package/docs/v5/api-reference/workflow-nest/workflow-controller.mdx +40 -0
- package/docs/v5/api-reference/workflow-nest/workflow-module.mdx +74 -0
- package/docs/v5/api-reference/workflow-nitro/index.mdx +60 -0
- package/docs/v5/api-reference/workflow-nuxt/index.mdx +48 -0
- package/docs/v5/api-reference/workflow-observability/hydrate-data.mdx +35 -0
- package/docs/v5/api-reference/workflow-observability/hydrate-resource-io.mdx +62 -0
- package/docs/v5/api-reference/workflow-observability/index.mdx +64 -0
- package/docs/v5/api-reference/workflow-observability/meta.json +11 -0
- package/docs/v5/api-reference/workflow-observability/observability-revivers.mdx +50 -0
- package/docs/v5/api-reference/workflow-observability/parse-class-name.mdx +41 -0
- package/docs/v5/api-reference/workflow-observability/parse-step-name.mdx +40 -0
- package/docs/v5/api-reference/workflow-observability/parse-workflow-name.mdx +55 -0
- package/docs/v5/api-reference/workflow-runtime/create-world.mdx +39 -0
- package/docs/v5/api-reference/workflow-runtime/get-world-handlers.mdx +44 -0
- package/docs/{api-reference/workflow-api → v5/api-reference/workflow-runtime}/get-world.mdx +7 -10
- package/docs/v5/api-reference/workflow-runtime/health-check.mdx +50 -0
- package/docs/v5/api-reference/workflow-runtime/index.mdx +43 -0
- package/docs/v5/api-reference/workflow-runtime/meta.json +12 -0
- package/docs/v5/api-reference/workflow-runtime/set-world.mdx +49 -0
- package/docs/v5/api-reference/workflow-runtime/workflow-entrypoint.mdx +42 -0
- package/docs/v5/api-reference/workflow-runtime/world/index.mdx +55 -0
- package/docs/v5/api-reference/workflow-runtime/world/meta.json +4 -0
- package/docs/{api-reference/workflow-api → v5/api-reference/workflow-runtime}/world/queue.mdx +2 -2
- package/docs/v5/api-reference/workflow-runtime/world/storage.mdx +409 -0
- package/docs/{api-reference/workflow-api → v5/api-reference/workflow-runtime}/world/streams.mdx +2 -2
- package/docs/v5/api-reference/workflow-sveltekit/index.mdx +18 -0
- package/docs/v5/api-reference/workflow-sveltekit/meta.json +4 -0
- package/docs/v5/api-reference/workflow-sveltekit/workflow-plugin.mdx +42 -0
- package/docs/v5/api-reference/workflow-vite/index.mdx +18 -0
- package/docs/v5/api-reference/workflow-vite/meta.json +4 -0
- package/docs/v5/api-reference/workflow-vite/workflow.mdx +48 -0
- package/docs/v5/errors/index.mdx +3 -0
- package/docs/v5/errors/step-executed-multiple-times.mdx +23 -0
- package/package.json +10 -10
- package/docs/api-reference/workflow-api/world/meta.json +0 -4
- package/docs/api-reference/workflow-api/world/observability.mdx +0 -164
|
@@ -194,6 +194,10 @@ This avoids replaying potentially thousands of chunks and lets the UI render fas
|
|
|
194
194
|
When using a negative `initialStartIndex`, the reconnection endpoint **must** return the `x-workflow-stream-tail-index` header (as shown in [Step 2](#add-a-stream-reconnection-endpoint) above). The transport uses this header to compute absolute chunk positions so that retries after a disconnect resume from the correct position. If the header is missing, the transport falls back to `startIndex: 0` (replaying the entire stream) and logs a warning.
|
|
195
195
|
</Callout>
|
|
196
196
|
|
|
197
|
+
### Mid-part resumes
|
|
198
|
+
|
|
199
|
+
A workflow stream is a flat sequence of chunks, but the AI SDK's UI protocol groups chunks into logical parts (`text-*`, `reasoning-*`, `tool-input-*`) that must be opened with a `*-start` before any `*-delta` or `*-end`. A non-zero `startIndex` can land in the middle of an open part. See [`WorkflowChatTransport` → Mid-part resumes](/docs/api-reference/workflow-ai/workflow-chat-transport#mid-part-resumes) for how this is handled and an example of rewinding to a step boundary on the server.
|
|
200
|
+
|
|
197
201
|
## Related Documentation
|
|
198
202
|
|
|
199
203
|
- [`WorkflowChatTransport` API Reference](/docs/api-reference/workflow-ai/workflow-chat-transport) - Full configuration options
|
|
@@ -17,9 +17,33 @@ All the functions and primitives that come with Workflow SDK by package.
|
|
|
17
17
|
<Card title="workflow/api" href="/docs/api-reference/workflow-api">
|
|
18
18
|
API reference for runtime functions from the `workflow/api` package.
|
|
19
19
|
</Card>
|
|
20
|
+
<Card title="workflow/runtime" href="/docs/api-reference/workflow-runtime">
|
|
21
|
+
Runtime functions for resolving the World instance and the low-level World SDK.
|
|
22
|
+
</Card>
|
|
23
|
+
<Card title="workflow/observability" href="/docs/api-reference/workflow-observability">
|
|
24
|
+
Utilities to hydrate step I/O, parse display names, and decrypt workflow data.
|
|
25
|
+
</Card>
|
|
20
26
|
<Card title="workflow/next" href="/docs/api-reference/workflow-next">
|
|
21
27
|
Next.js integration for Workflow SDK that automatically configures bundling and runtime support.
|
|
22
28
|
</Card>
|
|
29
|
+
<Card title="workflow/nitro" href="/docs/api-reference/workflow-nitro">
|
|
30
|
+
Nitro module for workflow bundling and runtime support.
|
|
31
|
+
</Card>
|
|
32
|
+
<Card title="workflow/nuxt" href="/docs/api-reference/workflow-nuxt">
|
|
33
|
+
Nuxt module for workflow bundling and runtime support.
|
|
34
|
+
</Card>
|
|
35
|
+
<Card title="workflow/sveltekit" href="/docs/api-reference/workflow-sveltekit">
|
|
36
|
+
SvelteKit Vite plugin for workflow bundling and runtime support.
|
|
37
|
+
</Card>
|
|
38
|
+
<Card title="workflow/astro" href="/docs/api-reference/workflow-astro">
|
|
39
|
+
Astro integration for workflow bundling and runtime support.
|
|
40
|
+
</Card>
|
|
41
|
+
<Card title="workflow/vite" href="/docs/api-reference/workflow-vite">
|
|
42
|
+
Standalone Vite plugin for workflow bundling and runtime support.
|
|
43
|
+
</Card>
|
|
44
|
+
<Card title="workflow/nest" href="/docs/api-reference/workflow-nest">
|
|
45
|
+
NestJS module for workflow bundling and runtime support.
|
|
46
|
+
</Card>
|
|
23
47
|
<Card title="workflow/errors" href="/docs/api-reference/workflow-errors">
|
|
24
48
|
Semantic error types for handling workflow storage backend failures.
|
|
25
49
|
</Card>
|
|
@@ -4,7 +4,15 @@
|
|
|
4
4
|
"workflow-globals",
|
|
5
5
|
"workflow",
|
|
6
6
|
"workflow-api",
|
|
7
|
+
"workflow-runtime",
|
|
8
|
+
"workflow-observability",
|
|
7
9
|
"workflow-next",
|
|
10
|
+
"workflow-nitro",
|
|
11
|
+
"workflow-nuxt",
|
|
12
|
+
"workflow-sveltekit",
|
|
13
|
+
"workflow-astro",
|
|
14
|
+
"workflow-vite",
|
|
15
|
+
"workflow-nest",
|
|
8
16
|
"workflow-errors",
|
|
9
17
|
"workflow-serde",
|
|
10
18
|
"workflow-ai",
|
|
@@ -11,7 +11,6 @@ The `@workflow/vitest` package provides a Vitest plugin and test helpers for run
|
|
|
11
11
|
|
|
12
12
|
Returns a Vite plugin array that handles SWC transforms, bundle building, and in-process handler registration automatically.
|
|
13
13
|
|
|
14
|
-
{/* @skip-typecheck - @workflow/vitest not available in docs-typecheck */}
|
|
15
14
|
|
|
16
15
|
```typescript
|
|
17
16
|
import { defineConfig } from "vitest/config";
|
|
@@ -24,7 +23,6 @@ export default defineConfig({
|
|
|
24
23
|
|
|
25
24
|
Pass a [`WorkflowTestOptions`](#workflowtestoptions) object when your project uses a non-standard layout — for example, a monorepo where `workflows/` does not live at the Vitest config's directory, or when the default `.workflow-data` / `.workflow-vitest` output locations need to move. The plugin forwards these paths to `buildWorkflowTests()` and `setupWorkflowTests()` through Vitest's per-project provided context, so each Vitest workspace project stays isolated.
|
|
26
25
|
|
|
27
|
-
{/* @skip-typecheck - @workflow/vitest not available in docs-typecheck */}
|
|
28
26
|
|
|
29
27
|
```typescript
|
|
30
28
|
import { defineConfig } from "vitest/config";
|
|
@@ -54,7 +52,6 @@ export default defineConfig({
|
|
|
54
52
|
|
|
55
53
|
Builds workflow and step bundles to disk. Called automatically by the `workflow()` plugin in `globalSetup`. Use directly only for [manual setup](/docs/testing#manual-setup).
|
|
56
54
|
|
|
57
|
-
{/* @skip-typecheck - @workflow/vitest not available in docs-typecheck */}
|
|
58
55
|
|
|
59
56
|
```typescript
|
|
60
57
|
import { buildWorkflowTests } from "@workflow/vitest";
|
|
@@ -76,7 +73,6 @@ Sets up an in-process workflow runtime in each test worker. Imports pre-built bu
|
|
|
76
73
|
|
|
77
74
|
Called automatically by the `workflow()` plugin in `setupFiles`. Use directly only for [manual setup](/docs/testing#manual-setup).
|
|
78
75
|
|
|
79
|
-
{/* @skip-typecheck - @workflow/vitest not available in docs-typecheck */}
|
|
80
76
|
|
|
81
77
|
```typescript
|
|
82
78
|
import { beforeAll, afterAll } from "vitest";
|
|
@@ -118,7 +114,6 @@ Tears down the workflow test world. Clears the global world and closes the Local
|
|
|
118
114
|
|
|
119
115
|
Polls the event log until the workflow has a pending `sleep()` call — one with a `wait_created` event but no corresponding `wait_completed` event. Returns the correlation ID of the pending sleep, which can be passed to [`wakeUp()`](/docs/api-reference/workflow-api/get-run) to target a specific sleep.
|
|
120
116
|
|
|
121
|
-
{/* @skip-typecheck - @workflow/vitest not available in docs-typecheck */}
|
|
122
117
|
|
|
123
118
|
```typescript
|
|
124
119
|
import { waitForSleep } from "@workflow/vitest"; // [!code highlight]
|
|
@@ -147,7 +142,6 @@ await getRun(run.runId).wakeUp({ correlationIds: [sleepId] }); // [!code highlig
|
|
|
147
142
|
|
|
148
143
|
Polls the hook list and event log until a hook matching the optional `token` filter exists that hasn't been received yet. Returns the matching hook object.
|
|
149
144
|
|
|
150
|
-
{/* @skip-typecheck - @workflow/vitest not available in docs-typecheck */}
|
|
151
145
|
|
|
152
146
|
```typescript
|
|
153
147
|
import { waitForHook } from "@workflow/vitest"; // [!code highlight]
|
|
@@ -65,6 +65,8 @@ export default Hook;`}
|
|
|
65
65
|
|
|
66
66
|
The returned `Hook` object also implements `AsyncIterable<T>`, which allows you to iterate over incoming payloads using `for await...of` syntax.
|
|
67
67
|
|
|
68
|
+
Use `hook.getConflict()` (available starting in `workflow@4.5.0`) to check whether the hook token is already claimed by another active hook, without waiting for hook payload data. Calling `createHook()` on its own does not register the hook — registration is only committed when the workflow suspends. Awaiting `hook.getConflict()` suspends the workflow to commit the registration, then resolves with `null` once `hook_created` is recorded, or with `{ runId }` identifying the conflicting run if another active hook already owns the same token.
|
|
69
|
+
|
|
68
70
|
## Examples
|
|
69
71
|
|
|
70
72
|
### Basic Usage
|
|
@@ -112,6 +114,36 @@ export async function slackBotWorkflow(channelId: string) {
|
|
|
112
114
|
}
|
|
113
115
|
```
|
|
114
116
|
|
|
117
|
+
### Detecting Token Conflicts
|
|
118
|
+
|
|
119
|
+
Use `hook.getConflict()` (available starting in `workflow@4.5.0`) when the workflow needs to claim a hook token before doing other work, but does not need a payload yet:
|
|
120
|
+
|
|
121
|
+
```typescript lineNumbers
|
|
122
|
+
import { createHook } from "workflow";
|
|
123
|
+
|
|
124
|
+
declare function chargeOrder(orderId: string): Promise<void>; // @setup
|
|
125
|
+
|
|
126
|
+
async function processOrder(orderId: string) {
|
|
127
|
+
"use workflow";
|
|
128
|
+
|
|
129
|
+
using hook = createHook({ // [!code highlight]
|
|
130
|
+
token: `order:${orderId}` // [!code highlight]
|
|
131
|
+
}); // [!code highlight]
|
|
132
|
+
|
|
133
|
+
const conflict = await hook.getConflict(); // [!code highlight]
|
|
134
|
+
if (conflict) { // [!code highlight]
|
|
135
|
+
// Another active workflow run already owns this token.
|
|
136
|
+
return { dedupedTo: conflict.runId };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
await chargeOrder(orderId);
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Because `createHook()` alone does not suspend the workflow, awaiting `hook.getConflict()` is what actually suspends the run and commits the hook registration. It only waits for registration — to receive payload data from a future `resumeHook()` call, await the hook itself or iterate it with `for await...of`.
|
|
144
|
+
|
|
145
|
+
On a conflict, the resolved value is `{ runId }` identifying the run that currently owns the token. To act on the owner — inspect its status, wait for its result, or cancel it — pass `conflict.runId` to [`getRun()`](/docs/api-reference/workflow-api/get-run) inside a step. See [Idempotency](/docs/foundations/idempotency) for these strategies in context.
|
|
146
|
+
|
|
115
147
|
### Waiting for Multiple Payloads
|
|
116
148
|
|
|
117
149
|
You can also wait for multiple payloads by using the `for await...of` syntax.
|
|
@@ -55,6 +55,7 @@ The returned `Webhook` object has:
|
|
|
55
55
|
|
|
56
56
|
- `url`: The HTTP endpoint URL that external systems can call
|
|
57
57
|
- `token`: The unique token identifying this webhook
|
|
58
|
+
- `getConflict()`: A promise that resolves with `{ runId }` identifying the conflicting run if another active hook already owns this token, or `null` once the webhook endpoint has been registered
|
|
58
59
|
- Implements `AsyncIterable<RequestWithResponse>` for handling multiple requests
|
|
59
60
|
|
|
60
61
|
The `RequestWithResponse` type extends the standard `Request` interface with a `respondWith(response: Response)` method for sending custom responses back to the caller.
|
|
@@ -254,6 +254,45 @@ export default function ChatWithCustomConfig() {
|
|
|
254
254
|
}
|
|
255
255
|
```
|
|
256
256
|
|
|
257
|
+
## Mid-part resumes
|
|
258
|
+
|
|
259
|
+
A workflow stream is a flat sequence of chunks, but the AI SDK's 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
|
+
|
|
257
296
|
## See Also
|
|
258
297
|
|
|
259
298
|
- [DurableAgent](/docs/api-reference/workflow-ai/durable-agent) - Building durable AI agents within workflows
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "workflow/api"
|
|
3
|
-
description: Runtime functions to inspect runs, start workflows, and
|
|
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
|
---
|
|
@@ -9,7 +9,7 @@ API reference for runtime functions from the `workflow/api` package.
|
|
|
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,
|
|
12
|
+
The API package is for access and introspection of workflow data to inspect runs, start new runs, and manage hooks.
|
|
13
13
|
|
|
14
14
|
<Cards>
|
|
15
15
|
<Card href="/docs/api-reference/workflow-api/start" title="start()">
|
|
@@ -27,10 +27,8 @@ The API package is for access and introspection of workflow data to inspect runs
|
|
|
27
27
|
<Card href="/docs/api-reference/workflow-api/get-run" title="getRun()">
|
|
28
28
|
Get workflow run status and metadata without waiting for completion.
|
|
29
29
|
</Card>
|
|
30
|
-
<Card href="/docs/api-reference/workflow-api/get-world" title="getWorld()">
|
|
31
|
-
Get direct access to workflow 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
30
|
</Cards>
|
|
31
|
+
|
|
32
|
+
<Callout type="info">
|
|
33
|
+
Looking for `getWorld()` and the World SDK? They are exported from `workflow/runtime` — see the [`workflow/runtime` reference](/docs/api-reference/workflow-runtime).
|
|
34
|
+
</Callout>
|
|
@@ -97,6 +97,8 @@ const run = await start(myWorkflow, ["arg1", "arg2"], { // [!code highlight]
|
|
|
97
97
|
|
|
98
98
|
<Callout type="info">
|
|
99
99
|
The `deploymentId` option is currently a Vercel-specific feature. Other Worlds may implement this option differently to match their own deployment runtimes, and the World spec may rename it from `deploymentId` to `version` in a future SDK version. On Vercel, `"latest"` resolves to the most recent deployment matching your current environment — the same production target for production deployments, or the same git branch for preview deployments.
|
|
100
|
+
|
|
101
|
+
In Worlds without atomic, immutable deployments (such as local development or self-hosted Postgres), there is no notion of multiple deployments to resolve between, so `deploymentId: "latest"` has no effect: the SDK logs a warning and the run targets the current deployment. This means a workflow that opts into `"latest"` on Vercel still runs unchanged in local development.
|
|
100
102
|
</Callout>
|
|
101
103
|
|
|
102
104
|
<Callout type="warn">
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "workflow/errors",
|
|
3
3
|
"pages": [
|
|
4
|
+
"workflow-error",
|
|
4
5
|
"hook-not-found-error",
|
|
6
|
+
"hook-conflict-error",
|
|
5
7
|
"step-not-registered-error",
|
|
6
8
|
"workflow-not-registered-error",
|
|
7
9
|
"workflow-run-not-found-error",
|
|
8
10
|
"workflow-run-failed-error",
|
|
9
11
|
"workflow-run-cancelled-error",
|
|
12
|
+
"workflow-run-not-completed-error",
|
|
13
|
+
"workflow-runtime-error",
|
|
10
14
|
"workflow-world-error",
|
|
11
15
|
"throttle-error",
|
|
12
16
|
"entity-conflict-error",
|
|
13
17
|
"run-expired-error",
|
|
18
|
+
"run-not-supported-error",
|
|
14
19
|
"too-early-error"
|
|
15
20
|
]
|
|
16
21
|
}
|
|
@@ -31,11 +31,35 @@ export default withWorkflow(nextConfig, workflowConfig); // [!code highlight]
|
|
|
31
31
|
If a package in `serverExternalPackages` contains workflow code (`"use step"`,
|
|
32
32
|
`"use workflow"`, or serialization classes), `withWorkflow()` automatically
|
|
33
33
|
removes it from `serverExternalPackages` for the current build and prints a
|
|
34
|
-
warning.
|
|
35
|
-
|
|
34
|
+
warning. Workflow still compiles the package so its directives are transformed.
|
|
35
|
+
Remove that package from `serverExternalPackages` in your
|
|
36
36
|
`next.config` to silence the warning.
|
|
37
37
|
</Callout>
|
|
38
38
|
|
|
39
|
+
### Workflow Discovery in Next.js
|
|
40
|
+
|
|
41
|
+
`withWorkflow()` discovers workflows by scanning your Next.js entrypoints — App
|
|
42
|
+
Router `route`, `page`, and `layout` files (under `app/` or `src/app/`) and any
|
|
43
|
+
file under `pages/` or `src/pages/` — for `start()` calls imported from
|
|
44
|
+
`workflow/api`. The workflow and step files themselves can live anywhere (for
|
|
45
|
+
example `src/workflows/`); they are discovered transitively through imports, as
|
|
46
|
+
long as a `start()` call in an entrypoint statically reaches them.
|
|
47
|
+
|
|
48
|
+
<Callout type="info">
|
|
49
|
+
Call `start()` from server-side entrypoints, including Route Handlers and Server
|
|
50
|
+
Actions. Don't call workflow functions directly — that bypasses the workflow
|
|
51
|
+
runtime.
|
|
52
|
+
</Callout>
|
|
53
|
+
|
|
54
|
+
### Next.js Server Actions and `"use server"`
|
|
55
|
+
|
|
56
|
+
Don't put a top-level `"use server"` directive in modules imported by workflow
|
|
57
|
+
or step functions. Workflow transformation wraps imported modules in synchronous
|
|
58
|
+
initializers, and Next.js rejects a `"use server"` directive inside that wrapper
|
|
59
|
+
with errors like `Server Actions must be async functions`. Keep `"use server"`
|
|
60
|
+
on the files that define your Server Actions, and move shared logic into
|
|
61
|
+
separate modules that don't carry the directive.
|
|
62
|
+
|
|
39
63
|
### Monorepos and Workspace Imports
|
|
40
64
|
|
|
41
65
|
By default, Next.js detects the correct workspace root automatically. If your Next.js app lives in a subdirectory such as `apps/web` and workspace resolution is not working correctly, you can set `outputFileTracingRoot` as a workaround:
|
|
@@ -68,7 +92,6 @@ const nextConfig: NextConfig = {};
|
|
|
68
92
|
|
|
69
93
|
export default withWorkflow(nextConfig, {
|
|
70
94
|
workflows: {
|
|
71
|
-
lazyDiscovery: true,
|
|
72
95
|
local: {
|
|
73
96
|
port: 4000,
|
|
74
97
|
},
|
|
@@ -78,7 +101,6 @@ export default withWorkflow(nextConfig, {
|
|
|
78
101
|
|
|
79
102
|
| Option | Type | Default | Description |
|
|
80
103
|
| --- | --- | --- | --- |
|
|
81
|
-
| `workflows.lazyDiscovery` | `boolean` | `false` | When `true`, defers workflow discovery until files are requested instead of scanning eagerly at startup. Useful for large projects where startup time matters. |
|
|
82
104
|
| `workflows.local.port` | `number` | — | Overrides the `PORT` environment variable for local development. Has no effect when deployed to Vercel. |
|
|
83
105
|
|
|
84
106
|
<Callout type="info">
|
|
@@ -6,7 +6,6 @@ A symbol used to define custom deserialization for user-defined class instances.
|
|
|
6
6
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
9
|
-
{/* @expect-error:2351 */}
|
|
10
9
|
|
|
11
10
|
```typescript lineNumbers
|
|
12
11
|
import { WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from "@workflow/serde";
|
|
@@ -26,7 +25,7 @@ class Point {
|
|
|
26
25
|
|
|
27
26
|
## API Signature
|
|
28
27
|
|
|
29
|
-
{/* @skip-typecheck */}
|
|
28
|
+
{/* @skip-typecheck: type-only signature snippet, not compilable code */}
|
|
30
29
|
|
|
31
30
|
```typescript
|
|
32
31
|
static [WORKFLOW_DESERIALIZE](data: SerializableData): T
|
|
@@ -6,7 +6,6 @@ A symbol used to define custom serialization for user-defined class instances. T
|
|
|
6
6
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
9
|
-
{/* @expect-error:2351 */}
|
|
10
9
|
|
|
11
10
|
```typescript lineNumbers
|
|
12
11
|
import { WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from "@workflow/serde";
|
|
@@ -26,7 +25,7 @@ class Point {
|
|
|
26
25
|
|
|
27
26
|
## API Signature
|
|
28
27
|
|
|
29
|
-
{/* @skip-typecheck */}
|
|
28
|
+
{/* @skip-typecheck: type-only signature snippet, not compilable code */}
|
|
30
29
|
|
|
31
30
|
```typescript
|
|
32
31
|
static [WORKFLOW_SERIALIZE](instance: T): SerializableData
|
|
@@ -31,10 +31,42 @@ WORKFLOW_POSTGRES_URL="postgres://user:password@host:5432/database"
|
|
|
31
31
|
|
|
32
32
|
Run the migration script to create the necessary tables in your database. Ensure `WORKFLOW_POSTGRES_URL` is set when running this command:
|
|
33
33
|
|
|
34
|
+
<Tabs items={["npm", "pnpm", "Yarn", "Bun"]}>
|
|
35
|
+
|
|
36
|
+
<Tab value="npm">
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx --package=@workflow/world-postgres bootstrap
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
</Tab>
|
|
43
|
+
|
|
44
|
+
<Tab value="pnpm">
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pnpm dlx --package @workflow/world-postgres bootstrap
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
</Tab>
|
|
51
|
+
|
|
52
|
+
<Tab value="Yarn">
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
yarn dlx --package @workflow/world-postgres bootstrap
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
</Tab>
|
|
59
|
+
|
|
60
|
+
<Tab value="Bun">
|
|
61
|
+
|
|
34
62
|
```bash
|
|
35
|
-
|
|
63
|
+
bunx --package @workflow/world-postgres bootstrap
|
|
36
64
|
```
|
|
37
65
|
|
|
66
|
+
</Tab>
|
|
67
|
+
|
|
68
|
+
</Tabs>
|
|
69
|
+
|
|
38
70
|
<Callout type="info">
|
|
39
71
|
The migration is idempotent and can safely be run as a post-deployment lifecycle script.
|
|
40
72
|
</Callout>
|
|
@@ -48,6 +48,8 @@ For self-hosted deployments, use the [Postgres World](/worlds/postgres). For loc
|
|
|
48
48
|
|
|
49
49
|
- **Data residency** - The Vercel World is currently deployed in the `iad1` region. This means independently of the deployment location of your application, the data for your workflows will be stored in the `iad1` region.
|
|
50
50
|
|
|
51
|
+
- **Stream routes need `supportsCancellation`** - Routes that pipe `run.getReadable()` back to a client keep running — and billing — until the function's max duration, even after the client disconnects. Set [`supportsCancellation`](https://vercel.com/docs/functions/request-cancellation) in `vercel.json` for those routes so client aborts tear the invocation down. See [Streaming — Resuming Streams from a Specific Point](/docs/foundations/streaming#resuming-streams-from-a-specific-point).
|
|
52
|
+
|
|
51
53
|
## Observability
|
|
52
54
|
|
|
53
55
|
Workflow observability is built into the Vercel dashboard on your project page. It respects your existing authentication and project permission settings.
|
package/docs/errors/index.mdx
CHANGED
|
@@ -43,6 +43,9 @@ Fix common mistakes when creating and executing workflows in the **Workflow SDK*
|
|
|
43
43
|
<Card href="/docs/errors/step-not-registered" title="step-not-registered">
|
|
44
44
|
Resolve step not registered errors caused by deployment mismatches.
|
|
45
45
|
</Card>
|
|
46
|
+
<Card href="/docs/errors/step-executed-multiple-times" title="Step executed multiple times">
|
|
47
|
+
Diagnose duplicate step_started events from function crashes, timeouts, or OOMs.
|
|
48
|
+
</Card>
|
|
46
49
|
<Card href="/docs/errors/workflow-not-registered" title="workflow-not-registered">
|
|
47
50
|
Resolve workflow not registered errors caused by deployment mismatches.
|
|
48
51
|
</Card>
|
|
@@ -85,6 +85,35 @@ The key points:
|
|
|
85
85
|
- You need the hook's `token` to resume it
|
|
86
86
|
- The workflow will resume execution right where it left off
|
|
87
87
|
|
|
88
|
+
### Checking for Token Conflicts
|
|
89
|
+
|
|
90
|
+
Sometimes you need to know that a hook token has been claimed, but you do not want to wait for external data yet. Await `hook.getConflict()` (available starting in `workflow@4.5.0`) for that:
|
|
91
|
+
|
|
92
|
+
```typescript lineNumbers
|
|
93
|
+
import { createHook } from "workflow";
|
|
94
|
+
|
|
95
|
+
declare function processOrder(orderId: string): Promise<void>; // @setup
|
|
96
|
+
|
|
97
|
+
export async function orderWorkflow(orderId: string) {
|
|
98
|
+
"use workflow";
|
|
99
|
+
|
|
100
|
+
using hook = createHook({
|
|
101
|
+
token: `order:${orderId}`
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const conflict = await hook.getConflict(); // [!code highlight]
|
|
105
|
+
if (conflict) { // [!code highlight]
|
|
106
|
+
// Another active run already owns this token.
|
|
107
|
+
return { dedupedTo: conflict.runId };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// The hook token is registered and reserved here.
|
|
111
|
+
await processOrder(orderId);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Calling `createHook()` on its own does not register the hook — registration is only committed when the workflow suspends. Awaiting `hook.getConflict()` suspends the workflow to commit the hook registration, then resolves with `null` once the hook is registered and ready to receive payloads, or with `{ runId }` identifying the run that owns the token if another active hook already claimed it (see [`HookConflictError`](/docs/errors/hook-conflict)). For `hook_conflict` events persisted by older worlds that did not record the owning run's ID, `getConflict()` rejects with `HookConflictError` instead of resolving with an incomplete handle. To act on the owner — inspect its status, wait for its result, or cancel it — pass `conflict.runId` to [`getRun()`](/docs/api-reference/workflow-api/get-run) inside a step. See [Idempotency](/docs/foundations/idempotency) for these strategies.
|
|
116
|
+
|
|
88
117
|
### Custom Tokens for Deterministic Hooks
|
|
89
118
|
|
|
90
119
|
By default, hooks generate a random token. However, you often want to use a **custom token** that external systems can reconstruct. This is especially useful for long-running workflows where the same workflow instance should handle multiple events.
|
|
@@ -87,6 +87,12 @@ export async function GET(
|
|
|
87
87
|
|
|
88
88
|
This allows clients to reconnect and continue receiving data from where they left off, rather than restarting from the beginning.
|
|
89
89
|
|
|
90
|
+
<Callout type="warn">
|
|
91
|
+
**Vercel: long-lived stream routes need `supportsCancellation`**
|
|
92
|
+
|
|
93
|
+
When a route like the one above pipes `run.getReadable()` out to a client on Vercel, the function keeps running — and billing — until the function's configured max duration, even after the client disconnects. Set [`supportsCancellation`](https://vercel.com/docs/functions/request-cancellation) in `vercel.json` for routes that stream workflow output so Vercel forwards the client abort signal and tears the invocation down when the client goes away.
|
|
94
|
+
</Callout>
|
|
95
|
+
|
|
90
96
|
`startIndex` also supports **negative values** to read relative to the end of the stream. For example, `startIndex: -5` starts 5 chunks before the current end. This is useful when you want to show the most recent output without reading the entire stream history.
|
|
91
97
|
|
|
92
98
|
On an active (not-yet-closed) stream, the negative index resolves relative to the chunk count at connection time; any chunks written afterward are still delivered normally.
|
|
@@ -593,7 +599,7 @@ Stream errors don't trigger automatic retries for the producer step. Design your
|
|
|
593
599
|
- [`sleep()` API Reference](/docs/api-reference/workflow/sleep) - Pause workflow execution for a duration
|
|
594
600
|
- [`start()` API Reference](/docs/api-reference/workflow-api/start) - Start workflows and access the `Run` object
|
|
595
601
|
- [`getRun()` API Reference](/docs/api-reference/workflow-api/get-run) - Retrieve runs and their streams later
|
|
596
|
-
- [world.streams](/docs/api-reference/workflow-
|
|
602
|
+
- [world.streams](/docs/api-reference/workflow-runtime/world/streams) - Low-level stream read/write/close via World SDK
|
|
597
603
|
- [DurableAgent](/docs/api-reference/workflow-ai/durable-agent) - AI agents with built-in streaming support
|
|
598
604
|
- [Errors and Retries](/docs/foundations/errors-and-retries) - Understanding error handling and retry behavior
|
|
599
605
|
- [Serialization](/docs/foundations/serialization) - Understanding what data types can be passed in workflows
|
|
@@ -93,7 +93,7 @@ npx workflow cancel \
|
|
|
93
93
|
--backend vercel
|
|
94
94
|
```
|
|
95
95
|
|
|
96
|
-
The `--workflowName` filter expects the generated workflow ID, not only the exported function's short name. Use the `workflowName` value from `workflow inspect runs`, and use [`parseWorkflowName()`](/docs/api-reference/workflow-
|
|
96
|
+
The `--workflowName` filter expects the generated workflow ID, not only the exported function's short name. Use the `workflowName` value from `workflow inspect runs`, and use [`parseWorkflowName()`](/docs/api-reference/workflow-observability/parse-workflow-name) when you need display-friendly names.
|
|
97
97
|
|
|
98
98
|
In the [observability UI](/docs/observability), use **Rerun on latest** to enqueue the workflow again with the same inputs against the latest deployment.
|
|
99
99
|
|
|
@@ -105,8 +105,8 @@ To add encryption support to a custom `World`:
|
|
|
105
105
|
import type { WorkflowRun, World } from "@workflow/world";
|
|
106
106
|
|
|
107
107
|
export const getEncryptionKeyForRun: World["getEncryptionKeyForRun"] = async (
|
|
108
|
-
run,
|
|
109
|
-
context
|
|
108
|
+
run: WorkflowRun | string,
|
|
109
|
+
context?: Record<string, unknown>
|
|
110
110
|
) => {
|
|
111
111
|
const runId = typeof run === "string" ? run : run.runId;
|
|
112
112
|
const deploymentId =
|
|
@@ -127,7 +127,7 @@ flowchart TD
|
|
|
127
127
|
|
|
128
128
|
Unlike other entities, hooks don't have a `status` field—the states above are conceptual. An "active" hook is one that exists in storage, while "disposed" means the hook has been deleted. When a `hook_disposed` event is created, the hook record is removed rather than updated.
|
|
129
129
|
|
|
130
|
-
While a hook is active, its token is reserved and cannot be used by other workflows. If a workflow attempts to create a hook with a token that is already in use by another active hook, a `hook_conflict` event is recorded instead of `hook_created`. Current worlds include the token and the run ID that currently owns it, though older persisted events or world implementations may only include the token. This causes the hook's promise to reject with a `HookConflictError`, which you can detect with `HookConflictError.is(error)`. See the [hook-conflict error](/docs/errors/hook-conflict) documentation for more details.
|
|
130
|
+
While a hook is active, its token is reserved and cannot be used by other workflows. If a workflow attempts to create a hook with a token that is already in use by another active hook, a `hook_conflict` event is recorded instead of `hook_created`. Current worlds include the token and the run ID that currently owns it, though older persisted events or world implementations may only include the token. This causes `hook.getConflict()` to resolve with the conflicting run and the hook's payload promise to reject with a `HookConflictError`, which you can detect with `HookConflictError.is(error)`. See the [hook-conflict error](/docs/errors/hook-conflict) documentation for more details.
|
|
131
131
|
|
|
132
132
|
When a hook is disposed (either explicitly or when its workflow completes), the token is released and can be claimed by future workflows. Hooks are automatically disposed when a workflow reaches a terminal state (`completed`, `failed`, or `cancelled`). The `hook_disposed` event is only needed for explicit disposal before workflow completion.
|
|
133
133
|
|
|
@@ -188,7 +188,7 @@ Events are categorized by the entity type they affect. Each event contains metad
|
|
|
188
188
|
| Event | Description |
|
|
189
189
|
|-------|-------------|
|
|
190
190
|
| `hook_created` | Creates a new hook in `active` state. Contains the hook token and optional metadata. |
|
|
191
|
-
| `hook_conflict` | Records that hook creation failed because the token is already in use by another active hook. Contains the token and, for current worlds, the active hook owner's run ID. The hook is not created, and awaiting the hook
|
|
191
|
+
| `hook_conflict` | Records that hook creation failed because the token is already in use by another active hook. Contains the token and, for current worlds, the active hook owner's run ID. The hook is not created: `hook.getConflict()` resolves with the conflicting run, and awaiting the hook payload rejects with a `HookConflictError`. |
|
|
192
192
|
| `hook_received` | Records that a payload was delivered to the hook. The hook remains `active` and can receive more payloads. |
|
|
193
193
|
| `hook_disposed` | Deletes the hook from storage (conceptually transitioning to `disposed` state). The token is released for reuse by future workflows. |
|
|
194
194
|
|
|
@@ -42,6 +42,19 @@ npx workflow inspect runs --web
|
|
|
42
42
|
|
|
43
43
|

|
|
44
44
|
|
|
45
|
+
To share a link to a specific run without opening a browser, use the `--url`
|
|
46
|
+
flag. It prints the dashboard deep link to stdout and exits (no browser, no
|
|
47
|
+
local server) — useful for scripts, PR comments, or automation. Add `--json` to
|
|
48
|
+
get `{ "url": "..." }`.
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Print the deep-link URL for a run (no browser, no server)
|
|
52
|
+
npx workflow inspect run <run_id> --url
|
|
53
|
+
|
|
54
|
+
# Vercel runs: add the backend (and --env preview for preview deployments)
|
|
55
|
+
npx workflow inspect run <run_id> --backend vercel --url
|
|
56
|
+
```
|
|
57
|
+
|
|
45
58
|
## Backends
|
|
46
59
|
|
|
47
60
|
The Workflow SDK CLI can inspect data from any [World](/docs/deploying). By default, it inspects data in your local development environment. For example, if you are using Next.js to develop workflows locally, the
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "workflow/astro"
|
|
3
|
+
description: Astro integration for automatic workflow bundling and route registration.
|
|
4
|
+
type: overview
|
|
5
|
+
summary: Explore the Astro integration for automatic workflow bundling and runtime support.
|
|
6
|
+
related:
|
|
7
|
+
- /docs/getting-started/astro
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Astro integration for Workflow SDK that transforms workflow code and builds the workflow bundles.
|
|
11
|
+
|
|
12
|
+
## Functions
|
|
13
|
+
|
|
14
|
+
<Cards>
|
|
15
|
+
<Card title="workflow()" href="/docs/api-reference/workflow-astro/workflow">
|
|
16
|
+
Astro integration that transforms workflow code (`"use step"`/`"use workflow"` directives)
|
|
17
|
+
</Card>
|
|
18
|
+
</Cards>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: workflow
|
|
3
|
+
description: Configure Astro to transform workflow directives.
|
|
4
|
+
type: reference
|
|
5
|
+
summary: Add the workflow integration to your Astro config to enable workflow directive transformation.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/getting-started/astro
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Returns an Astro integration that transforms workflow code (`"use step"`/`"use workflow"` directives) and builds the workflow bundles.
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
To enable `"use step"` and `"use workflow"` directives while developing locally or deploying to production, add `workflow()` to the `integrations` array of your Astro config.
|
|
15
|
+
|
|
16
|
+
```typescript title="astro.config.mjs" lineNumbers
|
|
17
|
+
// @ts-check
|
|
18
|
+
import { defineConfig } from "astro/config";
|
|
19
|
+
import { workflow } from "workflow/astro"; // [!code highlight]
|
|
20
|
+
|
|
21
|
+
// https://astro.build/config
|
|
22
|
+
export default defineConfig({
|
|
23
|
+
integrations: [workflow()], // [!code highlight]
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The integration registers the workflow Vite transform plugins during `astro:config:setup` and builds the workflow bundles — locally during config setup, or via the Vercel builder after `astro:build:done` when deploying to Vercel.
|
|
28
|
+
|
|
29
|
+
## API Signature
|
|
30
|
+
|
|
31
|
+
### Parameters
|
|
32
|
+
|
|
33
|
+
This function does not accept any parameters in workflow 4.x. (5.x adds an options object with a `sourcemap` setting.)
|
|
34
|
+
|
|
35
|
+
### Returns
|
|
36
|
+
|
|
37
|
+
Returns an `AstroIntegration` object to include in the `integrations` array of your Astro config.
|