workflow 5.0.0-beta.12 → 5.0.0-beta.13
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/index.mdx +21 -18
- package/docs/api-reference/workflow-ai/durable-agent.mdx +7 -45
- package/docs/cookbook/agent-patterns/durable-agent.mdx +10 -146
- package/docs/cookbook/index.mdx +1 -1
- package/docs/foundations/streaming.mdx +13 -22
- package/docs/internal/index.mdx +2 -0
- package/docs/internal/meta.json +6 -1
- package/docs/internal/nitro-native-build.mdx +38 -0
- package/docs/internal/nitro-web-ui.mdx +24 -0
- package/package.json +10 -10
package/docs/ai/index.mdx
CHANGED
|
@@ -92,7 +92,7 @@ Then modify your API endpoint to use the OpenAI provider:
|
|
|
92
92
|
{/* @skip-typecheck: incomplete code sample */}
|
|
93
93
|
```typescript title="app/api/chat/route.ts" lineNumbers
|
|
94
94
|
// ...
|
|
95
|
-
import { openai } from "@
|
|
95
|
+
import { openai } from "@ai-sdk/openai"; // [!code highlight]
|
|
96
96
|
|
|
97
97
|
export async function POST(req: Request) {
|
|
98
98
|
// ...
|
|
@@ -232,7 +232,7 @@ Now that we have a basic agent using AI SDK, we can modify it to make it durable
|
|
|
232
232
|
Add the Workflow SDK packages to your project:
|
|
233
233
|
|
|
234
234
|
```package-install
|
|
235
|
-
npm i workflow @workflow
|
|
235
|
+
npm i workflow @ai-sdk/workflow
|
|
236
236
|
```
|
|
237
237
|
|
|
238
238
|
and extend the Next.js config to transform your workflow code (see [Getting Started](/docs/getting-started/next) for more details).
|
|
@@ -258,18 +258,18 @@ Move the agent logic into a separate function, which will serve as our workflow
|
|
|
258
258
|
|
|
259
259
|
{/* @skip-typecheck: Shows two mutually exclusive model options */}
|
|
260
260
|
```typescript title="workflows/chat/workflow.ts" lineNumbers
|
|
261
|
-
import {
|
|
261
|
+
import { WorkflowAgent, type ModelCallStreamPart } from "@ai-sdk/workflow"; // [!code highlight]
|
|
262
262
|
import { getWritable } from "workflow"; // [!code highlight]
|
|
263
263
|
import { tools } from "@/ai/tools";
|
|
264
|
-
import { openai } from "@
|
|
265
|
-
import
|
|
264
|
+
import { openai } from "@ai-sdk/openai";
|
|
265
|
+
import { convertToModelMessages, type UIMessage } from "ai";
|
|
266
266
|
|
|
267
|
-
export async function chatWorkflow(messages:
|
|
267
|
+
export async function chatWorkflow(messages: UIMessage[]) {
|
|
268
268
|
"use workflow"; // [!code highlight]
|
|
269
269
|
|
|
270
|
-
const writable = getWritable<
|
|
270
|
+
const writable = getWritable<ModelCallStreamPart>(); // [!code highlight]
|
|
271
271
|
|
|
272
|
-
const agent = new
|
|
272
|
+
const agent = new WorkflowAgent({ // [!code highlight]
|
|
273
273
|
|
|
274
274
|
// If using AI Gateway, just specify the model name as a string:
|
|
275
275
|
model: "bedrock/claude-4-5-haiku-20251001-v1", // [!code highlight]
|
|
@@ -281,8 +281,10 @@ export async function chatWorkflow(messages: ModelMessage[]) {
|
|
|
281
281
|
tools: flightBookingTools,
|
|
282
282
|
});
|
|
283
283
|
|
|
284
|
+
const modelMessages = await convertToModelMessages(messages); // [!code highlight]
|
|
285
|
+
|
|
284
286
|
await agent.stream({ // [!code highlight]
|
|
285
|
-
messages,
|
|
287
|
+
messages: modelMessages,
|
|
286
288
|
writable,
|
|
287
289
|
});
|
|
288
290
|
}
|
|
@@ -291,8 +293,9 @@ export async function chatWorkflow(messages: ModelMessage[]) {
|
|
|
291
293
|
Key changes:
|
|
292
294
|
|
|
293
295
|
- Add the `"use workflow"` directive to mark our Agent as a workflow function
|
|
294
|
-
-
|
|
295
|
-
-
|
|
296
|
+
- Replace the in-memory agent with [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) from `@ai-sdk/workflow`. This runs the agent loop inside a workflow, persists state across step boundaries, and lets tool executions marked with `"use step"` retry automatically.
|
|
297
|
+
- Convert AI SDK `UIMessage` values to model messages inside the workflow before calling `agent.stream()`.
|
|
298
|
+
- Use [`getWritable()`](/docs/api-reference/workflow/get-writable) to get a stream for agent output. `WorkflowAgent` writes `ModelCallStreamPart` chunks to this persistent stream, and API endpoints can read from a run's stream at any time.
|
|
296
299
|
</Step>
|
|
297
300
|
|
|
298
301
|
<Step>
|
|
@@ -301,19 +304,18 @@ Key changes:
|
|
|
301
304
|
Remove the agent call that we just extracted, and replace it with a call to `start()` to run the workflow:
|
|
302
305
|
|
|
303
306
|
```typescript title="app/api/chat/route.ts" lineNumbers
|
|
304
|
-
import
|
|
305
|
-
import {
|
|
307
|
+
import { createModelCallToUIChunkTransform } from "@ai-sdk/workflow";
|
|
308
|
+
import { createUIMessageStreamResponse, type UIMessage } from "ai";
|
|
306
309
|
import { start } from "workflow/api";
|
|
307
310
|
import { chatWorkflow } from "@/workflows/chat/workflow";
|
|
308
311
|
|
|
309
312
|
export async function POST(req: Request) {
|
|
310
313
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
311
|
-
const modelMessages = await convertToModelMessages(messages);
|
|
312
314
|
|
|
313
|
-
const run = await start(chatWorkflow, [
|
|
315
|
+
const run = await start(chatWorkflow, [messages]); // [!code highlight]
|
|
314
316
|
|
|
315
317
|
return createUIMessageStreamResponse({
|
|
316
|
-
stream: run.readable, // [!code highlight]
|
|
318
|
+
stream: run.readable.pipeThrough(createModelCallToUIChunkTransform()), // [!code highlight]
|
|
317
319
|
});
|
|
318
320
|
}
|
|
319
321
|
```
|
|
@@ -321,7 +323,8 @@ export async function POST(req: Request) {
|
|
|
321
323
|
Key changes:
|
|
322
324
|
|
|
323
325
|
- Call `start()` to run the workflow function. This returns a `Run` object, which contains the run ID and the readable stream (see [Starting Workflows](/docs/foundations/starting-workflows) for more details on the `Run` object).
|
|
324
|
-
- Pass the `writable` to `agent.stream()` instead of returning a stream directly, ensuring all the Agent output is written to
|
|
326
|
+
- Pass the `writable` to `agent.stream()` instead of returning a stream directly, ensuring all the Agent output is written to the run's stream.
|
|
327
|
+
- Pipe the readable stream through `createModelCallToUIChunkTransform()` so the raw model-call chunks become AI SDK UI message chunks before they are returned to the client.
|
|
325
328
|
|
|
326
329
|
</Step>
|
|
327
330
|
|
|
@@ -423,7 +426,7 @@ A complete example that includes all of the above, plus all of the "next steps"
|
|
|
423
426
|
## Related Documentation
|
|
424
427
|
|
|
425
428
|
- [Tools](/docs/ai/defining-tools) - Patterns for defining tools for your agent
|
|
426
|
-
- [`
|
|
429
|
+
- [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) - AI SDK API for durable, resumable agents
|
|
427
430
|
- [Workflows and Steps](/docs/foundations/workflows-and-steps) - Core concepts
|
|
428
431
|
- [Streaming](/docs/foundations/streaming) - In-depth streaming guide
|
|
429
432
|
- [Errors and Retries](/docs/foundations/errors-and-retries) - Error handling patterns
|
|
@@ -1,59 +1,21 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: DurableAgent
|
|
3
|
-
description:
|
|
3
|
+
description: Deprecated DurableAgent API reference; use WorkflowAgent for new durable agents.
|
|
4
4
|
type: reference
|
|
5
|
-
summary:
|
|
5
|
+
summary: "Deprecated: use AI SDK's WorkflowAgent instead of DurableAgent."
|
|
6
6
|
prerequisites:
|
|
7
7
|
- /docs/ai
|
|
8
8
|
related:
|
|
9
9
|
- /docs/ai/defining-tools
|
|
10
10
|
---
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
```typescript lineNumbers
|
|
17
|
-
import { DurableAgent } from "@workflow/ai/agent";
|
|
18
|
-
import { getWritable } from "workflow";
|
|
19
|
-
import { z } from "zod";
|
|
20
|
-
import type { UIMessageChunk } from "ai";
|
|
21
|
-
|
|
22
|
-
async function getWeather({ city }: { city: string }) {
|
|
23
|
-
"use step";
|
|
24
|
-
|
|
25
|
-
return `Weather in ${city} is sunny`;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async function myAgent() {
|
|
29
|
-
"use workflow";
|
|
30
|
-
|
|
31
|
-
const agent = new DurableAgent({
|
|
32
|
-
model: "anthropic/claude-haiku-4.5",
|
|
33
|
-
instructions: "You are a helpful weather assistant.",
|
|
34
|
-
temperature: 0.7,
|
|
35
|
-
tools: {
|
|
36
|
-
getWeather: {
|
|
37
|
-
description: "Get weather for a city",
|
|
38
|
-
inputSchema: z.object({ city: z.string() }),
|
|
39
|
-
execute: getWeather,
|
|
40
|
-
},
|
|
41
|
-
},
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// The agent will stream its output to the workflow
|
|
45
|
-
// run's default output stream
|
|
46
|
-
const writable = getWritable<UIMessageChunk>();
|
|
12
|
+
<Callout type="warn">
|
|
13
|
+
`DurableAgent` is deprecated. Use AI SDK's [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) for new durable agents and migration guidance.
|
|
14
|
+
</Callout>
|
|
47
15
|
|
|
48
|
-
|
|
49
|
-
messages: [{ role: "user", content: "How is the weather in San Francisco?" }],
|
|
50
|
-
writable,
|
|
51
|
-
});
|
|
16
|
+
This reference is kept for existing applications that still import `DurableAgent` from `@workflow/ai/agent`. Do not use `DurableAgent` for new code.
|
|
52
17
|
|
|
53
|
-
|
|
54
|
-
console.log(result.messages);
|
|
55
|
-
}
|
|
56
|
-
```
|
|
18
|
+
For current examples and implementation guidance, see AI SDK's [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) docs. For legacy code, the API surface below documents the existing `DurableAgent` exports.
|
|
57
19
|
|
|
58
20
|
## API Signature
|
|
59
21
|
|
|
@@ -1,154 +1,18 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description:
|
|
2
|
+
title: DurableAgent is now WorkflowAgent
|
|
3
|
+
description: Use AI SDK v7's WorkflowAgent for durable, resumable AI agents.
|
|
4
4
|
type: guide
|
|
5
|
-
summary:
|
|
5
|
+
summary: Build durable, resumable AI agents with AI SDK v7's WorkflowAgent.
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## WorkflowAgent from AI SDK v7
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Use AI SDK v7's [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) for new durable agent work. It replaces `DurableAgent` in v5 and keeps the current agent pattern in the AI SDK package.
|
|
11
11
|
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
- Agents that need per-step observability in the workflow event log
|
|
12
|
+
- Import `WorkflowAgent` from `@ai-sdk/workflow` and run it inside a `"use workflow"` function.
|
|
13
|
+
- Stream `ModelCallStreamPart` chunks with `getWritable()`, then convert the run stream to UI message chunks with `createModelCallToUIChunkTransform()` in your route.
|
|
14
|
+
- Mark tool `execute` functions with `"use step"` when they should run as durable workflow steps with retry and observability behavior.
|
|
16
15
|
|
|
17
|
-
<Callout type="
|
|
18
|
-
|
|
16
|
+
<Callout type="warn">
|
|
17
|
+
`DurableAgent` is deprecated in v5 and remains documented for existing code only. Existing `DurableAgent` users can refer to the [`DurableAgent` API reference](/docs/api-reference/workflow-ai/durable-agent) while migrating.
|
|
19
18
|
</Callout>
|
|
20
|
-
|
|
21
|
-
## Pattern
|
|
22
|
-
|
|
23
|
-
Replace `Agent` with `DurableAgent`, wrap the function in `"use workflow"`, mark each tool with `"use step"`, and stream output through `getWritable()`.
|
|
24
|
-
|
|
25
|
-
### Workflow
|
|
26
|
-
|
|
27
|
-
```typescript
|
|
28
|
-
import { DurableAgent } from "@workflow/ai/agent";
|
|
29
|
-
import { getWritable } from "workflow";
|
|
30
|
-
import { z } from "zod";
|
|
31
|
-
import type { ModelMessage, UIMessageChunk } from "ai";
|
|
32
|
-
|
|
33
|
-
async function searchFlights({ from, to, date }: {
|
|
34
|
-
from: string;
|
|
35
|
-
to: string;
|
|
36
|
-
date: string;
|
|
37
|
-
}) {
|
|
38
|
-
"use step"; // [!code highlight]
|
|
39
|
-
const res = await fetch(
|
|
40
|
-
`https://api.example.com/flights?from=${from}&to=${to}&date=${date}`
|
|
41
|
-
);
|
|
42
|
-
if (!res.ok) throw new Error(`Search failed: ${res.status}`);
|
|
43
|
-
return res.json();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function bookFlight({ flightId, passenger }: {
|
|
47
|
-
flightId: string;
|
|
48
|
-
passenger: string;
|
|
49
|
-
}) {
|
|
50
|
-
"use step"; // [!code highlight]
|
|
51
|
-
const res = await fetch("https://api.example.com/bookings", {
|
|
52
|
-
method: "POST",
|
|
53
|
-
headers: { "Content-Type": "application/json" },
|
|
54
|
-
body: JSON.stringify({ flightId, passenger }),
|
|
55
|
-
});
|
|
56
|
-
if (!res.ok) throw new Error(`Booking failed: ${res.status}`);
|
|
57
|
-
return res.json();
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function checkWeather({ city }: { city: string }) {
|
|
61
|
-
"use step"; // [!code highlight]
|
|
62
|
-
const res = await fetch(`https://api.weather.com/forecast?city=${city}`);
|
|
63
|
-
return res.json();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export async function flightAgent(messages: ModelMessage[]) {
|
|
67
|
-
"use workflow";
|
|
68
|
-
|
|
69
|
-
const agent = new DurableAgent({ // [!code highlight]
|
|
70
|
-
model: "anthropic/claude-haiku-4.5",
|
|
71
|
-
instructions: "You are a helpful flight booking assistant.",
|
|
72
|
-
tools: {
|
|
73
|
-
searchFlights: {
|
|
74
|
-
description: "Search for available flights between two airports",
|
|
75
|
-
inputSchema: z.object({
|
|
76
|
-
from: z.string().describe("Departure airport code"),
|
|
77
|
-
to: z.string().describe("Arrival airport code"),
|
|
78
|
-
date: z.string().describe("Travel date (YYYY-MM-DD)"),
|
|
79
|
-
}),
|
|
80
|
-
execute: searchFlights,
|
|
81
|
-
},
|
|
82
|
-
bookFlight: {
|
|
83
|
-
description: "Book a specific flight for a passenger",
|
|
84
|
-
inputSchema: z.object({
|
|
85
|
-
flightId: z.string().describe("Flight ID from search results"),
|
|
86
|
-
passenger: z.string().describe("Passenger full name"),
|
|
87
|
-
}),
|
|
88
|
-
execute: bookFlight,
|
|
89
|
-
},
|
|
90
|
-
checkWeather: {
|
|
91
|
-
description: "Check the weather forecast for a city",
|
|
92
|
-
inputSchema: z.object({
|
|
93
|
-
city: z.string().describe("City name"),
|
|
94
|
-
}),
|
|
95
|
-
execute: checkWeather,
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
const result = await agent.stream({ // [!code highlight]
|
|
101
|
-
messages,
|
|
102
|
-
writable: getWritable<UIMessageChunk>(), // [!code highlight]
|
|
103
|
-
maxSteps: 10,
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
return { messages: result.messages };
|
|
107
|
-
}
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
### API route
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
import type { UIMessage } from "ai";
|
|
114
|
-
import { convertToModelMessages, createUIMessageStreamResponse } from "ai";
|
|
115
|
-
import { start } from "workflow/api";
|
|
116
|
-
import { flightAgent } from "@/app/workflows/flight-agent";
|
|
117
|
-
|
|
118
|
-
export async function POST(req: Request) {
|
|
119
|
-
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
120
|
-
const modelMessages = await convertToModelMessages(messages); // [!code highlight]
|
|
121
|
-
|
|
122
|
-
const run = await start(flightAgent, [modelMessages]); // [!code highlight]
|
|
123
|
-
|
|
124
|
-
return createUIMessageStreamResponse({ // [!code highlight]
|
|
125
|
-
stream: run.readable,
|
|
126
|
-
headers: {
|
|
127
|
-
"x-workflow-run-id": run.runId,
|
|
128
|
-
},
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
## How it works
|
|
134
|
-
|
|
135
|
-
1. **DurableAgent wraps Agent** — same API as AI SDK's `Agent`, but backed by a workflow. If the process crashes, the agent resumes from the last completed step on replay.
|
|
136
|
-
2. **Tools as steps** — each tool's `execute` function uses `"use step"`, giving it automatic retries, full Node.js access, and an entry in the workflow event log.
|
|
137
|
-
3. **Streaming** — `getWritable<UIMessageChunk>()` streams the agent's output (text chunks, tool calls, tool results) to the client in real time via `createUIMessageStreamResponse`.
|
|
138
|
-
4. **maxSteps** — limits the total number of LLM calls the agent can make, preventing runaway tool loops.
|
|
139
|
-
|
|
140
|
-
## Adapting to your use case
|
|
141
|
-
|
|
142
|
-
- **Change the model** — replace `"anthropic/claude-haiku-4.5"` with any AI Gateway model string (e.g. `"openai/gpt-4o"`, `"anthropic/claude-sonnet-4-5"`).
|
|
143
|
-
- **Add tools** — define a new `"use step"` function with a Zod schema. Each tool automatically gets retries and persistence.
|
|
144
|
-
- **Workflow-level tools** — if a tool needs workflow primitives like `sleep()` or `createHook()`, omit `"use step"` so it runs in the workflow context instead.
|
|
145
|
-
- **Multi-turn** — pass `result.messages` plus new user messages to subsequent `agent.stream()` calls for multi-turn conversations.
|
|
146
|
-
- **Client integration** — use `useChat()` from `@ai-sdk/react` with `WorkflowChatTransport` from `@workflow/ai` for a full chat UI with reconnection support.
|
|
147
|
-
|
|
148
|
-
## Key APIs
|
|
149
|
-
|
|
150
|
-
- [`"use workflow"`](/docs/api-reference/workflow/use-workflow) — declares the orchestrator function
|
|
151
|
-
- [`"use step"`](/docs/api-reference/workflow/use-step) — declares step functions with retries and full Node.js access
|
|
152
|
-
- [`DurableAgent`](/docs/api-reference/workflow-ai/durable-agent) — durable wrapper around AI SDK's Agent
|
|
153
|
-
- [`getWritable()`](/docs/api-reference/workflow/get-writable) — streams agent output to the client
|
|
154
|
-
- [`start()`](/docs/api-reference/workflow-api/start) — starts a workflow run from an API route
|
package/docs/cookbook/index.mdx
CHANGED
|
@@ -8,7 +8,7 @@ A curated collection of workflow patterns with clean, copy-paste code examples f
|
|
|
8
8
|
|
|
9
9
|
## Agent Patterns
|
|
10
10
|
|
|
11
|
-
- [**
|
|
11
|
+
- [**WorkflowAgent**](/cookbook/agent-patterns/durable-agent) — Build durable, resumable AI agents with AI SDK's WorkflowAgent
|
|
12
12
|
- [**Human-in-the-Loop**](/cookbook/agent-patterns/human-in-the-loop) — Pause an agent for human approval, then resume based on the decision
|
|
13
13
|
- [**Agent Cancellation**](/cookbook/agent-patterns/agent-cancellation) — Stop a running agent immediately via `run.cancel()` or gracefully via a hook + `Promise.race`
|
|
14
14
|
|
|
@@ -345,29 +345,19 @@ export async function batchProcessingWorkflow(items: string[]) {
|
|
|
345
345
|
}
|
|
346
346
|
```
|
|
347
347
|
|
|
348
|
-
### Streaming AI Responses with `
|
|
348
|
+
### Streaming AI Responses with `WorkflowAgent`
|
|
349
349
|
|
|
350
|
-
Stream AI-generated content using [`
|
|
350
|
+
Stream AI-generated content using AI SDK's [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) from `@ai-sdk/workflow`. The agent writes `ModelCallStreamPart` chunks to the workflow stream, and route handlers convert them to UI message chunks with `createModelCallToUIChunkTransform()` before returning the response:
|
|
351
351
|
|
|
352
352
|
```typescript title="workflows/ai-assistant.ts" lineNumbers
|
|
353
|
-
import {
|
|
353
|
+
import { WorkflowAgent, type ModelCallStreamPart } from "@ai-sdk/workflow";
|
|
354
|
+
import { tool } from "ai";
|
|
354
355
|
import { getWritable } from "workflow";
|
|
355
356
|
import { z } from "zod";
|
|
356
|
-
import type { UIMessageChunk } from "ai";
|
|
357
357
|
|
|
358
358
|
async function searchFlights({ query }: { query: string }) {
|
|
359
359
|
"use step";
|
|
360
360
|
|
|
361
|
-
// Tools can emit progress updates to the stream
|
|
362
|
-
const writable = getWritable<UIMessageChunk>(); // [!code highlight]
|
|
363
|
-
const writer = writable.getWriter(); // [!code highlight]
|
|
364
|
-
await writer.write({ // [!code highlight]
|
|
365
|
-
type: "data-progress", // [!code highlight]
|
|
366
|
-
data: { message: `Searching flights for ${query}...` }, // [!code highlight]
|
|
367
|
-
transient: true, // [!code highlight]
|
|
368
|
-
}); // [!code highlight]
|
|
369
|
-
writer.releaseLock(); // [!code highlight]
|
|
370
|
-
|
|
371
361
|
// ... search logic ...
|
|
372
362
|
return { flights: [/* results */] };
|
|
373
363
|
}
|
|
@@ -375,27 +365,28 @@ async function searchFlights({ query }: { query: string }) {
|
|
|
375
365
|
export async function aiAssistantWorkflow(userMessage: string) {
|
|
376
366
|
"use workflow";
|
|
377
367
|
|
|
378
|
-
const agent = new
|
|
368
|
+
const agent = new WorkflowAgent({
|
|
379
369
|
model: "anthropic/claude-haiku-4.5",
|
|
380
|
-
|
|
370
|
+
instructions: "You are a helpful flight assistant.",
|
|
381
371
|
tools: {
|
|
382
|
-
searchFlights: {
|
|
372
|
+
searchFlights: tool({
|
|
383
373
|
description: "Search for flights",
|
|
384
374
|
inputSchema: z.object({ query: z.string() }),
|
|
385
375
|
execute: searchFlights,
|
|
386
|
-
},
|
|
376
|
+
}),
|
|
387
377
|
},
|
|
388
378
|
});
|
|
389
379
|
|
|
390
380
|
// LLM response will be streamed to the run's writable
|
|
391
381
|
await agent.stream({
|
|
392
382
|
messages: [{ role: "user", content: userMessage }],
|
|
393
|
-
writable: getWritable<
|
|
383
|
+
writable: getWritable<ModelCallStreamPart>(), // [!code highlight]
|
|
394
384
|
});
|
|
395
385
|
}
|
|
396
386
|
```
|
|
397
387
|
|
|
398
388
|
```typescript title="app/api/ai-assistant/route.ts" lineNumbers
|
|
389
|
+
import { createModelCallToUIChunkTransform } from "@ai-sdk/workflow";
|
|
399
390
|
import { createUIMessageStreamResponse } from "ai";
|
|
400
391
|
import { start } from "workflow/api";
|
|
401
392
|
import { aiAssistantWorkflow } from "./workflows/ai";
|
|
@@ -406,13 +397,13 @@ export async function POST(request: Request) {
|
|
|
406
397
|
const run = await start(aiAssistantWorkflow, [message]);
|
|
407
398
|
|
|
408
399
|
return createUIMessageStreamResponse({
|
|
409
|
-
stream: run.readable,
|
|
400
|
+
stream: run.readable.pipeThrough(createModelCallToUIChunkTransform()), // [!code highlight]
|
|
410
401
|
});
|
|
411
402
|
}
|
|
412
403
|
```
|
|
413
404
|
|
|
414
405
|
<Callout type="info">
|
|
415
|
-
For
|
|
406
|
+
For the full agent API and migration notes, see the [`WorkflowAgent` documentation](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent).
|
|
416
407
|
</Callout>
|
|
417
408
|
|
|
418
409
|
### Streaming Between Steps
|
|
@@ -594,7 +585,7 @@ Stream errors don't trigger automatic retries for the producer step. Design your
|
|
|
594
585
|
- [`start()` API Reference](/docs/api-reference/workflow-api/start) - Start workflows and access the `Run` object
|
|
595
586
|
- [`getRun()` API Reference](/docs/api-reference/workflow-api/get-run) - Retrieve runs and their streams later
|
|
596
587
|
- [world.streams](/docs/api-reference/workflow-api/world/streams) - Low-level stream read/write/close via World SDK
|
|
597
|
-
- [
|
|
588
|
+
- [WorkflowAgent](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) - AI agents with durable, resumable streaming support
|
|
598
589
|
- [Errors and Retries](/docs/foundations/errors-and-retries) - Understanding error handling and retry behavior
|
|
599
590
|
- [Serialization](/docs/foundations/serialization) - Understanding what data types can be passed in workflows
|
|
600
591
|
- [Workflows and Steps](/docs/foundations/workflows-and-steps) - Core concepts of workflow execution
|
package/docs/internal/index.mdx
CHANGED
|
@@ -16,4 +16,6 @@ This page is only visible on preview deployments and local development. It does
|
|
|
16
16
|
|
|
17
17
|
Changelog entries staged here for review before publishing to the Vercel website.
|
|
18
18
|
|
|
19
|
+
- [Local web UI in Nitro dev](/docs/internal/nitro-web-ui) — unreleased (next beta)
|
|
20
|
+
- [Native Nitro v3 bundling for workflows](/docs/internal/nitro-native-build) — May 22, 2026
|
|
19
21
|
- [Serializable AbortController and AbortSignal](/docs/internal/serializable-abort-controller) — March 12, 2026
|
package/docs/internal/meta.json
CHANGED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Native Nitro v3 bundling for workflows
|
|
3
|
+
description: Workflow routes are now bundled by Nitro v3, so steps run in your app's runtime and can call any server-side Nitro API.
|
|
4
|
+
type: overview
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Native Nitro v3 bundling for workflows
|
|
8
|
+
|
|
9
|
+
<span className="text-sm text-fd-muted-foreground">May 22, 2026</span>
|
|
10
|
+
|
|
11
|
+
Workflow routes are now handled as Nitro v3 handlers and bundled by Nitro, rather than built separately for the Vercel Build Output API. Your workflows are part of the same bundle as the rest of your app.
|
|
12
|
+
|
|
13
|
+
## What's new
|
|
14
|
+
|
|
15
|
+
- **Call any server-side Nitro API from a step.** Workflow steps now run inside the same bundled runtime as the rest of your Nitro app, so you can call `useStorage()`, `useDatabase()`, `useRuntimeConfig()`, virtual imports, and any other server-side Nitro API directly from a `"use step"` function.
|
|
16
|
+
- **Workflows are part of your Nitro bundle.** Workflow routes are bundled by Nitro alongside your application code, instead of being built into a separate output. There's nothing extra to configure.
|
|
17
|
+
- **Minimal runtime output.** During bundling, Nitro automatically traces native dependencies and tree-shakes unused code to produce a minimal runtime output.
|
|
18
|
+
- **Nitro v2 is unchanged.** This applies to Nitro v3. Apps on Nitro v2 keep their existing behavior.
|
|
19
|
+
|
|
20
|
+
## Using Nitro APIs from a step
|
|
21
|
+
|
|
22
|
+
Because steps run inside your Nitro runtime, server-side utilities work directly inside a `"use step"` function:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
export async function cacheResult(key: string, value: string) {
|
|
26
|
+
"use step";
|
|
27
|
+
|
|
28
|
+
const storage = useStorage("cache");
|
|
29
|
+
await storage.setItem(key, value);
|
|
30
|
+
|
|
31
|
+
return { cached: true };
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Learn more
|
|
36
|
+
|
|
37
|
+
- [Nitro](/docs/getting-started/nitro) — Set up Workflow SDK in a Nitro v3 app
|
|
38
|
+
- [Deploying](/docs/deploying) — How workflow bundles are deployed
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Local web UI in Nitro dev
|
|
3
|
+
description: Inspect, monitor, and debug your workflow runs from the /_workflow route during Nitro development.
|
|
4
|
+
type: overview
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Local web UI in Nitro dev
|
|
8
|
+
|
|
9
|
+
{/* TODO: unreleased — changeset .changeset/nitro-dashboard-route.md is pending; ships in the next @workflow/nitro beta (5.0.0-beta.12). Update this date on publish. */}
|
|
10
|
+
<span className="text-sm text-fd-muted-foreground">June 2, 2026</span>
|
|
11
|
+
|
|
12
|
+
The Workflow SDK web UI is now built into the Nitro dev server. During development, open `/_workflow` in your browser to inspect, monitor, and debug your workflow runs.
|
|
13
|
+
|
|
14
|
+
## What's new
|
|
15
|
+
|
|
16
|
+
- **Built-in `/_workflow` route in development.** The route starts the local web UI and redirects to it — no separate command or process required.
|
|
17
|
+
- **Inspect runs in place.** Inspect, monitor, and debug your workflow runs directly from the dev server you're already running.
|
|
18
|
+
|
|
19
|
+

|
|
20
|
+
|
|
21
|
+
## Learn more
|
|
22
|
+
|
|
23
|
+
- [Observability](/docs/observability) — Inspect runs with the web UI and CLI
|
|
24
|
+
- [Nitro](/docs/getting-started/nitro) — Set up Workflow SDK in a Nitro v3 app
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "workflow",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.13",
|
|
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.
|
|
61
|
-
"@workflow/cli": "5.0.0-beta.
|
|
62
|
-
"@workflow/core": "5.0.0-beta.
|
|
60
|
+
"@workflow/astro": "5.0.0-beta.13",
|
|
61
|
+
"@workflow/cli": "5.0.0-beta.13",
|
|
62
|
+
"@workflow/core": "5.0.0-beta.13",
|
|
63
63
|
"@workflow/errors": "5.0.0-beta.7",
|
|
64
64
|
"@workflow/typescript-plugin": "5.0.0-beta.4",
|
|
65
65
|
"@workflow/utils": "5.0.0-beta.3",
|
|
66
|
-
"@workflow/next": "5.0.0-beta.
|
|
67
|
-
"@workflow/nest": "5.0.0-beta.
|
|
68
|
-
"@workflow/nitro": "5.0.0-beta.
|
|
69
|
-
"@workflow/nuxt": "5.0.0-beta.
|
|
70
|
-
"@workflow/sveltekit": "5.0.0-beta.
|
|
71
|
-
"@workflow/rollup": "5.0.0-beta.
|
|
66
|
+
"@workflow/next": "5.0.0-beta.13",
|
|
67
|
+
"@workflow/nest": "5.0.0-beta.13",
|
|
68
|
+
"@workflow/nitro": "5.0.0-beta.13",
|
|
69
|
+
"@workflow/nuxt": "5.0.0-beta.13",
|
|
70
|
+
"@workflow/sveltekit": "5.0.0-beta.13",
|
|
71
|
+
"@workflow/rollup": "5.0.0-beta.13"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
74
74
|
"@types/ms": "2.1.0",
|