workflow 4.2.0-beta.75 → 4.2.0-beta.77

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +2 -2
  2. package/docs/api-reference/workflow-ai/durable-agent.mdx +86 -1
  3. package/docs/api-reference/workflow-api/get-world.mdx +59 -14
  4. package/docs/api-reference/workflow-api/start.mdx +5 -0
  5. package/docs/api-reference/workflow-api/world/index.mdx +5 -14
  6. package/docs/api-reference/workflow-api/world/meta.json +1 -9
  7. package/docs/api-reference/workflow-api/world/observability.mdx +14 -139
  8. package/docs/api-reference/workflow-api/world/queue.mdx +26 -67
  9. package/docs/api-reference/workflow-api/world/storage.mdx +408 -0
  10. package/docs/api-reference/workflow-api/world/streams.mdx +89 -27
  11. package/docs/api-reference/workflow-next/with-workflow.mdx +51 -0
  12. package/docs/changelog/meta.json +1 -1
  13. package/docs/changelog/resilient-start.mdx +327 -0
  14. package/docs/deploying/building-a-world.mdx +16 -6
  15. package/docs/deploying/index.mdx +2 -2
  16. package/docs/deploying/world/vercel-world.mdx +30 -1
  17. package/docs/errors/hook-conflict.mdx +1 -1
  18. package/docs/errors/node-js-module-in-workflow.mdx +1 -1
  19. package/docs/errors/start-invalid-workflow-function.mdx +83 -58
  20. package/docs/foundations/serialization.mdx +3 -3
  21. package/docs/foundations/starting-workflows.mdx +1 -1
  22. package/docs/foundations/streaming.mdx +1 -1
  23. package/docs/getting-started/astro.mdx +18 -1
  24. package/docs/getting-started/express.mdx +18 -1
  25. package/docs/getting-started/fastify.mdx +18 -1
  26. package/docs/getting-started/hono.mdx +18 -1
  27. package/docs/getting-started/nestjs.mdx +84 -6
  28. package/docs/getting-started/next.mdx +17 -2
  29. package/docs/getting-started/nitro.mdx +18 -1
  30. package/docs/getting-started/nuxt.mdx +18 -1
  31. package/docs/getting-started/sveltekit.mdx +18 -1
  32. package/docs/getting-started/vite.mdx +18 -1
  33. package/docs/how-it-works/encryption.mdx +39 -2
  34. package/docs/how-it-works/event-sourcing.mdx +19 -2
  35. package/docs/how-it-works/framework-integrations.mdx +68 -11
  36. package/docs/how-it-works/understanding-directives.mdx +3 -3
  37. package/docs/observability/index.mdx +1 -1
  38. package/docs/testing/index.mdx +1 -1
  39. package/docs/testing/server-based.mdx +59 -16
  40. package/package.json +10 -10
  41. package/docs/api-reference/workflow-api/world/events.mdx +0 -227
  42. package/docs/api-reference/workflow-api/world/hooks.mdx +0 -181
  43. package/docs/api-reference/workflow-api/world/runs.mdx +0 -223
  44. package/docs/api-reference/workflow-api/world/steps.mdx +0 -216
@@ -1,181 +0,0 @@
1
- ---
2
- title: world.hooks
3
- description: Look up workflow hooks by ID or token for webhook resume flows and metadata inspection.
4
- type: reference
5
- summary: "Methods: get(), getByToken(), list(). Query hook details for resume flows."
6
- prerequisites:
7
- - /docs/api-reference/workflow-api/get-world
8
- related:
9
- - /docs/api-reference/workflow-api/world/events
10
- - /docs/api-reference/workflow-api/resume-hook
11
- - /docs/api-reference/workflow-api/resume-webhook
12
- keywords:
13
- - world.hooks
14
- - world.hooks.get
15
- - world.hooks.getByToken
16
- - world.hooks.list
17
- - Hook
18
- - webhook token
19
- - hook metadata
20
- - resume flow
21
- - pending approvals
22
- ---
23
-
24
- The `world.hooks` interface provides access to workflow hook data. Hooks are pause points in workflows that wait for external input. Use this interface to look up hooks by ID or token, inspect metadata, and build admin UIs for pending approvals.
25
-
26
- ## Import
27
-
28
- ```typescript lineNumbers
29
- import { getWorld } from "workflow/runtime";
30
-
31
- const world = getWorld();
32
- const hooks = world.hooks; // [!code highlight]
33
- ```
34
-
35
- ## Methods
36
-
37
- ### get()
38
-
39
- Retrieve a hook by its ID.
40
-
41
- ```typescript lineNumbers
42
- const hook = await world.hooks.get(hookId); // [!code highlight]
43
- ```
44
-
45
- **Parameters:**
46
-
47
- | Parameter | Type | Description |
48
- |-----------|------|-------------|
49
- | `hookId` | `string` | The hook ID |
50
- | `params` | `object` | Optional parameters |
51
-
52
- **Returns:** `Hook`
53
-
54
- ### getByToken()
55
-
56
- Look up a hook by its token. Useful in webhook resume flows where you receive a token in the callback URL.
57
-
58
- ```typescript lineNumbers
59
- const hook = await world.hooks.getByToken(token); // [!code highlight]
60
- ```
61
-
62
- **Parameters:**
63
-
64
- | Parameter | Type | Description |
65
- |-----------|------|-------------|
66
- | `token` | `string` | The hook token |
67
- | `params` | `object` | Optional parameters |
68
-
69
- **Returns:** `Hook`
70
-
71
- ### list()
72
-
73
- List hooks with cursor pagination.
74
-
75
- ```typescript lineNumbers
76
- const result = await world.hooks.list({ // [!code highlight]
77
- pagination: { cursor },
78
- }); // [!code highlight]
79
- ```
80
-
81
- **Parameters:**
82
-
83
- | Parameter | Type | Description |
84
- |-----------|------|-------------|
85
- | `params.pagination.cursor` | `string` | Cursor for the next page |
86
-
87
- **Returns:** `{ data: Hook[], cursor?: string }`
88
-
89
- ## Types
90
-
91
- ### Hook
92
-
93
- | Field | Type | Description |
94
- |-------|------|-------------|
95
- | `runId` | `string` | Parent workflow run ID |
96
- | `hookId` | `string` | Unique hook identifier |
97
- | `token` | `string` | Hook token for resuming |
98
- | `ownerId` | `string` | Owner (team/user) ID |
99
- | `projectId` | `string` | Project ID |
100
- | `environment` | `string` | Deployment environment |
101
- | `metadata` | `object` | Custom metadata attached to the hook |
102
- | `isWebhook` | `boolean` | Whether this is a webhook-style hook |
103
-
104
- ## Examples
105
-
106
- ### Look Up Hook by ID
107
-
108
- ```typescript lineNumbers
109
- // app/api/workflow-hooks/route.ts
110
- import { getWorld } from "workflow/runtime";
111
-
112
- export async function GET(req: Request) {
113
- const url = new URL(req.url);
114
- const hookId = url.searchParams.get("hookId");
115
-
116
- if (!hookId) {
117
- return Response.json({ error: "hookId required" }, { status: 400 });
118
- }
119
-
120
- const world = getWorld();
121
- const hook = await world.hooks.get(hookId); // [!code highlight]
122
-
123
- return Response.json({
124
- hookId: hook.hookId,
125
- runId: hook.runId,
126
- token: hook.token,
127
- metadata: hook.metadata,
128
- });
129
- }
130
- ```
131
-
132
- ### Look Up Hook by Token for Webhook Resume
133
-
134
- When you receive a webhook callback with a token, look up the hook to inspect metadata before resuming:
135
-
136
- ```typescript lineNumbers
137
- // app/api/workflow-hooks/resume/route.ts
138
- import { getWorld } from "workflow/runtime";
139
-
140
- export async function POST(req: Request) {
141
- const { token } = await req.json();
142
-
143
- const world = getWorld();
144
- const hook = await world.hooks.getByToken(token); // [!code highlight]
145
-
146
- // Inspect hook metadata before deciding to resume
147
- console.log(hook.runId, hook.metadata); // [!code highlight]
148
-
149
- return Response.json({
150
- runId: hook.runId,
151
- hookId: hook.hookId,
152
- metadata: hook.metadata,
153
- });
154
- }
155
- ```
156
-
157
- ### List All Hooks for Pending Approvals Dashboard
158
-
159
- ```typescript lineNumbers
160
- // app/api/workflow-hooks/pending/route.ts
161
- import { getWorld } from "workflow/runtime";
162
-
163
- export async function GET(req: Request) {
164
- const url = new URL(req.url);
165
- const cursor = url.searchParams.get("cursor") ?? undefined;
166
-
167
- const world = getWorld();
168
- const hooks = await world.hooks.list({ // [!code highlight]
169
- pagination: { cursor },
170
- }); // [!code highlight]
171
-
172
- return Response.json(hooks);
173
- }
174
- ```
175
-
176
- ## Related
177
-
178
- - [resumeHook()](/docs/api-reference/workflow-api/resume-hook) — Resume a workflow by sending a payload to a hook
179
- - [resumeWebhook()](/docs/api-reference/workflow-api/resume-webhook) — Resume a workflow via webhook
180
- - [getHookByToken()](/docs/api-reference/workflow-api/get-hook-by-token) — Higher-level API for hook lookup
181
- - [Hooks](/docs/foundations/hooks) — Core concepts for hooks and pause points
@@ -1,223 +0,0 @@
1
- ---
2
- title: world.runs
3
- description: List, filter, and inspect workflow runs with cursor pagination and status filtering.
4
- type: reference
5
- summary: "Methods: get(), list(). Query workflow runs by status, paginate results, and inspect run metadata."
6
- prerequisites:
7
- - /docs/api-reference/workflow-api/get-world
8
- related:
9
- - /docs/api-reference/workflow-api/world/steps
10
- - /docs/api-reference/workflow-api/world/events
11
- - /docs/api-reference/workflow-api/get-run
12
- keywords:
13
- - world.runs
14
- - world.runs.get
15
- - world.runs.list
16
- - WorkflowRun
17
- - cursor pagination
18
- - run status
19
- - resolveData
20
- - parseWorkflowName
21
- - list workflow runs
22
- - filter runs
23
- ---
24
-
25
- The `world.runs` interface provides direct access to workflow run data. Use it to list runs with pagination, filter by status, and inspect individual run metadata.
26
-
27
- ## Import
28
-
29
- ```typescript lineNumbers
30
- import { getWorld } from "workflow/runtime";
31
-
32
- const world = getWorld();
33
- const runs = world.runs; // [!code highlight]
34
- ```
35
-
36
- ## Methods
37
-
38
- ### get()
39
-
40
- Retrieve a single workflow run by ID.
41
-
42
- ```typescript lineNumbers
43
- const run = await world.runs.get(runId); // [!code highlight]
44
- ```
45
-
46
- **Parameters:**
47
-
48
- | Parameter | Type | Description |
49
- |-----------|------|-------------|
50
- | `runId` | `string` | The workflow run ID |
51
- | `params.resolveData` | `'all' \| 'none'` | Whether to hydrate input/output data. Default: `'all'` |
52
-
53
- **Returns:** `WorkflowRun`
54
-
55
- ### list()
56
-
57
- List workflow runs with cursor pagination.
58
-
59
- ```typescript lineNumbers
60
- const result = await world.runs.list({ // [!code highlight]
61
- pagination: { cursor },
62
- }); // [!code highlight]
63
- ```
64
-
65
- **Parameters:**
66
-
67
- | Parameter | Type | Description |
68
- |-----------|------|-------------|
69
- | `params.pagination.cursor` | `string` | Cursor for the next page |
70
- | `params.resolveData` | `'all' \| 'none'` | Whether to hydrate input/output data |
71
-
72
- **Returns:** `{ data: WorkflowRun[], cursor?: string }`
73
-
74
- ### cancel()
75
-
76
- Cancel a running workflow. This is a convenience method that creates a `run_cancelled` event.
77
-
78
- ```typescript lineNumbers
79
- const run = await world.runs.cancel(runId); // [!code highlight]
80
- ```
81
-
82
- **Parameters:**
83
-
84
- | Parameter | Type | Description |
85
- |-----------|------|-------------|
86
- | `runId` | `string` | The workflow run ID to cancel |
87
-
88
- **Returns:** `WorkflowRun`
89
-
90
- <Callout type="info">
91
- Cancellation works by creating an event with `eventType: 'run_cancelled'`. See [world.events](/docs/api-reference/workflow-api/world/events) for the full event creation API.
92
- </Callout>
93
-
94
- ## Types
95
-
96
- ### WorkflowRun
97
-
98
- | Field | Type | Description |
99
- |-------|------|-------------|
100
- | `runId` | `string` | Unique run identifier |
101
- | `status` | `string` | Run status: `'running'`, `'completed'`, `'failed'`, `'cancelled'` |
102
- | `workflowName` | `string` | Machine-readable workflow identifier |
103
- | `input` | `any` | Workflow input data (when `resolveData: 'all'`) |
104
- | `output` | `any` | Workflow output data (when `resolveData: 'all'`) |
105
- | `error` | `any` | Error data if the run failed |
106
- | `startedAt` | `string` | ISO timestamp when the run started |
107
- | `completedAt` | `string \| null` | ISO timestamp when the run completed |
108
- | `specVersion` | `number` | Workflow spec version |
109
-
110
- <Callout type="warn">
111
- The `workflowName` field contains a machine-readable identifier like `workflow//./src/workflows/order//processOrder`. Use `parseWorkflowName()` from `workflow/observability` to extract a display-friendly name.
112
- </Callout>
113
-
114
- ## Examples
115
-
116
- ### List Workflow Runs with Cursor Pagination
117
-
118
- ```typescript lineNumbers
119
- // app/api/workflow-runs/route.ts
120
- import { getWorld } from "workflow/runtime";
121
-
122
- export async function GET(req: Request) {
123
- const url = new URL(req.url);
124
- const cursor = url.searchParams.get("cursor") ?? undefined;
125
-
126
- const world = getWorld(); // [!code highlight]
127
- const runs = await world.runs.list({ // [!code highlight]
128
- pagination: { cursor }, // [!code highlight]
129
- }); // [!code highlight]
130
-
131
- return Response.json(runs);
132
- }
133
- ```
134
-
135
- ### Get a Single Run with Full Data
136
-
137
- Use `resolveData: 'all'` (the default) to fetch the complete run including input and output:
138
-
139
- ```typescript lineNumbers
140
- // app/api/workflow-runs/[runId]/route.ts
141
- import { getWorld } from "workflow/runtime";
142
-
143
- export async function GET(req: Request) {
144
- const url = new URL(req.url);
145
- const runId = url.searchParams.get("runId");
146
-
147
- if (!runId) {
148
- return Response.json({ error: "runId required" }, { status: 400 });
149
- }
150
-
151
- const world = getWorld();
152
- const run = await world.runs.get(runId, { // [!code highlight]
153
- resolveData: "all", // [!code highlight]
154
- }); // [!code highlight]
155
-
156
- return Response.json({
157
- runId: run.runId,
158
- status: run.status,
159
- input: run.input,
160
- output: run.output,
161
- startedAt: run.startedAt,
162
- completedAt: run.completedAt,
163
- });
164
- }
165
- ```
166
-
167
- ### Get Run without Data for Lightweight Status Checks
168
-
169
- Use `resolveData: 'none'` when you only need status metadata:
170
-
171
- ```typescript lineNumbers
172
- import { getWorld } from "workflow/runtime";
173
-
174
- const world = getWorld();
175
- const run = await world.runs.get(runId, { // [!code highlight]
176
- resolveData: "none", // Skip input/output for performance // [!code highlight]
177
- }); // [!code highlight]
178
-
179
- console.log(run.status); // 'running' | 'completed' | 'failed' | 'cancelled'
180
- ```
181
-
182
- ### Parse Workflow Display Name from Machine-Readable ID
183
-
184
- ```typescript lineNumbers
185
- import { getWorld } from "workflow/runtime";
186
- import { parseWorkflowName } from "workflow/observability"; // [!code highlight]
187
-
188
- const world = getWorld();
189
- const runs = await world.runs.list({});
190
-
191
- for (const run of runs.data) {
192
- const parsed = parseWorkflowName(run.workflowName); // [!code highlight]
193
- console.log(parsed?.shortName); // e.g., "processOrder" // [!code highlight]
194
- console.log(parsed?.moduleSpecifier); // e.g., "./src/workflows/order"
195
- }
196
- ```
197
-
198
- ### Cancel a Running Workflow
199
-
200
- ```typescript lineNumbers
201
- // app/api/workflow-runs/cancel/route.ts
202
- import { getWorld } from "workflow/runtime";
203
-
204
- export async function POST(req: Request) {
205
- const { runId } = await req.json();
206
-
207
- if (!runId) {
208
- return Response.json({ error: "runId required" }, { status: 400 });
209
- }
210
-
211
- const world = getWorld();
212
- const run = await world.runs.cancel(runId); // [!code highlight]
213
-
214
- return Response.json({ status: run.status });
215
- }
216
- ```
217
-
218
- ## Related
219
-
220
- - [world.steps](/docs/api-reference/workflow-api/world/steps) — Inspect individual step execution within a run
221
- - [world.events](/docs/api-reference/workflow-api/world/events) — Query the event log for a run
222
- - [getRun()](/docs/api-reference/workflow-api/get-run) — Higher-level API for working with individual runs
223
- - [Observability Utilities](/docs/api-reference/workflow-api/world/observability) — Parse workflow names and hydrate data
@@ -1,216 +0,0 @@
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