workflow 5.0.0-beta.8 → 5.0.0-beta.9

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.
@@ -0,0 +1,63 @@
1
+ ---
2
+ title: experimental_setAttributes
3
+ description: Attach string metadata to workflow run for observability.
4
+ type: reference
5
+ summary: Use experimental_setAttributes inside a workflow or step function to set run attributes.
6
+ prerequisites:
7
+ - /docs/foundations/workflows-and-steps
8
+ related:
9
+ - /docs/observability/attributes
10
+ - /docs/api-reference/workflow/fatal-error
11
+ ---
12
+
13
+ Attaches string metadata to the current workflow run.
14
+
15
+ <Callout>
16
+ This API is experimental and may change before the stable attributes API is released.
17
+ </Callout>
18
+
19
+ ```typescript lineNumbers
20
+ import { experimental_setAttributes } from "workflow"
21
+
22
+ export async function orderWorkflow(orderId: string) {
23
+ "use workflow"
24
+
25
+ await experimental_setAttributes({
26
+ phase: "received",
27
+ orderId,
28
+ })
29
+ }
30
+ ```
31
+
32
+ ## API Signature
33
+
34
+ ### Parameters
35
+
36
+ <TSDoc
37
+ definition={`
38
+ import { experimental_setAttributes } from "workflow";
39
+ export default experimental_setAttributes;`}
40
+ showSections={['parameters']}
41
+ />
42
+
43
+ ## Usage
44
+
45
+ Call `experimental_setAttributes` from a `"use workflow"` function or a `"use step"` function. Calling it from plain application code is not supported because there is no active workflow run.
46
+
47
+ Attribute values must be strings. Pass `undefined` to remove an attribute:
48
+
49
+ ```typescript lineNumbers
50
+ import { experimental_setAttributes } from "workflow"
51
+
52
+ export async function cleanupAttributes() {
53
+ "use workflow"
54
+
55
+ await experimental_setAttributes({ staleKey: undefined })
56
+ }
57
+ ```
58
+
59
+ Attribute keys must be 1-256 characters, values must be strings up to 256 bytes, and each run can have up to 64 attributes. Keys that start with `$` are reserved for framework and library code.
60
+
61
+ Validation errors throw [`FatalError`](/docs/api-reference/workflow/fatal-error) and fail the run before an attribute write is attempted.
62
+
63
+ When called from a workflow body, the write is recorded through an internal step. When called from a step body, the step posts the attributes directly to the World. Storage errors from step-body calls throw from `experimental_setAttributes`, so catch them inside the step if the write should be best-effort.
@@ -47,6 +47,9 @@ Workflow SDK contains the following functions you can use inside your workflow f
47
47
  <Card href="/docs/api-reference/workflow/get-writable" title="getWritable()">
48
48
  Access the current workflow run's default stream.
49
49
  </Card>
50
+ <Card href="/docs/api-reference/workflow/experimental-set-attributes" title="experimental_setAttributes()">
51
+ Attach experimental string metadata to the current workflow run.
52
+ </Card>
50
53
  </Cards>
51
54
 
52
55
  ## Error Classes
@@ -15,7 +15,7 @@ The MVP lets workflow code attach plaintext `string → string` metadata to a ru
15
15
  - Attributes are materialized onto the `WorkflowRun` entity, plaintext, and visible via `world.runs.get()` / `world.runs.list()` and any observability UI built on top of those
16
16
  - World implementations emit a side-channel observability record per successful write (in `world-vercel`, this hooks into the same observability/analytics pipeline already used for other run lifecycle events)
17
17
 
18
- Calling `experimental_setAttributes` from a step body or plain host code is intentionally not supported in the MVP the host-side export throws `FatalError` directing callers back to a workflow body. This keeps the implementation a single dispatch path; step-body support can be added later without breaking the workflow-body contract.
18
+ Calling `experimental_setAttributes` from a step body was intentionally not supported in the MVP, but step-body calls are now supported as a follow-up. Plain host code remains unsupported because there is no active workflow run to attach attributes to.
19
19
 
20
20
  ## What MVP does **not** support (deferred to 5.0.0)
21
21
 
@@ -136,7 +136,7 @@ await experimental_setAttributes(
136
136
 
137
137
  The flag is per-call (no run-level "this run accepts reserved keys" mode), so each framework call site explicitly declares intent. Don't enable it from user code — misuse can conflict with observability surfaces, agent dashboards, or future platform features that rely on the reserved namespace.
138
138
 
139
- `experimental_setAttributes` is callable only from a workflow body:
139
+ `experimental_setAttributes` is callable from a workflow body:
140
140
 
141
141
  ```ts
142
142
  import { experimental_setAttributes } from 'workflow';
@@ -151,7 +151,7 @@ export async function myWorkflow(orderId: string) {
151
151
 
152
152
  The workflow-body path validates input inside the VM and then dispatches the canonical `AttributeChange[]` through an internal `__builtin_set_attributes` step bridge — see "How workflow-body dispatch works" below. The mutation is materialized on the run entity by the step body.
153
153
 
154
- The host-side export (the one resolved when the `workflow` package-exports condition is **not** `workflow`, i.e. step bodies and plain host code) throws `FatalError` with a message pointing callers back to the workflow body. There is no step-side dispatch path in the MVP — the workflow-body-only restriction is a scope cut for the MVP, not an architectural constraint, and may be relaxed in a follow-up.
154
+ Step-body calls resolve to the host-side export. In a step context, that export validates the input and posts the attribute changes directly to `world.runs.experimentalSetAttributes(runId, changes)`. Plain host code still throws `FatalError`.
155
155
 
156
156
  #### Usage patterns
157
157
 
@@ -266,7 +266,8 @@ Unit tests in `@workflow/world` (validation surface) and `@workflow/core` (VM-si
266
266
  - `undefined` value normalizes to a `null`-valued change on the wire
267
267
  - The `{ allowReservedAttributes: true }` opt-in is forwarded through the step bridge so the world receives the flag
268
268
  - Workflow VM with no `WORKFLOW_USE_STEP` bound throws `FatalError`
269
- - Host-side stub (resolved when not in the workflow VM) throws `FatalError` directing the caller back to a workflow body
269
+ - Host-side implementation posts directly to the world when called from a step context
270
+ - Host-side implementation throws `FatalError` when called from plain host code
270
271
 
271
272
  Unit tests in `workflow` (internal built-in step behavior):
272
273
 
@@ -324,9 +325,11 @@ This puts the mutation on the event log as a normal `step_created → step_compl
324
325
 
325
326
  The internal step is best-effort during the experimental phase. It sets `maxRetries = 2`, for three total attempts. If `world.runs.experimentalSetAttributes` fails on attempts 1 or 2, the error is rethrown so the runtime retries the step normally. If it still fails on attempt 3, the step logs `console.error` and returns; the workflow run continues instead of receiving a retry-exhaustion `FatalError` for failed tag posting.
326
327
 
328
+ Step-body calls do not use the internal built-in step. They run in host context already, so they post directly to the World. Storage errors throw from `experimental_setAttributes` like any other step-side side effect and can be caught by user code inside the step.
329
+
327
330
  The step body intentionally does **not** import anything from `@workflow/core`. That keeps the Next.js deferred-entries discoverer from walking a `__builtin_set_attributes` → `@workflow/core/...` → world adapter → `@vercel/queue` chain, which earlier drafts triggered (blowing the call stack of webpack's regex-based extractor with `RangeError: Maximum call stack size exceeded at RegExpStringIterator.next` on tarball-installed `nextjs-webpack` builds).
328
331
 
329
- The host-side `experimental_setAttributes` export (`packages/core/src/set-attributes.ts`, resolved by everything that isn't the workflow VM) throws `FatalError` with a message pointing the caller back to a workflow body. Step-body support can be added in a follow-up without changing this contract.
332
+ The host-side `experimental_setAttributes` export (`packages/core/src/set-attributes.ts`, resolved by everything that isn't the workflow VM) supports step bodies by reading the current run id from step context and posting directly to the World. It still throws `FatalError` when called from plain host code.
330
333
 
331
334
  When the full 5.0.0 attributes feature lands, `__builtin_set_attributes` is replaced by an `events.create(runId, { eventType: 'attr_set', ... })` dispatch path; SDK signatures don't change.
332
335
 
@@ -0,0 +1,66 @@
1
+ ---
2
+ title: Attributes
3
+ description: Attach experimental metadata to workflow runs for observability.
4
+ type: reference
5
+ summary: Add string attributes to a workflow run.
6
+ prerequisites:
7
+ - /docs/foundations/workflows-and-steps
8
+ related:
9
+ - /docs/observability
10
+ - /docs/api-reference/workflow/experimental-set-attributes
11
+ - /docs/api-reference/workflow-errors/workflow-world-error
12
+ ---
13
+
14
+ <Callout type="warn">
15
+ This feature is experimental and may change before the stable attributes API is released.
16
+ </Callout>
17
+
18
+ [`experimental_setAttributes`](/docs/api-reference/workflow/experimental-set-attributes) attaches plaintext string metadata to the current workflow run. These attributes are displayed in observability CLI/UI.
19
+ In the future, you'll be able to search and filter runs by attributes.
20
+
21
+ ```typescript lineNumbers
22
+ import { experimental_setAttributes } from "workflow"
23
+
24
+ export async function orderWorkflow(orderId: string) {
25
+ "use workflow"
26
+
27
+ await experimental_setAttributes({ // [!code highlight]
28
+ phase: "received", // [!code highlight]
29
+ orderId, // [!code highlight]
30
+ }) // [!code highlight]
31
+
32
+ // ...work...
33
+
34
+ await experimental_setAttributes({ phase: "complete" }) // [!code highlight]
35
+ }
36
+ ```
37
+
38
+ ## Usage
39
+
40
+ Call [`experimental_setAttributes`](/docs/api-reference/workflow/experimental-set-attributes) from a `"use workflow"` function or a `"use step"` function. Plain application code is not supported because there is no active workflow run to attach attributes to.
41
+
42
+ Values must be strings. Pass `undefined` to remove a key:
43
+
44
+ ```typescript lineNumbers
45
+ import { experimental_setAttributes } from "workflow"
46
+
47
+ export async function cleanupAttributes() {
48
+ "use workflow"
49
+
50
+ await experimental_setAttributes({ staleKey: undefined }) // [!code highlight]
51
+ }
52
+ ```
53
+
54
+ Attribute keys must be 1-256 characters, values must be strings up to 256 bytes, and each run can have up to 64 attributes. Keys that start with `$` are reserved for framework and library code.
55
+
56
+ ## Experimental Behavior
57
+
58
+ While attributes are experimental:
59
+
60
+ - Worlds that do not support attributes log a warning and ignore the call.
61
+ - Workflow-body storage errors are logged after retries, but do not fail the workflow run.
62
+ - Step-body storage errors throw from `experimental_setAttributes` like any other step-side network write. Catch the error inside the step if the attribute is best-effort.
63
+ - Setting attributes from a workflow body is currently slower than the final API will be, because each write goes through an internal workflow step. Step-body calls post directly to the World. Prefer batching related attributes in one call.
64
+ - Reading and querying attributes is not available yet. A query API is planned.
65
+
66
+ In a future release, using attributes with a World that does not support them, or when the World fails to store them, will fail with a [world error](/docs/api-reference/workflow-errors/workflow-world-error). This can be caught and handled to prevent failing a run.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Observability
3
3
  description: Inspect, monitor, and debug workflows through the CLI and Web UI with powerful observability tools.
4
- type: guide
4
+ type: overview
5
5
  summary: Inspect and debug workflow runs using the CLI and Web UI.
6
6
  prerequisites:
7
7
  - /docs/foundations
@@ -63,3 +63,11 @@ npx workflow inspect runs --backend vercel
63
63
  ```
64
64
 
65
65
  When deployed to Vercel, workflow data is [encrypted end-to-end](/docs/how-it-works/encryption). Encrypted fields display as locked placeholders until you choose to decrypt them using the **Decrypt** button in the web UI or the `--decrypt` flag in the CLI.
66
+
67
+ ## More Observability Features
68
+
69
+ <Cards>
70
+ <Card href="/docs/observability/attributes" title="Attributes">
71
+ Attach experimental metadata to workflow runs for observability.
72
+ </Card>
73
+ </Cards>
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "title": "Observability",
3
- "pages": ["observability"]
3
+ "pages": ["attributes"]
4
4
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "workflow",
3
- "version": "5.0.0-beta.8",
3
+ "version": "5.0.0-beta.9",
4
4
  "description": "Workflow SDK - Build durable, resilient, and observable workflows",
5
5
  "main": "dist/typescript-plugin.cjs",
6
6
  "type": "module",
@@ -57,18 +57,18 @@
57
57
  },
58
58
  "dependencies": {
59
59
  "ms": "2.1.3",
60
- "@workflow/astro": "5.0.0-beta.8",
61
- "@workflow/core": "5.0.0-beta.8",
62
- "@workflow/cli": "5.0.0-beta.8",
60
+ "@workflow/astro": "5.0.0-beta.9",
61
+ "@workflow/cli": "5.0.0-beta.9",
62
+ "@workflow/core": "5.0.0-beta.9",
63
63
  "@workflow/errors": "5.0.0-beta.5",
64
64
  "@workflow/typescript-plugin": "5.0.0-beta.4",
65
- "@workflow/next": "5.0.0-beta.8",
66
- "@workflow/nest": "5.0.0-beta.8",
67
65
  "@workflow/utils": "5.0.0-beta.3",
68
- "@workflow/nitro": "5.0.0-beta.8",
69
- "@workflow/nuxt": "5.0.0-beta.8",
70
- "@workflow/sveltekit": "5.0.0-beta.8",
71
- "@workflow/rollup": "5.0.0-beta.8"
66
+ "@workflow/next": "5.0.0-beta.9",
67
+ "@workflow/nest": "5.0.0-beta.9",
68
+ "@workflow/nitro": "5.0.0-beta.9",
69
+ "@workflow/nuxt": "5.0.0-beta.9",
70
+ "@workflow/sveltekit": "5.0.0-beta.9",
71
+ "@workflow/rollup": "5.0.0-beta.9"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@types/ms": "2.1.0",