workflow 5.0.0-beta.50 → 5.0.0-beta.52
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/chat-session-modeling.mdx +170 -419
- package/docs/ai/index.mdx +27 -36
- package/docs/ai/message-queueing.mdx +61 -100
- package/docs/api-reference/index.mdx +1 -1
- package/docs/api-reference/workflow-ai/durable-agent.mdx +15 -15
- package/docs/api-reference/workflow-ai/index.mdx +3 -3
- package/docs/changelog/batched-event-writes.mdx +1 -1
- package/docs/configuration/runtime-tuning.mdx +5 -0
- package/docs/configuration/worlds.mdx +1 -1
- package/docs/cookbook/advanced/serializable-steps.mdx +33 -61
- package/docs/cookbook/agent-patterns/agent-cancellation.mdx +64 -54
- package/docs/cookbook/agent-patterns/durable-agent.mdx +21 -1
- package/docs/cookbook/agent-patterns/human-in-the-loop.mdx +177 -200
- package/docs/cookbook/integrations/ai-sdk.mdx +2 -2
- package/docs/errors/corrupted-event-log.mdx +11 -1
- package/docs/errors/fetch-in-workflow.mdx +4 -7
- package/docs/errors/run-expired.mdx +6 -6
- package/docs/foundations/streaming.mdx +1 -1
- package/docs/getting-started/python.mdx +69 -15
- package/docs/how-it-works/event-sourcing.mdx +27 -0
- package/docs/observability/retention.mdx +8 -6
- package/package.json +10 -10
package/docs/ai/index.mdx
CHANGED
|
@@ -57,55 +57,49 @@ cd workflow-examples/flight-booking-app
|
|
|
57
57
|
|
|
58
58
|
<Step>
|
|
59
59
|
|
|
60
|
-
###
|
|
60
|
+
### Configure model access
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
<Tabs items={['Gateway', 'Custom Provider']}>
|
|
62
|
+
<Tabs items={['AI Gateway', 'Provider package']}>
|
|
64
63
|
|
|
65
|
-
<Tab value="Gateway">
|
|
64
|
+
<Tab value="AI Gateway">
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
AI SDK uses [Vercel AI Gateway](https://vercel.com/docs/ai-gateway) as its default global provider, so plain `"provider/model"` strings need no provider-specific package. Vercel deployments authenticate with OIDC automatically. For local development, link the project and pull a short-lived OIDC token:
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
GATEWAY_API_KEY=...
|
|
68
|
+
```bash
|
|
69
|
+
vercel link
|
|
70
|
+
vercel env pull .env.local
|
|
73
71
|
```
|
|
74
72
|
|
|
73
|
+
You can alternatively set `AI_GATEWAY_API_KEY` from the [AI Gateway authentication](https://vercel.com/docs/ai-gateway/authentication) page.
|
|
74
|
+
|
|
75
75
|
</Tab>
|
|
76
76
|
|
|
77
|
-
<Tab value="
|
|
77
|
+
<Tab value="Provider package">
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
`WorkflowAgent` accepts any AI SDK provider. To use OpenAI, install its provider package:
|
|
80
80
|
|
|
81
81
|
```package-install
|
|
82
82
|
npm i @ai-sdk/openai
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
Set
|
|
85
|
+
Set the provider's API key:
|
|
86
86
|
|
|
87
87
|
```bash title=".env.local" lineNumbers
|
|
88
88
|
OPENAI_API_KEY=...
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
Then
|
|
91
|
+
Then construct the model with the provider package:
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// ...
|
|
96
|
-
import { openai } from "@ai-sdk/openai"; // [!code highlight]
|
|
93
|
+
```typescript
|
|
94
|
+
import { openai } from "@ai-sdk/openai";
|
|
97
95
|
|
|
98
|
-
|
|
99
|
-
// ...
|
|
100
|
-
const agent = new Agent({
|
|
101
|
-
// This uses the OPENAI_API_KEY environment variable by default, but you
|
|
102
|
-
// can also pass { apiKey: string } as an option.
|
|
103
|
-
model: openai("gpt-5.1"), // [!code highlight]
|
|
104
|
-
// ...
|
|
105
|
-
});
|
|
96
|
+
const model = openai("gpt-5.6-sol");
|
|
106
97
|
```
|
|
107
98
|
|
|
99
|
+
See the [AI SDK provider guide](https://ai-sdk.dev/providers/ai-sdk-providers) for Anthropic, Google, Amazon Bedrock, and other providers.
|
|
100
|
+
|
|
108
101
|
</Tab>
|
|
102
|
+
|
|
109
103
|
</Tabs>
|
|
110
104
|
</Step>
|
|
111
105
|
|
|
@@ -131,7 +125,7 @@ import { convertToModelMessages, createUIMessageStreamResponse } from "ai";
|
|
|
131
125
|
export async function POST(req: Request) {
|
|
132
126
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
|
133
127
|
const agent = new ToolLoopAgent({ // [!code highlight]
|
|
134
|
-
model: "
|
|
128
|
+
model: "spacexai/grok-4.6",
|
|
135
129
|
instructions: FLIGHT_ASSISTANT_PROMPT,
|
|
136
130
|
tools: flightBookingTools,
|
|
137
131
|
});
|
|
@@ -257,12 +251,10 @@ export default withWorkflow(nextConfig);
|
|
|
257
251
|
|
|
258
252
|
Move the agent logic into a separate function, which will serve as our workflow definition.
|
|
259
253
|
|
|
260
|
-
{/* @skip-typecheck: Shows two mutually exclusive model options */}
|
|
261
254
|
```typescript title="workflows/chat/workflow.ts" lineNumbers
|
|
262
255
|
import { WorkflowAgent, type ModelCallStreamPart } from "@ai-sdk/workflow"; // [!code highlight]
|
|
263
256
|
import { getWritable } from "workflow"; // [!code highlight]
|
|
264
|
-
import {
|
|
265
|
-
import { openai } from "@ai-sdk/openai";
|
|
257
|
+
import { flightBookingTools, FLIGHT_ASSISTANT_PROMPT } from "@/ai/tools";
|
|
266
258
|
import { convertToModelMessages, type UIMessage } from "ai";
|
|
267
259
|
|
|
268
260
|
export async function chatWorkflow(messages: UIMessage[]) {
|
|
@@ -271,13 +263,8 @@ export async function chatWorkflow(messages: UIMessage[]) {
|
|
|
271
263
|
const writable = getWritable<ModelCallStreamPart>(); // [!code highlight]
|
|
272
264
|
|
|
273
265
|
const agent = new WorkflowAgent({ // [!code highlight]
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
model: "bedrock/claude-4-5-haiku-20251001-v1", // [!code highlight]
|
|
277
|
-
|
|
278
|
-
// ELSE if using a custom provider, pass the provider call as an argument:
|
|
279
|
-
model: openai("gpt-5.1"), // [!code highlight]
|
|
280
|
-
|
|
266
|
+
// Plain model strings use Vercel AI Gateway.
|
|
267
|
+
model: "spacexai/grok-4.6", // [!code highlight]
|
|
281
268
|
instructions: FLIGHT_ASSISTANT_PROMPT,
|
|
282
269
|
tools: flightBookingTools,
|
|
283
270
|
});
|
|
@@ -291,6 +278,10 @@ export async function chatWorkflow(messages: UIMessage[]) {
|
|
|
291
278
|
}
|
|
292
279
|
```
|
|
293
280
|
|
|
281
|
+
<Callout type="info">
|
|
282
|
+
`WorkflowAgent` accepts any AI SDK provider. Import the provider and pass its model instance, for example `model: openai("gpt-5.6-sol")` from `@ai-sdk/openai`. The rest of the integration is unchanged.
|
|
283
|
+
</Callout>
|
|
284
|
+
|
|
294
285
|
Key changes:
|
|
295
286
|
|
|
296
287
|
- Add the `"use workflow"` directive to mark our Agent as a workflow function
|
|
@@ -7,7 +7,6 @@ prerequisites:
|
|
|
7
7
|
- /docs/ai
|
|
8
8
|
related:
|
|
9
9
|
- /docs/ai/chat-session-modeling
|
|
10
|
-
- /docs/api-reference/workflow-ai/durable-agent
|
|
11
10
|
- /docs/api-reference/workflow/define-hook
|
|
12
11
|
---
|
|
13
12
|
|
|
@@ -29,27 +28,24 @@ If you need basic multi-turn conversations where messages arrive between turns,
|
|
|
29
28
|
|
|
30
29
|
## The `prepareStep` callback
|
|
31
30
|
|
|
32
|
-
The `prepareStep` callback runs before each step in the agent loop.
|
|
31
|
+
The `prepareStep` callback runs before each step in the agent loop. Use WorkflowAgent's exported types rather than redeclaring its normalized provider-prompt contract:
|
|
33
32
|
|
|
34
33
|
```typescript lineNumbers
|
|
35
|
-
import type {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
messages:
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
interface PrepareStepResult {
|
|
45
|
-
model?: string | (() => Promise<LanguageModel>); // Override model
|
|
46
|
-
messages?: ModelMessage[]; // Override messages
|
|
47
|
-
}
|
|
34
|
+
import type {
|
|
35
|
+
PrepareStepInfo,
|
|
36
|
+
PrepareStepResult,
|
|
37
|
+
} from "@ai-sdk/workflow";
|
|
38
|
+
|
|
39
|
+
const prepareStep = (
|
|
40
|
+
{ messages }: PrepareStepInfo
|
|
41
|
+
): PrepareStepResult => ({ messages });
|
|
48
42
|
```
|
|
49
43
|
|
|
50
|
-
|
|
44
|
+
`PrepareStepInfo.messages` is a normalized `LanguageModelV4Prompt`, not the application-level `ModelMessage[]` accepted by `WorkflowAgent.stream()`.
|
|
51
45
|
|
|
52
|
-
|
|
46
|
+
## Queueing messages during and between turns
|
|
47
|
+
|
|
48
|
+
Use one async Hook consumer and one FIFO. `prepareStep` atomically drains messages that arrived during a model turn; messages that arrive after the final model step become input to the next turn. Each Hook payload therefore has exactly one ownership path.
|
|
53
49
|
|
|
54
50
|
```typescript title="workflows/chat/index.ts" lineNumbers
|
|
55
51
|
import { WorkflowAgent, type ModelCallStreamPart } from "@ai-sdk/workflow";
|
|
@@ -63,112 +59,77 @@ export async function chat(initialMessages: ModelMessage[]) {
|
|
|
63
59
|
|
|
64
60
|
const { workflowRunId: runId } = getWorkflowMetadata();
|
|
65
61
|
const writable = getWritable<ModelCallStreamPart>();
|
|
62
|
+
let messages: ModelMessage[] = [...initialMessages];
|
|
66
63
|
const messageQueue: Array<{ role: "user"; content: string }> = []; // [!code highlight]
|
|
64
|
+
let stopped = false;
|
|
65
|
+
let notifyMessage: (() => void) | undefined;
|
|
67
66
|
|
|
68
67
|
const agent = new WorkflowAgent({
|
|
69
|
-
model: "
|
|
68
|
+
model: "spacexai/grok-4.6",
|
|
70
69
|
instructions: FLIGHT_ASSISTANT_PROMPT,
|
|
71
70
|
tools: flightBookingTools,
|
|
72
71
|
});
|
|
73
72
|
|
|
74
|
-
// Listen for messages in background (non-blocking) // [!code highlight]
|
|
75
73
|
const hook = chatMessageHook.create({ token: runId }); // [!code highlight]
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
prepareStep: ({ messages: currentMessages }) => { // [!code highlight]
|
|
84
|
-
// Inject any queued messages before the next LLM call // [!code highlight]
|
|
85
|
-
if (messageQueue.length > 0) { // [!code highlight]
|
|
86
|
-
const newMessages = messageQueue.splice(0); // Drain queue // [!code highlight]
|
|
87
|
-
return { // [!code highlight]
|
|
88
|
-
messages: [ // [!code highlight]
|
|
89
|
-
...currentMessages, // [!code highlight]
|
|
90
|
-
...newMessages.map((m) => ({ // [!code highlight]
|
|
91
|
-
role: m.role, // [!code highlight]
|
|
92
|
-
content: [{ type: "text" as const, text: m.content }], // [!code highlight]
|
|
93
|
-
})), // [!code highlight]
|
|
94
|
-
], // [!code highlight]
|
|
95
|
-
}; // [!code highlight]
|
|
74
|
+
// This is the only code path that consumes Hook payloads. // [!code highlight]
|
|
75
|
+
const consumeMessages = (async () => { // [!code highlight]
|
|
76
|
+
for await (const { message } of hook) { // [!code highlight]
|
|
77
|
+
if (message === "/done") { // [!code highlight]
|
|
78
|
+
stopped = true; // [!code highlight]
|
|
79
|
+
notifyMessage?.(); // [!code highlight]
|
|
80
|
+
break; // [!code highlight]
|
|
96
81
|
} // [!code highlight]
|
|
97
|
-
return {}; // [!code highlight]
|
|
98
|
-
}, // [!code highlight]
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Messages sent via `chatMessageHook.resume()` accumulate in the queue and get injected before the next step, whether that's a tool call or another LLM request.
|
|
104
|
-
|
|
105
|
-
<Callout type="info">
|
|
106
|
-
The `prepareStep` callback receives messages in `ModelMessage[]` format (with content arrays), which is the internal format used by the AI SDK.
|
|
107
|
-
</Callout>
|
|
108
|
-
|
|
109
|
-
## Combining with multi-turn sessions
|
|
110
|
-
|
|
111
|
-
You can also combine message queueing with the standard multi-turn pattern:
|
|
112
|
-
|
|
113
|
-
```typescript title="workflows/chat/index.ts" lineNumbers
|
|
114
|
-
import { WorkflowAgent, type ModelCallStreamPart } from "@ai-sdk/workflow";
|
|
115
|
-
import { getWritable, getWorkflowMetadata } from "workflow";
|
|
116
|
-
import { chatMessageHook } from "./hooks/chat-message";
|
|
117
|
-
import type { ModelMessage } from "ai";
|
|
118
|
-
|
|
119
|
-
export async function chat(initialMessages: ModelMessage[]) {
|
|
120
|
-
"use workflow";
|
|
121
|
-
|
|
122
|
-
const { workflowRunId: runId } = getWorkflowMetadata();
|
|
123
|
-
const writable = getWritable<ModelCallStreamPart>();
|
|
124
|
-
const messages: ModelMessage[] = [...initialMessages];
|
|
125
|
-
const messageQueue: Array<{ role: "user"; content: string }> = [];
|
|
126
|
-
|
|
127
|
-
const agent = new WorkflowAgent({ /* ... */ });
|
|
128
|
-
const hook = chatMessageHook.create({ token: runId });
|
|
129
|
-
|
|
130
|
-
while (true) {
|
|
131
|
-
// Set up non-blocking listener for mid-turn messages // [!code highlight]
|
|
132
|
-
let pendingMessage: string | null = null; // [!code highlight]
|
|
133
|
-
hook.then(({ message }) => { // [!code highlight]
|
|
134
|
-
if (message === "/done") return; // [!code highlight]
|
|
135
82
|
messageQueue.push({ role: "user", content: message }); // [!code highlight]
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
83
|
+
notifyMessage?.(); // [!code highlight]
|
|
84
|
+
notifyMessage = undefined; // [!code highlight]
|
|
85
|
+
} // [!code highlight]
|
|
86
|
+
})(); // [!code highlight]
|
|
87
|
+
|
|
88
|
+
const waitForMessage = async () => {
|
|
89
|
+
while (messageQueue.length === 0 && !stopped) {
|
|
90
|
+
await new Promise<void>((resolve) => {
|
|
91
|
+
notifyMessage = resolve;
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
while (!stopped) {
|
|
139
97
|
const result = await agent.stream({
|
|
140
98
|
messages,
|
|
141
99
|
writable,
|
|
142
100
|
preventClose: true,
|
|
101
|
+
sendFinish: false,
|
|
143
102
|
prepareStep: ({ messages: currentMessages }) => {
|
|
144
|
-
|
|
145
|
-
if (
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
return {};
|
|
103
|
+
const queued = messageQueue.splice(0); // Atomic drain // [!code highlight]
|
|
104
|
+
if (queued.length === 0) return {};
|
|
105
|
+
return {
|
|
106
|
+
messages: [
|
|
107
|
+
...currentMessages,
|
|
108
|
+
...queued.map(({ role, content }) => ({
|
|
109
|
+
role,
|
|
110
|
+
content: [{ type: "text" as const, text: content }],
|
|
111
|
+
})),
|
|
112
|
+
],
|
|
113
|
+
};
|
|
158
114
|
},
|
|
159
115
|
});
|
|
116
|
+
messages = result.messages;
|
|
160
117
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const { message: followUp } = pendingMessage ? { message: pendingMessage } : await hook; // [!code highlight]
|
|
165
|
-
if (followUp === "/done") break;
|
|
118
|
+
if (stopped) break;
|
|
119
|
+
await waitForMessage(); // [!code highlight]
|
|
120
|
+
if (stopped) break;
|
|
166
121
|
|
|
167
|
-
|
|
122
|
+
// Anything not consumed by prepareStep arrived after the final model step.
|
|
123
|
+
messages = [...messages, ...messageQueue.splice(0)]; // [!code highlight]
|
|
168
124
|
}
|
|
125
|
+
|
|
126
|
+
await consumeMessages;
|
|
127
|
+
return { messages };
|
|
169
128
|
}
|
|
170
129
|
```
|
|
171
130
|
|
|
131
|
+
Messages sent via `chatMessageHook.resume()` accumulate until either `prepareStep` or the between-turn branch drains the FIFO. Send `/done` to stop the consumer and let the workflow return.
|
|
132
|
+
|
|
172
133
|
## Related documentation
|
|
173
134
|
|
|
174
135
|
- [Chat Session Modeling](/docs/ai/chat-session-modeling) - Single-turn vs multi-turn patterns
|
|
@@ -51,7 +51,7 @@ All the functions and primitives that come with Workflow SDK by package.
|
|
|
51
51
|
Serialization symbols for custom class serialization in workflows.
|
|
52
52
|
</Card>
|
|
53
53
|
<Card title="@workflow/ai" href="/docs/api-reference/workflow-ai">
|
|
54
|
-
|
|
54
|
+
Deprecated AI integration APIs kept for existing applications. Use `@ai-sdk/workflow` for new agents.
|
|
55
55
|
</Card>
|
|
56
56
|
<Card title="@workflow/vitest" href="/docs/api-reference/vitest">
|
|
57
57
|
Vitest plugin and test helpers for integration testing workflows in-process.
|
|
@@ -199,7 +199,7 @@ async function weatherAgentWorkflow(userQuery: string) {
|
|
|
199
199
|
"use workflow";
|
|
200
200
|
|
|
201
201
|
const agent = new DurableAgent({
|
|
202
|
-
model: "
|
|
202
|
+
model: "spacexai/grok-4.6",
|
|
203
203
|
tools: {
|
|
204
204
|
getWeather: {
|
|
205
205
|
description: "Get current weather for a location",
|
|
@@ -244,7 +244,7 @@ async function multiToolAgentWorkflow(userQuery: string) {
|
|
|
244
244
|
"use workflow";
|
|
245
245
|
|
|
246
246
|
const agent = new DurableAgent({
|
|
247
|
-
model: "
|
|
247
|
+
model: "spacexai/grok-4.6",
|
|
248
248
|
tools: {
|
|
249
249
|
getWeather: {
|
|
250
250
|
description: "Get weather for a location",
|
|
@@ -289,7 +289,7 @@ async function multiTurnAgentWorkflow() {
|
|
|
289
289
|
"use workflow";
|
|
290
290
|
|
|
291
291
|
const agent = new DurableAgent({
|
|
292
|
-
model: "
|
|
292
|
+
model: "spacexai/grok-4.6",
|
|
293
293
|
tools: {
|
|
294
294
|
searchProducts: {
|
|
295
295
|
description: "Search for products",
|
|
@@ -368,7 +368,7 @@ async function agentWithLibraryFeaturesWorkflow(userRequest: string) {
|
|
|
368
368
|
"use workflow";
|
|
369
369
|
|
|
370
370
|
const agent = new DurableAgent({
|
|
371
|
-
model: "
|
|
371
|
+
model: "spacexai/grok-4.6",
|
|
372
372
|
tools: {
|
|
373
373
|
scheduleTask: {
|
|
374
374
|
description: "Pause the workflow for the specified number of seconds",
|
|
@@ -405,7 +405,7 @@ async function agentWithPrepareStep(userMessage: string) {
|
|
|
405
405
|
"use workflow";
|
|
406
406
|
|
|
407
407
|
const agent = new DurableAgent({
|
|
408
|
-
model: "
|
|
408
|
+
model: "spacexai/grok-4.6", // Default model
|
|
409
409
|
instructions: "You are a helpful assistant.",
|
|
410
410
|
});
|
|
411
411
|
|
|
@@ -459,7 +459,7 @@ async function agentWithMessageQueue(initialMessage: string) {
|
|
|
459
459
|
});
|
|
460
460
|
|
|
461
461
|
const agent = new DurableAgent({
|
|
462
|
-
model: "
|
|
462
|
+
model: "spacexai/grok-4.6",
|
|
463
463
|
instructions: "You are a helpful assistant.",
|
|
464
464
|
});
|
|
465
465
|
|
|
@@ -500,7 +500,7 @@ async function agentWithGenerationSettings() {
|
|
|
500
500
|
|
|
501
501
|
// Set default generation settings in constructor
|
|
502
502
|
const agent = new DurableAgent({
|
|
503
|
-
model: "
|
|
503
|
+
model: "spacexai/grok-4.6",
|
|
504
504
|
temperature: 0.7,
|
|
505
505
|
maxOutputTokens: 2000,
|
|
506
506
|
topP: 0.9,
|
|
@@ -548,7 +548,7 @@ async function multiStepAgent() {
|
|
|
548
548
|
"use workflow";
|
|
549
549
|
|
|
550
550
|
const agent = new DurableAgent({
|
|
551
|
-
model: "
|
|
551
|
+
model: "spacexai/grok-4.6",
|
|
552
552
|
tools: {
|
|
553
553
|
searchWeb: {
|
|
554
554
|
description: "Search the web for information",
|
|
@@ -588,7 +588,7 @@ async function agentWithCallbacks() {
|
|
|
588
588
|
"use workflow";
|
|
589
589
|
|
|
590
590
|
const agent = new DurableAgent({
|
|
591
|
-
model: "
|
|
591
|
+
model: "spacexai/grok-4.6",
|
|
592
592
|
});
|
|
593
593
|
|
|
594
594
|
await agent.stream({
|
|
@@ -630,7 +630,7 @@ async function agentWithStructuredOutput() {
|
|
|
630
630
|
"use workflow";
|
|
631
631
|
|
|
632
632
|
const agent = new DurableAgent({
|
|
633
|
-
model: "
|
|
633
|
+
model: "spacexai/grok-4.6",
|
|
634
634
|
});
|
|
635
635
|
|
|
636
636
|
const result = await agent.stream({
|
|
@@ -665,7 +665,7 @@ async function agentWithToolChoice() {
|
|
|
665
665
|
"use workflow";
|
|
666
666
|
|
|
667
667
|
const agent = new DurableAgent({
|
|
668
|
-
model: "
|
|
668
|
+
model: "spacexai/grok-4.6",
|
|
669
669
|
tools: {
|
|
670
670
|
calculator: {
|
|
671
671
|
description: "Perform calculations",
|
|
@@ -733,7 +733,7 @@ async function agentWithContext(userId: string) {
|
|
|
733
733
|
"use workflow";
|
|
734
734
|
|
|
735
735
|
const agent = new DurableAgent({
|
|
736
|
-
model: "
|
|
736
|
+
model: "spacexai/grok-4.6",
|
|
737
737
|
tools: {
|
|
738
738
|
getUserData: {
|
|
739
739
|
description: "Get user data",
|
|
@@ -771,7 +771,7 @@ async function agentWithUIMessages(userMessage: string) {
|
|
|
771
771
|
"use workflow";
|
|
772
772
|
|
|
773
773
|
const agent = new DurableAgent({
|
|
774
|
-
model: "
|
|
774
|
+
model: "spacexai/grok-4.6",
|
|
775
775
|
instructions: "You are a helpful assistant.",
|
|
776
776
|
});
|
|
777
777
|
|
|
@@ -819,7 +819,7 @@ async function agentWithToolInspection(userMessage: string) {
|
|
|
819
819
|
"use workflow";
|
|
820
820
|
|
|
821
821
|
const agent = new DurableAgent({
|
|
822
|
-
model: "
|
|
822
|
+
model: "spacexai/grok-4.6",
|
|
823
823
|
tools: {
|
|
824
824
|
checkOrderStatus: {
|
|
825
825
|
description: "Check order status",
|
|
@@ -874,7 +874,7 @@ async function agentWithTimeout(userMessage: string) {
|
|
|
874
874
|
"use workflow";
|
|
875
875
|
|
|
876
876
|
const agent = new DurableAgent({
|
|
877
|
-
model: "
|
|
877
|
+
model: "spacexai/grok-4.6",
|
|
878
878
|
});
|
|
879
879
|
|
|
880
880
|
await agent.stream({
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: "@workflow/ai"
|
|
3
|
-
description:
|
|
3
|
+
description: Deprecated AI integration APIs kept for existing Workflow applications.
|
|
4
4
|
type: overview
|
|
5
|
-
summary:
|
|
5
|
+
summary: Migrate legacy @workflow/ai APIs to AI SDK's WorkflowAgent and WorkflowChatTransport.
|
|
6
6
|
related:
|
|
7
7
|
- /docs/ai
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
The `@workflow/ai` package
|
|
10
|
+
The `@workflow/ai` package is deprecated in Workflow 5 and remains documented for existing applications. Build new agents with [`WorkflowAgent`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#workflowagent) and [`WorkflowChatTransport`](https://ai-sdk.dev/v7/docs/agents/workflow-agent#resumable-streaming-with-workflowchattransport) from `@ai-sdk/workflow`.
|
|
11
11
|
|
|
12
12
|
## Classes
|
|
13
13
|
|
|
@@ -66,7 +66,7 @@ The contract:
|
|
|
66
66
|
|
|
67
67
|
**Per-chunk continuation.** Each chunk's follow-on work starts the moment **that chunk** commits, not when the whole fold does: a chunk's step-execution queue messages publish right off its own commit (publish-after-create holds per step), and only the chunk carrying the inline pairs gates the replay's continuation: trailing chunks' commits and publishes are joined before the invocation can acknowledge its message, so the durability contract ("every create durable before ack") is unchanged.
|
|
68
68
|
|
|
69
|
-
**Pre-claimed inline pairs.** When the fold engages
|
|
69
|
+
**Pre-claimed inline pairs.** When the fold engages with at least two inline steps, the steps the runtime is about to execute inline join the batch as adjacent `[step_created, step_started]` pairs: the created row carrying the input, the started row a bare ownership-stamped claim the World folds into a born-running create. The pairs commit in a chunk of their own, ahead of the plain `step_created` and `wait_created` chunks, so the write the inline bodies wait for carries only two rows per inline step (a small transaction that commits faster than a full 32-event chunk) while the plain creates commit concurrently beside it. The inline bodies start straight off the pair chunk's commit (in parallel with the queue publishes and the sibling chunks) with no per-step claim POST at all, and a pair that loses its atomic create-claim to a concurrent delivery skips its body exactly as a lost lazy claim does. A lone inline step keeps the optimistic lazy-start path (one row, whose claim overlaps the body) even when eager creates batch beside it: the pairs share no round trip with those creates, so only two or more inline steps make a pair chunk worth the trade. A plain partition of exactly one `step_created` or `wait_created` beside the pairs is written through the ordinary single path rather than a one-row batch, and its queue message still waits for that write.
|
|
70
70
|
|
|
71
71
|
Per-event `409`s are tolerated the same way the single path tolerates `EntityConflictError` (a concurrent delivery already created the entity); any other per-event failure fails the suspension write the way a single-path rejection would. A batch carrying a `step_started` (that is, any batch with inline pairs) is **not** retried in-process on a transport blip: a pair's `409` cannot be told apart from the caller's own earlier attempt having committed it, so recovery goes through queue redelivery instead, where the step's ownership stamp routes it back to the same invocation.
|
|
72
72
|
|
|
@@ -314,6 +314,11 @@ These variables are primarily for tests, debugging, or unusual deployments.
|
|
|
314
314
|
- Group-commit window for the *leading* chunk of an idle stream. `0` sends it at once; a positive value holds it up to that many milliseconds to collect a group. This opt-in setting trades first-chunk latency for larger batches and can benefit slow-but-steady producers. Chunks arriving while a request is already in flight always coalesce into the next group regardless of this setting.
|
|
315
315
|
- Also available as `streamFlushIntervalMs` on Worlds that expose it (the env var, when set, takes precedence over the World option).
|
|
316
316
|
|
|
317
|
+
### `WORKFLOW_STEP_STREAM_DRAIN_TIMEOUT_MS`
|
|
318
|
+
|
|
319
|
+
- Default: `30000` (30 seconds)
|
|
320
|
+
- Maximum time a step waits for writes queued by a released workflow stream writer to be acknowledged by the Workflow server before recording `step_completed`. A timeout fails the step instead of exposing a completion while released-writer data remains client-side. A writer intentionally kept locked does not trigger this durability wait.
|
|
321
|
+
|
|
317
322
|
### `WORKFLOW_STREAM_MAX_INFLIGHT_CHUNKS`
|
|
318
323
|
|
|
319
324
|
- Default: `1000`
|
|
@@ -286,7 +286,7 @@ Platform-provided values such as `VERCEL_DEPLOYMENT_ID`, `VERCEL_PROJECT_ID`, an
|
|
|
286
286
|
- Factory option: none
|
|
287
287
|
- CLI flag: none
|
|
288
288
|
- Default: `http`
|
|
289
|
-
- Experimental stream-write transport capability. Set to exactly `ws` to
|
|
289
|
+
- Experimental stream-write transport capability. Set to exactly `ws` to attempt `workflow-stream-ws/v1`. The server authoritatively accepts or declines each upgrade; a decline uses HTTP directly for that writer lifetime. Stream reads remain HTTP and demand-driven.
|
|
290
290
|
- This is not tenant rollout policy or a package-version check. HTTP remains the compatibility path. `/websockets/v1` is independent of REST v2/v4 and persisted workflow `specVersion` values.
|
|
291
291
|
|
|
292
292
|
### `WORKFLOW_DISABLE_ANALYTICS_READS`
|