workflow 4.2.0-beta.73 → 4.2.0-beta.75
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/README.md +6 -6
- package/docs/ai/defining-tools.mdx +2 -2
- package/docs/ai/human-in-the-loop.mdx +1 -1
- package/docs/ai/index.mdx +8 -8
- package/docs/ai/resumable-streams.mdx +1 -1
- package/docs/ai/sleep-and-delays.mdx +2 -2
- package/docs/ai/streaming-updates-from-tools.mdx +1 -1
- package/docs/api-reference/index.mdx +9 -3
- package/docs/api-reference/meta.json +10 -1
- package/docs/api-reference/workflow/create-webhook.mdx +4 -0
- package/docs/api-reference/workflow/index.mdx +2 -2
- package/docs/api-reference/workflow-ai/durable-agent.mdx +1 -1
- package/docs/api-reference/workflow-api/get-world.mdx +33 -157
- package/docs/api-reference/workflow-api/index.mdx +3 -0
- package/docs/api-reference/workflow-api/world/events.mdx +227 -0
- package/docs/api-reference/workflow-api/world/hooks.mdx +181 -0
- package/docs/api-reference/workflow-api/world/index.mdx +67 -0
- package/docs/api-reference/workflow-api/world/meta.json +12 -0
- package/docs/api-reference/workflow-api/world/observability.mdx +289 -0
- package/docs/api-reference/workflow-api/world/queue.mdx +127 -0
- package/docs/api-reference/workflow-api/world/runs.mdx +223 -0
- package/docs/api-reference/workflow-api/world/steps.mdx +216 -0
- package/docs/api-reference/workflow-api/world/streams.mdx +152 -0
- package/docs/api-reference/workflow-globals.mdx +102 -0
- package/docs/api-reference/workflow-next/index.mdx +1 -1
- package/docs/api-reference/workflow-serde/index.mdx +2 -2
- package/docs/changelog/index.mdx +2 -2
- package/docs/deploying/building-a-world.mdx +1 -1
- package/docs/deploying/world/vercel-world.mdx +20 -13
- package/docs/errors/index.mdx +1 -1
- package/docs/errors/node-js-module-in-workflow.mdx +1 -1
- package/docs/errors/serialization-failed.mdx +1 -1
- package/docs/errors/start-invalid-workflow-function.mdx +3 -3
- package/docs/foundations/errors-and-retries.mdx +1 -1
- package/docs/foundations/hooks.mdx +5 -1
- package/docs/foundations/serialization.mdx +2 -2
- package/docs/foundations/streaming.mdx +3 -2
- package/docs/foundations/workflows-and-steps.mdx +2 -2
- package/docs/getting-started/astro.mdx +5 -5
- package/docs/getting-started/express.mdx +5 -5
- package/docs/getting-started/fastify.mdx +5 -5
- package/docs/getting-started/hono.mdx +5 -5
- package/docs/getting-started/nestjs.mdx +5 -5
- package/docs/getting-started/next.mdx +5 -5
- package/docs/getting-started/nitro.mdx +5 -5
- package/docs/getting-started/nuxt.mdx +5 -5
- package/docs/getting-started/sveltekit.mdx +5 -5
- package/docs/getting-started/vite.mdx +5 -5
- package/docs/how-it-works/code-transform.mdx +6 -6
- package/docs/how-it-works/encryption.mdx +3 -3
- package/docs/how-it-works/event-sourcing.mdx +5 -5
- package/docs/how-it-works/framework-integrations.mdx +9 -9
- package/docs/how-it-works/understanding-directives.mdx +11 -11
- package/docs/observability/index.mdx +5 -5
- package/docs/testing/index.mdx +4 -4
- package/package.json +12 -12
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: world.steps
|
|
3
|
+
description: List and inspect workflow step execution data with input/output hydration.
|
|
4
|
+
type: reference
|
|
5
|
+
summary: "Methods: get(), list(). Query step metadata, hydrate serialized I/O, calculate durations."
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/api-reference/workflow-api/get-world
|
|
8
|
+
related:
|
|
9
|
+
- /docs/api-reference/workflow-api/world/runs
|
|
10
|
+
- /docs/api-reference/workflow-api/world/observability
|
|
11
|
+
keywords:
|
|
12
|
+
- world.steps
|
|
13
|
+
- world.steps.get
|
|
14
|
+
- world.steps.list
|
|
15
|
+
- Step
|
|
16
|
+
- step input output
|
|
17
|
+
- hydrateResourceIO
|
|
18
|
+
- step duration
|
|
19
|
+
- resolveData
|
|
20
|
+
- parseStepName
|
|
21
|
+
- devalue serialization
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
The `world.steps` interface provides access to individual step execution data within workflow runs. Use it to list steps, inspect their input/output, and build progress dashboards.
|
|
25
|
+
|
|
26
|
+
## Import
|
|
27
|
+
|
|
28
|
+
```typescript lineNumbers
|
|
29
|
+
import { getWorld } from "workflow/runtime";
|
|
30
|
+
|
|
31
|
+
const world = getWorld();
|
|
32
|
+
const steps = world.steps; // [!code highlight]
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Methods
|
|
36
|
+
|
|
37
|
+
### get()
|
|
38
|
+
|
|
39
|
+
Retrieve a single step by run ID and step ID.
|
|
40
|
+
|
|
41
|
+
```typescript lineNumbers
|
|
42
|
+
const step = await world.steps.get(runId, stepId); // [!code highlight]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Parameters:**
|
|
46
|
+
|
|
47
|
+
| Parameter | Type | Description |
|
|
48
|
+
|-----------|------|-------------|
|
|
49
|
+
| `runId` | `string` | The workflow run ID |
|
|
50
|
+
| `stepId` | `string` | The step ID |
|
|
51
|
+
| `params.resolveData` | `'all' \| 'none'` | Whether to hydrate input/output data. Default: `'all'` |
|
|
52
|
+
|
|
53
|
+
**Returns:** `Step`
|
|
54
|
+
|
|
55
|
+
### list()
|
|
56
|
+
|
|
57
|
+
List steps with cursor pagination.
|
|
58
|
+
|
|
59
|
+
```typescript lineNumbers
|
|
60
|
+
const result = await world.steps.list({ // [!code highlight]
|
|
61
|
+
runId,
|
|
62
|
+
pagination: { cursor },
|
|
63
|
+
}); // [!code highlight]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Parameters:**
|
|
67
|
+
|
|
68
|
+
| Parameter | Type | Description |
|
|
69
|
+
|-----------|------|-------------|
|
|
70
|
+
| `params.runId` | `string` | Filter steps by run ID |
|
|
71
|
+
| `params.pagination.cursor` | `string` | Cursor for the next page |
|
|
72
|
+
| `params.resolveData` | `'all' \| 'none'` | Whether to hydrate input/output data |
|
|
73
|
+
|
|
74
|
+
**Returns:** `{ data: Step[], cursor?: string }`
|
|
75
|
+
|
|
76
|
+
## Types
|
|
77
|
+
|
|
78
|
+
### Step
|
|
79
|
+
|
|
80
|
+
| Field | Type | Description |
|
|
81
|
+
|-------|------|-------------|
|
|
82
|
+
| `runId` | `string` | Parent workflow run ID |
|
|
83
|
+
| `stepId` | `string` | Unique step identifier |
|
|
84
|
+
| `stepName` | `string` | Machine-readable step identifier |
|
|
85
|
+
| `status` | `string` | Step status: `'running'`, `'completed'`, `'failed'` |
|
|
86
|
+
| `input` | `any` | Step input data (when `resolveData: 'all'`) |
|
|
87
|
+
| `output` | `any` | Step output data (when `resolveData: 'all'`) |
|
|
88
|
+
| `error` | `any` | Error data if the step failed |
|
|
89
|
+
| `attempt` | `number` | Current retry attempt number |
|
|
90
|
+
| `startedAt` | `string` | ISO timestamp when the step started |
|
|
91
|
+
| `completedAt` | `string \| null` | ISO timestamp when the step completed |
|
|
92
|
+
| `retryAfter` | `string \| null` | ISO timestamp for next retry attempt |
|
|
93
|
+
|
|
94
|
+
<Callout type="info">
|
|
95
|
+
Step I/O is serialized using the [devalue](https://github.com/Rich-Harris/devalue) format. Use `hydrateResourceIO()` from `workflow/observability` to deserialize it for display. See [Observability Utilities](/docs/api-reference/workflow-api/world/observability).
|
|
96
|
+
</Callout>
|
|
97
|
+
|
|
98
|
+
## Examples
|
|
99
|
+
|
|
100
|
+
### List Steps for a Run without Data
|
|
101
|
+
|
|
102
|
+
Use `resolveData: 'none'` to efficiently get step metadata for progress dashboards:
|
|
103
|
+
|
|
104
|
+
```typescript lineNumbers
|
|
105
|
+
// app/api/workflow-steps/route.ts
|
|
106
|
+
import { getWorld } from "workflow/runtime";
|
|
107
|
+
import { parseStepName } from "workflow/observability"; // [!code highlight]
|
|
108
|
+
|
|
109
|
+
export async function GET(req: Request) {
|
|
110
|
+
const url = new URL(req.url);
|
|
111
|
+
const runId = url.searchParams.get("runId");
|
|
112
|
+
|
|
113
|
+
if (!runId) {
|
|
114
|
+
return Response.json({ error: "runId required" }, { status: 400 });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const world = getWorld();
|
|
118
|
+
const steps = await world.steps.list({ // [!code highlight]
|
|
119
|
+
runId,
|
|
120
|
+
resolveData: "none", // Skip I/O for performance // [!code highlight]
|
|
121
|
+
}); // [!code highlight]
|
|
122
|
+
|
|
123
|
+
const progress = steps.data.map((step) => {
|
|
124
|
+
const parsed = parseStepName(step.stepName); // [!code highlight]
|
|
125
|
+
return {
|
|
126
|
+
stepId: step.stepId,
|
|
127
|
+
displayName: parsed?.shortName ?? step.stepName, // [!code highlight]
|
|
128
|
+
module: parsed?.moduleSpecifier,
|
|
129
|
+
status: step.status,
|
|
130
|
+
startedAt: step.startedAt,
|
|
131
|
+
completedAt: step.completedAt,
|
|
132
|
+
};
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return Response.json({ progress, cursor: steps.cursor });
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Get Step with Hydrated Input and Output Data
|
|
140
|
+
|
|
141
|
+
Retrieve a step with its full serialized data and hydrate it for display:
|
|
142
|
+
|
|
143
|
+
```typescript lineNumbers
|
|
144
|
+
// app/api/workflow-steps/[stepId]/route.ts
|
|
145
|
+
import { getWorld } from "workflow/runtime";
|
|
146
|
+
import { parseStepName } from "workflow/observability";
|
|
147
|
+
import { // [!code highlight]
|
|
148
|
+
hydrateResourceIO, // [!code highlight]
|
|
149
|
+
observabilityRevivers, // [!code highlight]
|
|
150
|
+
} from "workflow/observability"; // [!code highlight]
|
|
151
|
+
|
|
152
|
+
export async function GET(req: Request) {
|
|
153
|
+
const url = new URL(req.url);
|
|
154
|
+
const runId = url.searchParams.get("runId");
|
|
155
|
+
const stepId = url.searchParams.get("stepId");
|
|
156
|
+
|
|
157
|
+
if (!runId || !stepId) {
|
|
158
|
+
return Response.json({ error: "runId and stepId required" }, { status: 400 });
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const world = getWorld();
|
|
162
|
+
const step = await world.steps.get(runId, stepId); // [!code highlight]
|
|
163
|
+
|
|
164
|
+
const hydrated = hydrateResourceIO(step, observabilityRevivers); // [!code highlight]
|
|
165
|
+
const parsed = parseStepName(step.stepName);
|
|
166
|
+
|
|
167
|
+
return Response.json({
|
|
168
|
+
stepId: hydrated.stepId,
|
|
169
|
+
displayName: parsed?.shortName ?? step.stepName,
|
|
170
|
+
status: hydrated.status,
|
|
171
|
+
attempt: hydrated.attempt,
|
|
172
|
+
input: hydrated.input, // [!code highlight]
|
|
173
|
+
output: hydrated.output, // [!code highlight]
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Calculate Step Duration from Timestamps
|
|
179
|
+
|
|
180
|
+
```typescript lineNumbers
|
|
181
|
+
import { getWorld } from "workflow/runtime";
|
|
182
|
+
|
|
183
|
+
const world = getWorld();
|
|
184
|
+
const steps = await world.steps.list({ runId });
|
|
185
|
+
|
|
186
|
+
for (const step of steps.data) {
|
|
187
|
+
if (step.completedAt) {
|
|
188
|
+
const start = new Date(step.startedAt).getTime();
|
|
189
|
+
const end = new Date(step.completedAt).getTime();
|
|
190
|
+
const durationMs = end - start; // [!code highlight]
|
|
191
|
+
console.log(`${step.stepName}: ${durationMs}ms`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Parse Step Display Name from Machine-Readable ID
|
|
197
|
+
|
|
198
|
+
The `stepName` field contains a machine-readable identifier like `step//./src/workflows/order//processPayment`. Use `parseStepName()` to extract display-friendly names:
|
|
199
|
+
|
|
200
|
+
```typescript lineNumbers
|
|
201
|
+
import { parseStepName } from "workflow/observability"; // [!code highlight]
|
|
202
|
+
|
|
203
|
+
const parsed = parseStepName(step.stepName); // [!code highlight]
|
|
204
|
+
// parsed.shortName → "processPayment"
|
|
205
|
+
// parsed.moduleSpecifier → "./src/workflows/order"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
<Callout type="warn">
|
|
209
|
+
The `stepName` field is a machine-readable identifier, not a display name. Always use `parseStepName()` from `workflow/observability` to extract the `shortName` for UI display.
|
|
210
|
+
</Callout>
|
|
211
|
+
|
|
212
|
+
## Related
|
|
213
|
+
|
|
214
|
+
- [world.runs](/docs/api-reference/workflow-api/world/runs) — List and inspect workflow runs
|
|
215
|
+
- [Observability Utilities](/docs/api-reference/workflow-api/world/observability) — Hydrate step I/O and parse display names
|
|
216
|
+
- [Workflows and Steps](/docs/foundations/workflows-and-steps) — Core concepts for steps
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Streams
|
|
3
|
+
description: Read, write, and manage real-time data streams for workflow runs.
|
|
4
|
+
type: reference
|
|
5
|
+
summary: "Methods: writeToStream(), readFromStream(), closeStream(), listStreamsByRunId(). Stream methods live directly on the world object."
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/api-reference/workflow-api/get-world
|
|
8
|
+
related:
|
|
9
|
+
- /docs/foundations/streaming
|
|
10
|
+
- /docs/api-reference/workflow/get-writable
|
|
11
|
+
keywords:
|
|
12
|
+
- writeToStream
|
|
13
|
+
- readFromStream
|
|
14
|
+
- closeStream
|
|
15
|
+
- listStreamsByRunId
|
|
16
|
+
- Streamer interface
|
|
17
|
+
- real-time streaming
|
|
18
|
+
- stream lifecycle
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
Stream methods live directly on the `world` object returned by `getWorld()`. Use them to write chunks, read streams, and manage stream lifecycle outside of the standard `getWritable()` pattern.
|
|
22
|
+
|
|
23
|
+
<Callout type="info">
|
|
24
|
+
For most streaming use cases, use [`getWritable()`](/docs/api-reference/workflow/get-writable) inside steps. Direct stream methods are for advanced scenarios like building custom stream consumers or managing streams from outside a workflow.
|
|
25
|
+
</Callout>
|
|
26
|
+
|
|
27
|
+
## Import
|
|
28
|
+
|
|
29
|
+
```typescript lineNumbers
|
|
30
|
+
import { getWorld } from "workflow/runtime";
|
|
31
|
+
|
|
32
|
+
const world = getWorld(); // [!code highlight]
|
|
33
|
+
// Stream methods are called directly on world — e.g. world.writeToStream()
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Methods
|
|
37
|
+
|
|
38
|
+
### writeToStream()
|
|
39
|
+
|
|
40
|
+
Write a data chunk to a named stream for a workflow run.
|
|
41
|
+
|
|
42
|
+
```typescript lineNumbers
|
|
43
|
+
await world.writeToStream("default", runId, chunk); // [!code highlight]
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Parameters:**
|
|
47
|
+
|
|
48
|
+
| Parameter | Type | Description |
|
|
49
|
+
|-----------|------|-------------|
|
|
50
|
+
| `name` | `string` | The stream name |
|
|
51
|
+
| `runId` | `string` | The workflow run ID |
|
|
52
|
+
| `chunk` | `string \| Uint8Array` | Data to write to the stream |
|
|
53
|
+
|
|
54
|
+
### readFromStream()
|
|
55
|
+
|
|
56
|
+
Read data from a named stream as a `ReadableStream`. Returns a live stream that waits for new chunks in real time.
|
|
57
|
+
|
|
58
|
+
```typescript lineNumbers
|
|
59
|
+
const readable = await world.readFromStream("default"); // [!code highlight]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Parameters:**
|
|
63
|
+
|
|
64
|
+
| Parameter | Type | Description |
|
|
65
|
+
|-----------|------|-------------|
|
|
66
|
+
| `name` | `string` | The stream name |
|
|
67
|
+
| `startIndex` | `number` | Optional starting index for partial reads. Negative values read from the tail (e.g. `-3` starts 3 chunks from the end). |
|
|
68
|
+
|
|
69
|
+
**Returns:** `ReadableStream<Uint8Array>`
|
|
70
|
+
|
|
71
|
+
### closeStream()
|
|
72
|
+
|
|
73
|
+
Close a stream when done writing.
|
|
74
|
+
|
|
75
|
+
```typescript lineNumbers
|
|
76
|
+
await world.closeStream("default", runId); // [!code highlight]
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Parameters:**
|
|
80
|
+
|
|
81
|
+
| Parameter | Type | Description |
|
|
82
|
+
|-----------|------|-------------|
|
|
83
|
+
| `name` | `string` | The stream name |
|
|
84
|
+
| `runId` | `string` | The workflow run ID |
|
|
85
|
+
|
|
86
|
+
### listStreamsByRunId()
|
|
87
|
+
|
|
88
|
+
List all stream names associated with a workflow run.
|
|
89
|
+
|
|
90
|
+
```typescript lineNumbers
|
|
91
|
+
const streamNames = await world.listStreamsByRunId(runId); // [!code highlight]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Parameters:**
|
|
95
|
+
|
|
96
|
+
| Parameter | Type | Description |
|
|
97
|
+
|-----------|------|-------------|
|
|
98
|
+
| `runId` | `string` | The workflow run ID |
|
|
99
|
+
|
|
100
|
+
**Returns:** `string[]` — Array of stream names
|
|
101
|
+
|
|
102
|
+
## Examples
|
|
103
|
+
|
|
104
|
+
### List All Streams for a Workflow Run
|
|
105
|
+
|
|
106
|
+
```typescript lineNumbers
|
|
107
|
+
// app/api/workflow-streams/route.ts
|
|
108
|
+
import { getWorld } from "workflow/runtime";
|
|
109
|
+
|
|
110
|
+
export async function GET(req: Request) {
|
|
111
|
+
const url = new URL(req.url);
|
|
112
|
+
const runId = url.searchParams.get("runId");
|
|
113
|
+
|
|
114
|
+
if (!runId) {
|
|
115
|
+
return Response.json({ error: "runId required" }, { status: 400 });
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const world = getWorld();
|
|
119
|
+
const streamNames = await world.listStreamsByRunId(runId); // [!code highlight]
|
|
120
|
+
|
|
121
|
+
return Response.json({ streams: streamNames });
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Read a Stream as a Response
|
|
126
|
+
|
|
127
|
+
```typescript lineNumbers
|
|
128
|
+
// app/api/workflow-streams/read/route.ts
|
|
129
|
+
import { getWorld } from "workflow/runtime";
|
|
130
|
+
|
|
131
|
+
export async function GET(req: Request) {
|
|
132
|
+
const url = new URL(req.url);
|
|
133
|
+
const streamName = url.searchParams.get("name");
|
|
134
|
+
|
|
135
|
+
if (!streamName) {
|
|
136
|
+
return Response.json({ error: "name required" }, { status: 400 });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const world = getWorld();
|
|
140
|
+
const readable = await world.readFromStream(streamName); // [!code highlight]
|
|
141
|
+
|
|
142
|
+
return new Response(readable, {
|
|
143
|
+
headers: { "Content-Type": "application/octet-stream" },
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Related
|
|
149
|
+
|
|
150
|
+
- [Streaming](/docs/foundations/streaming) — Core concepts for streaming data from workflows
|
|
151
|
+
- [getWritable()](/docs/api-reference/workflow/get-writable) — The standard way to write to streams from within steps
|
|
152
|
+
- [world.runs](/docs/api-reference/workflow-api/world/runs) — List runs that may have associated streams
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Workflow Globals
|
|
3
|
+
description: Global APIs available inside workflow functions.
|
|
4
|
+
type: reference
|
|
5
|
+
summary: Reference of all global APIs available inside workflow functions.
|
|
6
|
+
prerequisites:
|
|
7
|
+
- /docs/foundations/workflows-and-steps
|
|
8
|
+
related:
|
|
9
|
+
- /docs/errors/node-js-module-in-workflow
|
|
10
|
+
- /docs/errors/fetch-in-workflow
|
|
11
|
+
- /docs/errors/timeout-in-workflow
|
|
12
|
+
- /docs/how-it-works/code-transform
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
Workflow functions run in a restricted environment that prevents access to non-deterministic or side-effecting APIs. This page lists all global APIs available inside `"use workflow"` functions.
|
|
16
|
+
|
|
17
|
+
For full Node.js runtime access, use [step functions](/docs/foundations/workflows-and-steps#step-functions).
|
|
18
|
+
|
|
19
|
+
## Deterministic APIs
|
|
20
|
+
|
|
21
|
+
These APIs are available but are **seeded or fixed** to ensure deterministic behavior across replays.
|
|
22
|
+
|
|
23
|
+
| API | Behavior |
|
|
24
|
+
|-----|----------|
|
|
25
|
+
| [`Math.random()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random) | Seeded random number generator — same seed produces the same sequence every replay |
|
|
26
|
+
| [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) / `Date.now()` / `new Date()` | Returns a fixed timestamp that advances with the workflow's logical clock |
|
|
27
|
+
| [`crypto.getRandomValues()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues) | Seeded — produces deterministic output for a given workflow run |
|
|
28
|
+
| [`crypto.randomUUID()`](https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID) | Seeded — produces deterministic UUIDs for a given workflow run |
|
|
29
|
+
| [`crypto.subtle.digest()`](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest) | Passes through to the real implementation (SHA-256, etc. are deterministic by nature) |
|
|
30
|
+
|
|
31
|
+
<Callout type="info">
|
|
32
|
+
You can safely use `Math.random()`, `Date.now()`, and `crypto.randomUUID()` in workflow functions. The framework ensures these return the same values across replays.
|
|
33
|
+
</Callout>
|
|
34
|
+
|
|
35
|
+
## Web Platform APIs
|
|
36
|
+
|
|
37
|
+
These standard Web APIs are available in workflow functions:
|
|
38
|
+
|
|
39
|
+
- [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers)
|
|
40
|
+
- [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) / [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder)
|
|
41
|
+
- [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL) / [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)
|
|
42
|
+
- [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) / [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) — custom implementations with [special behavior in the workflow context](/docs/foundations/serialization#request--response). Body methods like `.json()` and `.text()` are automatically treated as step invocations.
|
|
43
|
+
- [`console`](https://developer.mozilla.org/en-US/docs/Web/API/console)
|
|
44
|
+
- [`structuredClone`](https://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone)
|
|
45
|
+
- [`atob`](https://developer.mozilla.org/en-US/docs/Web/API/Window/atob) / [`btoa`](https://developer.mozilla.org/en-US/docs/Web/API/Window/btoa)
|
|
46
|
+
|
|
47
|
+
## Environment Variables
|
|
48
|
+
|
|
49
|
+
`process.env` is available as a **read-only, frozen** snapshot of the environment variables at the time the workflow was started. You cannot modify it.
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
export async function myWorkflow() {
|
|
53
|
+
"use workflow";
|
|
54
|
+
|
|
55
|
+
const apiKey = process.env.API_KEY; // works
|
|
56
|
+
process.env.FOO = "bar"; // throws — process.env is frozen
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Binary Data
|
|
61
|
+
|
|
62
|
+
Standard JavaScript typed arrays (`Uint8Array`, `Int32Array`, `Float64Array`, etc.) are available in workflow functions.
|
|
63
|
+
|
|
64
|
+
### Base64 and hex encoding
|
|
65
|
+
|
|
66
|
+
The workflow environment provides [`Uint8Array` base64 and hex methods](https://tc39.es/proposal-arraybuffer-base64/) for encoding and decoding binary data:
|
|
67
|
+
|
|
68
|
+
{/* @skip-typecheck: polyfilled methods not available in host TypeScript */}
|
|
69
|
+
```typescript
|
|
70
|
+
// Encode to base64
|
|
71
|
+
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
|
|
72
|
+
bytes.toBase64(); // "SGVsbG8="
|
|
73
|
+
bytes.toBase64({ alphabet: "base64url" }); // URL-safe variant
|
|
74
|
+
bytes.toBase64({ omitPadding: true }); // "SGVsbG8"
|
|
75
|
+
|
|
76
|
+
// Decode from base64
|
|
77
|
+
Uint8Array.fromBase64("SGVsbG8="); // Uint8Array([72, 101, 108, 108, 111])
|
|
78
|
+
|
|
79
|
+
// Encode to hex
|
|
80
|
+
bytes.toHex(); // "48656c6c6f"
|
|
81
|
+
|
|
82
|
+
// Decode from hex
|
|
83
|
+
Uint8Array.fromHex("48656c6c6f"); // Uint8Array([72, 101, 108, 108, 111])
|
|
84
|
+
|
|
85
|
+
// Write into an existing array
|
|
86
|
+
const target = new Uint8Array(5);
|
|
87
|
+
target.setFromBase64("SGVsbG8="); // { read: 8, written: 5 }
|
|
88
|
+
target.setFromHex("48656c6c6f"); // { read: 10, written: 5 }
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
<Callout type="info">
|
|
92
|
+
These methods are polyfilled in the workflow environment. When the JavaScript runtime ships native support, the polyfill is automatically bypassed.
|
|
93
|
+
</Callout>
|
|
94
|
+
|
|
95
|
+
## Not Available
|
|
96
|
+
|
|
97
|
+
The following are **not available** in workflow functions. Move this logic to [step functions](/docs/foundations/workflows-and-steps#step-functions) instead.
|
|
98
|
+
|
|
99
|
+
- **Node.js core modules**: `fs`, `path`, `http`, `https`, `net`, `dns`, `child_process`, `cluster`, `os`, `stream`, `crypto` (Node.js version), etc. See [node-js-module-in-workflow](/docs/errors/node-js-module-in-workflow).
|
|
100
|
+
- **Global `fetch`**: Use [`import { fetch } from "workflow"`](/docs/api-reference/workflow/fetch) instead. See [fetch-in-workflow](/docs/errors/fetch-in-workflow).
|
|
101
|
+
- **Timers**: `setTimeout`, `setInterval`, `setImmediate`, and their `clear*` counterparts. Use [`sleep()`](/docs/api-reference/workflow/sleep) instead. See [timeout-in-workflow](/docs/errors/timeout-in-workflow).
|
|
102
|
+
- **`Buffer`**: Node.js-specific API. Use `Uint8Array` with `toBase64()` / `fromBase64()` / `toHex()` / `fromHex()` for binary data encoding, or `atob()` / `btoa()` for string-based base64.
|
|
@@ -7,7 +7,7 @@ related:
|
|
|
7
7
|
- /docs/getting-started/next
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
Next.js integration for Workflow
|
|
10
|
+
Next.js integration for Workflow SDK that automatically configures bundling and runtime support.
|
|
11
11
|
|
|
12
12
|
## Functions
|
|
13
13
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
title: "@workflow/serde"
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
Serialization symbols for custom class serialization in Workflow
|
|
5
|
+
Serialization symbols for custom class serialization in Workflow SDK.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -12,7 +12,7 @@ npm i @workflow/serde
|
|
|
12
12
|
|
|
13
13
|
## Overview
|
|
14
14
|
|
|
15
|
-
By default, Workflow
|
|
15
|
+
By default, Workflow SDK can serialize standard JavaScript types like primitives, objects, arrays, `Date`, `Map`, `Set`, and more. However, custom class instances are not serializable by default because the serialization system doesn't know how to reconstruct them.
|
|
16
16
|
|
|
17
17
|
The `@workflow/serde` package provides two symbols that allow you to define custom serialization and deserialization logic for your classes, enabling them to be passed between workflow and step functions.
|
|
18
18
|
|
package/docs/changelog/index.mdx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Changelog
|
|
3
|
-
description: Latest updates and new features in Workflow
|
|
3
|
+
description: Latest updates and new features in Workflow SDK.
|
|
4
4
|
type: overview
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Changelog
|
|
8
8
|
|
|
9
|
-
Stay up to date with the latest changes to Workflow
|
|
9
|
+
Stay up to date with the latest changes to Workflow SDK.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -214,7 +214,7 @@ Study these implementations for guidance:
|
|
|
214
214
|
|
|
215
215
|
## Testing Your World
|
|
216
216
|
|
|
217
|
-
Workflow
|
|
217
|
+
Workflow SDK includes an E2E test suite that validates World implementations. Once your World is published to npm:
|
|
218
218
|
|
|
219
219
|
1. Add your world to [`worlds-manifest.json`](https://github.com/vercel/workflow/blob/main/worlds-manifest.json)
|
|
220
220
|
2. Open a PR to the Workflow repository
|
|
@@ -23,8 +23,6 @@ Deploy your application to Vercel:
|
|
|
23
23
|
vercel deploy
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
<FluidComputeCallout />
|
|
27
|
-
|
|
28
26
|
That's it. Vercel automatically:
|
|
29
27
|
|
|
30
28
|
- Selects the Vercel World backend
|
|
@@ -32,6 +30,24 @@ That's it. Vercel automatically:
|
|
|
32
30
|
- Provisions storage and queuing infrastructure
|
|
33
31
|
- Isolates data per environment (production, preview, development)
|
|
34
32
|
|
|
33
|
+
<FluidComputeCallout />
|
|
34
|
+
|
|
35
|
+
## Vercel platform documentation
|
|
36
|
+
|
|
37
|
+
For complete details on pricing, usage limits, and included allotments on Vercel, see the official Vercel documentation:
|
|
38
|
+
|
|
39
|
+
- **[Vercel Workflow](https://vercel.com/docs/workflow)** — Pricing details, concepts, and observability for Workflow on Vercel
|
|
40
|
+
- **[Vercel limits](https://vercel.com/docs/limits)** — Platform-wide limits including Workflow-specific constraints
|
|
41
|
+
- **[Vercel Hobby plan](https://vercel.com/docs/plans/hobby)** — Free tier included usage for Workflow and other resources
|
|
42
|
+
|
|
43
|
+
For self-hosted deployments, use the [Postgres World](/worlds/postgres). For local development, use the [Local World](/worlds/local).
|
|
44
|
+
|
|
45
|
+
## Limitations
|
|
46
|
+
|
|
47
|
+
- **Single-region deployment** - The backend infrastructure is currently deployed only in `iad1`. Applications in other regions will route workflow requests to `iad1`, which may result in higher latency. For best performance, deploy your Vercel apps using Workflow to `iad1`. Global deployment is planned to colocate the backend closer to your applications.
|
|
48
|
+
|
|
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
|
+
|
|
35
51
|
## Observability
|
|
36
52
|
|
|
37
53
|
Workflow observability is built into the Vercel dashboard on your project page. It respects your existing authentication and project permission settings.
|
|
@@ -97,7 +113,8 @@ Custom base URL for the Vercel workflow API. Automatically detected.
|
|
|
97
113
|
|
|
98
114
|
### Programmatic configuration
|
|
99
115
|
|
|
100
|
-
{
|
|
116
|
+
{/*@skip-typecheck: incomplete code sample*/}
|
|
117
|
+
|
|
101
118
|
```typescript title="workflow.config.ts" lineNumbers
|
|
102
119
|
import { createVercelWorld } from "@workflow/world-vercel";
|
|
103
120
|
|
|
@@ -131,13 +148,3 @@ The Vercel World uses Vercel's infrastructure for workflow execution:
|
|
|
131
148
|
- **Authentication** - OIDC tokens provide secure, automatic authentication
|
|
132
149
|
|
|
133
150
|
For more details, see the [Vercel Workflow documentation](https://vercel.com/docs/workflow).
|
|
134
|
-
|
|
135
|
-
## Pricing and More
|
|
136
|
-
|
|
137
|
-
See the [Vercel Workflow documentation](https://vercel.com/docs/workflow) for current pricing and to learn more.
|
|
138
|
-
|
|
139
|
-
For self-hosted deployments, use the [Postgres World](/worlds/postgres). For local development, use the [Local World](/worlds/local).
|
|
140
|
-
|
|
141
|
-
## Limitations
|
|
142
|
-
|
|
143
|
-
- **Single-region deployment** - The backend infrastructure is currently deployed only in `iad1`. Applications in other regions will route workflow requests to `iad1`, which may result in higher latency. For best performance, deploy your Vercel apps using Workflow to `iad1`. Global deployment is planned to colocate the backend closer to your applications.
|
package/docs/errors/index.mdx
CHANGED
|
@@ -7,7 +7,7 @@ related:
|
|
|
7
7
|
- /docs/foundations/errors-and-retries
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
Fix common mistakes when creating and executing workflows in the **Workflow
|
|
10
|
+
Fix common mistakes when creating and executing workflows in the **Workflow SDK**.
|
|
11
11
|
|
|
12
12
|
<Cards>
|
|
13
13
|
<Card href="/docs/errors/fetch-in-workflow" title="fetch-in-workflow">
|
|
@@ -76,5 +76,5 @@ These common Node.js core modules cannot be used in workflow functions:
|
|
|
76
76
|
- Streams: `stream` (use Web Streams API instead)
|
|
77
77
|
|
|
78
78
|
<Callout type="info">
|
|
79
|
-
You can use Web Platform APIs in workflow functions (like `Headers`, `crypto.randomUUID()`, `Response`, etc.), since these are available in the sandboxed environment.
|
|
79
|
+
You can use Web Platform APIs in workflow functions (like `Headers`, `crypto.randomUUID()`, `Response`, etc.), since these are available in the sandboxed environment. See [Workflow Globals](/docs/api-reference/workflow-globals) for the full list.
|
|
80
80
|
</Callout>
|
|
@@ -109,7 +109,7 @@ async function greetStep(userData: { name: string }) {
|
|
|
109
109
|
|
|
110
110
|
## Supported Serializable Types
|
|
111
111
|
|
|
112
|
-
Workflow
|
|
112
|
+
Workflow SDK supports these types across execution boundaries:
|
|
113
113
|
|
|
114
114
|
### Standard JSON Types
|
|
115
115
|
|
|
@@ -9,18 +9,18 @@ related:
|
|
|
9
9
|
- /docs/api-reference/workflow-api/start
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
This error occurs when you try to call `start()` with a function that is not a valid workflow function or when the Workflow
|
|
12
|
+
This error occurs when you try to call `start()` with a function that is not a valid workflow function or when the Workflow SDK is not configured correctly.
|
|
13
13
|
|
|
14
14
|
## Error Message
|
|
15
15
|
|
|
16
16
|
```
|
|
17
|
-
'start' received an invalid workflow function. Ensure the Workflow
|
|
17
|
+
'start' received an invalid workflow function. Ensure the Workflow SDK
|
|
18
18
|
is configured correctly and the function includes a 'use workflow' directive.
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Why This Happens
|
|
22
22
|
|
|
23
|
-
The `start()` function expects a workflow function that has been properly processed by Workflow
|
|
23
|
+
The `start()` function expects a workflow function that has been properly processed by Workflow SDK's build system. During the build process, workflow functions are transformed and marked with special metadata that `start()` uses to identify and execute them.
|
|
24
24
|
|
|
25
25
|
This error typically happens when:
|
|
26
26
|
|
|
@@ -10,7 +10,7 @@ related:
|
|
|
10
10
|
- /docs/api-reference/workflow/retryable-error
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
By default, errors thrown inside steps are retried. Additionally, Workflow
|
|
13
|
+
By default, errors thrown inside steps are retried. Additionally, Workflow SDK provides two new types of errors you can use to customize retries.
|
|
14
14
|
|
|
15
15
|
## Default Retrying
|
|
16
16
|
|
|
@@ -219,7 +219,11 @@ While hooks are powerful, they require you to manually handle HTTP requests and
|
|
|
219
219
|
2. Provides an automatically addressable `url` property pointing to the generated webhook endpoint
|
|
220
220
|
3. Handles sending HTTP [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) objects back to the caller
|
|
221
221
|
|
|
222
|
-
When using Workflow
|
|
222
|
+
When using Workflow SDK, webhooks are automatically wired up at `/.well-known/workflow/v1/webhook/:token` without any additional setup.
|
|
223
|
+
|
|
224
|
+
<Callout type="warn">
|
|
225
|
+
`createWebhook()` exposes a public route at `/.well-known/workflow/v1/webhook/:token`, and the token in that URL is the only authorization performed for incoming requests. This is convenient for prototypes and a simple developer experience because you can share the webhook URL (endpoint) without creating another route, but if you need stronger security, prefer [`createHook()`](/docs/api-reference/workflow/create-hook) behind your own route and authorize the request before calling [`resumeHook()`](/docs/api-reference/workflow-api/resume-hook) to avoid unauthenticated workflow resumptions.
|
|
226
|
+
</Callout>
|
|
223
227
|
|
|
224
228
|
<Callout type="info">
|
|
225
229
|
See the full API reference for [`createWebhook()`](/docs/api-reference/workflow/create-webhook) for all available options.
|