ai 6.0.141 → 6.0.142

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.
@@ -153,7 +153,7 @@ var import_provider_utils2 = require("@ai-sdk/provider-utils");
153
153
  var import_provider_utils3 = require("@ai-sdk/provider-utils");
154
154
 
155
155
  // src/version.ts
156
- var VERSION = true ? "6.0.141" : "0.0.0-test";
156
+ var VERSION = true ? "6.0.142" : "0.0.0-test";
157
157
 
158
158
  // src/util/download/download.ts
159
159
  var download = async ({
@@ -133,7 +133,7 @@ import {
133
133
  } from "@ai-sdk/provider-utils";
134
134
 
135
135
  // src/version.ts
136
- var VERSION = true ? "6.0.141" : "0.0.0-test";
136
+ var VERSION = true ? "6.0.142" : "0.0.0-test";
137
137
 
138
138
  // src/util/download/download.ts
139
139
  var download = async ({
@@ -20,7 +20,7 @@ These components work together:
20
20
  The ToolLoopAgent class handles these three components. Here's an agent that uses multiple tools in a loop to accomplish a task:
21
21
 
22
22
  ```ts
23
- import { ToolLoopAgent, stepCountIs, tool } from 'ai';
23
+ import { ToolLoopAgent, tool } from 'ai';
24
24
  __PROVIDER_IMPORT__;
25
25
  import { z } from 'zod';
26
26
 
@@ -48,8 +48,6 @@ const weatherAgent = new ToolLoopAgent({
48
48
  },
49
49
  }),
50
50
  },
51
- // Agent's default behavior is to stop after a maximum of 20 steps
52
- // stopWhen: stepCountIs(20),
53
51
  });
54
52
 
55
53
  const result = await weatherAgent.generate({
@@ -81,7 +81,7 @@ const codeAgent = new ToolLoopAgent({
81
81
 
82
82
  By default, agents run for 20 steps (`stopWhen: stepCountIs(20)`). In each step, the model either generates text or calls a tool. If it generates text, the agent completes. If it calls a tool, the AI SDK executes that tool.
83
83
 
84
- To let agents call multiple tools in sequence, configure `stopWhen` to allow more steps. After each tool execution, the agent triggers a new generation where the model can call another tool or generate text:
84
+ You can configure `stopWhen` differently to allow more steps. After each tool execution, the agent triggers a new generation where the model can call another tool or generate text:
85
85
 
86
86
  ```ts
87
87
  import { ToolLoopAgent, stepCountIs } from 'ai';
@@ -89,7 +89,7 @@ __PROVIDER_IMPORT__;
89
89
 
90
90
  const agent = new ToolLoopAgent({
91
91
  model: __MODEL__,
92
- stopWhen: stepCountIs(20), // Allow up to 20 steps
92
+ stopWhen: stepCountIs(50), // Increase default from 20 to 50.
93
93
  });
94
94
  ```
95
95
 
@@ -160,7 +160,7 @@ const agent = new ToolLoopAgent({
160
160
  Define structured output schemas:
161
161
 
162
162
  ```ts
163
- import { ToolLoopAgent, Output, stepCountIs } from 'ai';
163
+ import { ToolLoopAgent, Output } from 'ai';
164
164
  __PROVIDER_IMPORT__;
165
165
  import { z } from 'zod';
166
166
 
@@ -173,7 +173,6 @@ const analysisAgent = new ToolLoopAgent({
173
173
  keyPoints: z.array(z.string()),
174
174
  }),
175
175
  }),
176
- stopWhen: stepCountIs(10),
177
176
  });
178
177
 
179
178
  const { output } = await analysisAgent.generate({
@@ -16,7 +16,7 @@ The AI SDK provides built-in loop control through two parameters: `stopWhen` for
16
16
 
17
17
  ## Stop Conditions
18
18
 
19
- The `stopWhen` parameter controls when to stop execution when there are tool results in the last step. By default, agents stop after 20 steps using `stepCountIs(20)`.
19
+ The `stopWhen` parameter controls when to stop execution when there are tool results in the last step. By default, agents stop after 20 steps using `stepCountIs(20)`. This default is a safety measure to prevent runaway loops that could result in excessive API calls and costs.
20
20
 
21
21
  When you provide `stopWhen`, the agent continues executing after tool calls until a stopping condition is met. When the condition is an array, execution stops when any of the conditions are met.
22
22
 
@@ -24,6 +24,12 @@ When you provide `stopWhen`, the agent continues executing after tool calls unti
24
24
 
25
25
  The AI SDK provides several built-in stopping conditions:
26
26
 
27
+ - `stepCountIs(count)` — stops after a specified number of steps
28
+ - `hasToolCall(toolName)` — stops when a specific tool is called
29
+ - `isLoopFinished()` — never triggers, letting the loop run until the agent is naturally finished
30
+
31
+ ### Run Up to a Maximum Number of Steps
32
+
27
33
  ```ts
28
34
  import { ToolLoopAgent, stepCountIs } from 'ai';
29
35
  __PROVIDER_IMPORT__;
@@ -33,7 +39,28 @@ const agent = new ToolLoopAgent({
33
39
  tools: {
34
40
  // your tools
35
41
  },
36
- stopWhen: stepCountIs(20), // Default state: stop after 20 steps maximum
42
+ stopWhen: stepCountIs(50), // Increasing the default of 20 to 50.
43
+ });
44
+
45
+ const result = await agent.generate({
46
+ prompt: 'Analyze this dataset and create a summary report',
47
+ });
48
+ ```
49
+
50
+ ### Run Until Finished
51
+
52
+ If you want the agent to run until the model naturally stops making tool calls, use `isLoopFinished()`. This removes the default step limit:
53
+
54
+ ```ts
55
+ import { ToolLoopAgent, isLoopFinished } from 'ai';
56
+ __PROVIDER_IMPORT__;
57
+
58
+ const agent = new ToolLoopAgent({
59
+ model: __MODEL__,
60
+ tools: {
61
+ // your tools
62
+ },
63
+ stopWhen: isLoopFinished(), // No maximum step limit.
37
64
  });
38
65
 
39
66
  const result = await agent.generate({
@@ -41,6 +68,12 @@ const result = await agent.generate({
41
68
  });
42
69
  ```
43
70
 
71
+ <Note>
72
+ Use `isLoopFinished()` with caution. Without a step limit, the agent could
73
+ potentially run indefinitely or incur significant costs if the model keeps
74
+ making tool calls.
75
+ </Note>
76
+
44
77
  ### Combine Multiple Conditions
45
78
 
46
79
  Combine multiple stopping conditions. The loop stops when it meets any condition:
@@ -187,7 +187,7 @@ pnpm add @vectorize-io/hindsight-ai-sdk @vectorize-io/hindsight-client
187
187
  __PROVIDER_IMPORT__;
188
188
  import { HindsightClient } from '@vectorize-io/hindsight-client';
189
189
  import { createHindsightTools } from '@vectorize-io/hindsight-ai-sdk';
190
- import { ToolLoopAgent, stepCountIs } from 'ai';
190
+ import { ToolLoopAgent } from 'ai';
191
191
  import { openai } from '@ai-sdk/openai';
192
192
 
193
193
  const client = new HindsightClient({ baseUrl: process.env.HINDSIGHT_API_URL });
@@ -195,7 +195,6 @@ const client = new HindsightClient({ baseUrl: process.env.HINDSIGHT_API_URL });
195
195
  const agent = new ToolLoopAgent({
196
196
  model: __MODEL__,
197
197
  tools: createHindsightTools({ client, bankId: 'user-123' }),
198
- stopWhen: stepCountIs(10),
199
198
  instructions: 'You are a helpful assistant with long-term memory.',
200
199
  });
201
200
 
@@ -226,6 +226,14 @@ When using `useChat`, the approval flow is handled through UI state. See [Chatbo
226
226
 
227
227
  With the `stopWhen` setting, you can enable multi-step calls in `generateText` and `streamText`. When `stopWhen` is set and the model generates a tool call, the AI SDK will trigger a new generation passing in the tool result until there are no further tool calls or the stopping condition is met.
228
228
 
229
+ The AI SDK provides several built-in stopping conditions:
230
+
231
+ - `stepCountIs(count)` — stops after a specified number of steps (default: `stepCountIs(20)`)
232
+ - `hasToolCall(toolName)` — stops when a specific tool is called
233
+ - `isLoopFinished()` — never triggers, letting the loop run until naturally finished
234
+
235
+ You can also combine multiple conditions in an array or create custom conditions. See [Loop Control](/docs/agents/loop-control) for more details.
236
+
229
237
  <Note>
230
238
  The `stopWhen` conditions are only evaluated when the last step contains tool
231
239
  results.
@@ -10,10 +10,10 @@ function to generate images based on a given prompt using an image model.
10
10
 
11
11
  ```tsx
12
12
  import { generateImage } from 'ai';
13
- import { openai } from '@ai-sdk/openai';
13
+ __PROVIDER_IMPORT__;
14
14
 
15
15
  const { image } = await generateImage({
16
- model: openai.image('dall-e-3'),
16
+ model: __IMAGE_MODEL__,
17
17
  prompt: 'Santa Claus driving a Cadillac',
18
18
  });
19
19
  ```
@@ -38,10 +38,10 @@ Models only support a few sizes, and the supported sizes are different for each
38
38
 
39
39
  ```tsx highlight={"7"}
40
40
  import { generateImage } from 'ai';
41
- import { openai } from '@ai-sdk/openai';
41
+ __PROVIDER_IMPORT__;
42
42
 
43
43
  const { image } = await generateImage({
44
- model: openai.image('dall-e-3'),
44
+ model: __IMAGE_MODEL__,
45
45
  prompt: 'Santa Claus driving a Cadillac',
46
46
  size: '1024x1024',
47
47
  });
@@ -54,10 +54,10 @@ Models only support a few aspect ratios, and the supported aspect ratios are dif
54
54
 
55
55
  ```tsx highlight={"7"}
56
56
  import { generateImage } from 'ai';
57
- import { vertex } from '@ai-sdk/google-vertex';
57
+ __PROVIDER_IMPORT__;
58
58
 
59
59
  const { image } = await generateImage({
60
- model: vertex.image('imagen-4.0-generate-001'),
60
+ model: __IMAGE_MODEL__,
61
61
  prompt: 'Santa Claus driving a Cadillac',
62
62
  aspectRatio: '16:9',
63
63
  });
@@ -69,10 +69,10 @@ const { image } = await generateImage({
69
69
 
70
70
  ```tsx highlight={"7"}
71
71
  import { generateImage } from 'ai';
72
- import { openai } from '@ai-sdk/openai';
72
+ __PROVIDER_IMPORT__;
73
73
 
74
74
  const { images } = await generateImage({
75
- model: openai.image('dall-e-2'),
75
+ model: __IMAGE_MODEL__,
76
76
  prompt: 'Santa Claus driving a Cadillac',
77
77
  n: 4, // number of images to generate
78
78
  });
@@ -89,7 +89,7 @@ If needed, you can override this behavior using the `maxImagesPerCall` setting w
89
89
 
90
90
  ```tsx
91
91
  const { images } = await generateImage({
92
- model: openai.image('dall-e-2'),
92
+ model: __IMAGE_MODEL__,
93
93
  prompt: 'Santa Claus driving a Cadillac',
94
94
  maxImagesPerCall: 5, // Override the default batch size
95
95
  n: 10, // Will make 2 calls of 5 images each
@@ -103,10 +103,10 @@ If supported by the model, the same seed will always produce the same image.
103
103
 
104
104
  ```tsx highlight={"7"}
105
105
  import { generateImage } from 'ai';
106
- import { openai } from '@ai-sdk/openai';
106
+ __PROVIDER_IMPORT__;
107
107
 
108
108
  const { image } = await generateImage({
109
- model: openai.image('dall-e-3'),
109
+ model: __IMAGE_MODEL__,
110
110
  prompt: 'Santa Claus driving a Cadillac',
111
111
  seed: 1234567890,
112
112
  });
@@ -140,11 +140,11 @@ type [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSigna
140
140
  that you can use to abort the image generation process or set a timeout.
141
141
 
142
142
  ```ts highlight={"7"}
143
- import { openai } from '@ai-sdk/openai';
144
143
  import { generateImage } from 'ai';
144
+ __PROVIDER_IMPORT__;
145
145
 
146
146
  const { image } = await generateImage({
147
- model: openai.image('dall-e-3'),
147
+ model: __IMAGE_MODEL__,
148
148
  prompt: 'Santa Claus driving a Cadillac',
149
149
  abortSignal: AbortSignal.timeout(1000), // Abort after 1 second
150
150
  });
@@ -156,11 +156,11 @@ const { image } = await generateImage({
156
156
  that you can use to add custom headers to the image generation request.
157
157
 
158
158
  ```ts highlight={"7"}
159
- import { openai } from '@ai-sdk/openai';
160
159
  import { generateImage } from 'ai';
160
+ __PROVIDER_IMPORT__;
161
161
 
162
162
  const { image } = await generateImage({
163
- model: openai.image('dall-e-3'),
163
+ model: __IMAGE_MODEL__,
164
164
  prompt: 'Santa Claus driving a Cadillac',
165
165
  headers: { 'X-Custom-Header': 'custom-value' },
166
166
  });
@@ -172,7 +172,7 @@ If the model returns warnings, e.g. for unsupported parameters, they will be ava
172
172
 
173
173
  ```tsx
174
174
  const { image, warnings } = await generateImage({
175
- model: openai.image('dall-e-3'),
175
+ model: __IMAGE_MODEL__,
176
176
  prompt: 'Santa Claus driving a Cadillac',
177
177
  });
178
178
  ```
@@ -236,10 +236,10 @@ Here is an example that sets a default size when none is provided:
236
236
 
237
237
  ```ts
238
238
  import { generateImage, wrapImageModel } from 'ai';
239
- import { openai } from '@ai-sdk/openai';
239
+ __PROVIDER_IMPORT__;
240
240
 
241
241
  const model = wrapImageModel({
242
- model: openai.image('gpt-image-1'),
242
+ model: __IMAGE_MODEL__,
243
243
  middleware: {
244
244
  specificationVersion: 'v3',
245
245
  transformParams: async ({ params }) => ({
@@ -15,10 +15,10 @@ function to generate videos based on a given prompt using a video model.
15
15
 
16
16
  ```tsx
17
17
  import { experimental_generateVideo as generateVideo } from 'ai';
18
- import { fal } from '@ai-sdk/fal';
18
+ __PROVIDER_IMPORT__;
19
19
 
20
20
  const { video } = await generateVideo({
21
- model: fal.video('luma-dream-machine/ray-2'),
21
+ model: __VIDEO_MODEL__,
22
22
  prompt: 'A cat walking on a treadmill',
23
23
  });
24
24
  ```
@@ -39,10 +39,10 @@ Models only support a few aspect ratios, and the supported aspect ratios are dif
39
39
 
40
40
  ```tsx highlight={"7"}
41
41
  import { experimental_generateVideo as generateVideo } from 'ai';
42
- import { fal } from '@ai-sdk/fal';
42
+ __PROVIDER_IMPORT__;
43
43
 
44
44
  const { video } = await generateVideo({
45
- model: fal.video('luma-dream-machine/ray-2'),
45
+ model: __VIDEO_MODEL__,
46
46
  prompt: 'A cat walking on a treadmill',
47
47
  aspectRatio: '16:9',
48
48
  });
@@ -55,10 +55,10 @@ Models only support specific resolutions, and the supported resolutions are diff
55
55
 
56
56
  ```tsx highlight={"7"}
57
57
  import { experimental_generateVideo as generateVideo } from 'ai';
58
- import { google } from '@ai-sdk/google';
58
+ __PROVIDER_IMPORT__;
59
59
 
60
60
  const { video } = await generateVideo({
61
- model: google.video('veo-2.0-generate-001'),
61
+ model: __VIDEO_MODEL__,
62
62
  prompt: 'A serene mountain landscape at sunset',
63
63
  resolution: '1280x720',
64
64
  });
@@ -70,10 +70,10 @@ Some video models support specifying the duration of the generated video in seco
70
70
 
71
71
  ```tsx highlight={"7"}
72
72
  import { experimental_generateVideo as generateVideo } from 'ai';
73
- import { fal } from '@ai-sdk/fal';
73
+ __PROVIDER_IMPORT__;
74
74
 
75
75
  const { video } = await generateVideo({
76
- model: fal.video('luma-dream-machine/ray-2'),
76
+ model: __VIDEO_MODEL__,
77
77
  prompt: 'A timelapse of clouds moving across the sky',
78
78
  duration: 5,
79
79
  });
@@ -85,10 +85,10 @@ Some video models allow you to specify the frames per second for the generated v
85
85
 
86
86
  ```tsx highlight={"7"}
87
87
  import { experimental_generateVideo as generateVideo } from 'ai';
88
- import { fal } from '@ai-sdk/fal';
88
+ __PROVIDER_IMPORT__;
89
89
 
90
90
  const { video } = await generateVideo({
91
- model: fal.video('luma-dream-machine/ray-2'),
91
+ model: __VIDEO_MODEL__,
92
92
  prompt: 'A hummingbird in slow motion',
93
93
  fps: 24,
94
94
  });
@@ -100,10 +100,10 @@ const { video } = await generateVideo({
100
100
 
101
101
  ```tsx highlight={"7"}
102
102
  import { experimental_generateVideo as generateVideo } from 'ai';
103
- import { google } from '@ai-sdk/google';
103
+ __PROVIDER_IMPORT__;
104
104
 
105
105
  const { videos } = await generateVideo({
106
- model: google.video('veo-2.0-generate-001'),
106
+ model: __VIDEO_MODEL__,
107
107
  prompt: 'A rocket launching into space',
108
108
  n: 3, // number of videos to generate
109
109
  });
@@ -120,7 +120,7 @@ If needed, you can override this behavior using the `maxVideosPerCall` setting:
120
120
 
121
121
  ```tsx
122
122
  const { videos } = await generateVideo({
123
- model: google.video('veo-2.0-generate-001'),
123
+ model: __VIDEO_MODEL__,
124
124
  prompt: 'A rocket launching into space',
125
125
  maxVideosPerCall: 2, // Override the default batch size
126
126
  n: 4, // Will make 2 calls of 2 videos each
@@ -133,10 +133,10 @@ Some video models support generating videos from an input image. You can provide
133
133
 
134
134
  ```tsx highlight={"7-10"}
135
135
  import { experimental_generateVideo as generateVideo } from 'ai';
136
- import { fal } from '@ai-sdk/fal';
136
+ __PROVIDER_IMPORT__;
137
137
 
138
138
  const { video } = await generateVideo({
139
- model: fal.video('hunyuan-video'),
139
+ model: __VIDEO_MODEL__,
140
140
  prompt: {
141
141
  image: 'https://example.com/my-image.png',
142
142
  text: 'Animate this image with gentle motion',
@@ -148,7 +148,7 @@ You can also provide the image as a base64-encoded string or `Uint8Array`:
148
148
 
149
149
  ```tsx
150
150
  const { video } = await generateVideo({
151
- model: fal.video('hunyuan-video'),
151
+ model: __VIDEO_MODEL__,
152
152
  prompt: {
153
153
  image: imageBase64String, // or imageUint8Array
154
154
  text: 'Animate this image',
@@ -163,10 +163,10 @@ If supported by the model, the same seed will always produce the same video.
163
163
 
164
164
  ```tsx highlight={"7"}
165
165
  import { experimental_generateVideo as generateVideo } from 'ai';
166
- import { fal } from '@ai-sdk/fal';
166
+ __PROVIDER_IMPORT__;
167
167
 
168
168
  const { video } = await generateVideo({
169
- model: fal.video('luma-dream-machine/ray-2'),
169
+ model: __VIDEO_MODEL__,
170
170
  prompt: 'A cat walking on a treadmill',
171
171
  seed: 1234567890,
172
172
  });
@@ -200,11 +200,11 @@ type [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSigna
200
200
  that you can use to abort the video generation process or set a timeout.
201
201
 
202
202
  ```ts highlight={"7"}
203
- import { fal } from '@ai-sdk/fal';
204
203
  import { experimental_generateVideo as generateVideo } from 'ai';
204
+ __PROVIDER_IMPORT__;
205
205
 
206
206
  const { video } = await generateVideo({
207
- model: fal.video('luma-dream-machine/ray-2'),
207
+ model: __VIDEO_MODEL__,
208
208
  prompt: 'A cat walking on a treadmill',
209
209
  abortSignal: AbortSignal.timeout(60000), // Abort after 60 seconds
210
210
  });
@@ -249,11 +249,11 @@ const { video } = await generateVideo({
249
249
  that you can use to add custom headers to the video generation request.
250
250
 
251
251
  ```ts highlight={"7"}
252
- import { fal } from '@ai-sdk/fal';
253
252
  import { experimental_generateVideo as generateVideo } from 'ai';
253
+ __PROVIDER_IMPORT__;
254
254
 
255
255
  const { video } = await generateVideo({
256
- model: fal.video('luma-dream-machine/ray-2'),
256
+ model: __VIDEO_MODEL__,
257
257
  prompt: 'A cat walking on a treadmill',
258
258
  headers: { 'X-Custom-Header': 'custom-value' },
259
259
  });
@@ -265,7 +265,7 @@ If the model returns warnings, e.g. for unsupported parameters, they will be ava
265
265
 
266
266
  ```tsx
267
267
  const { video, warnings } = await generateVideo({
268
- model: fal.video('luma-dream-machine/ray-2'),
268
+ model: __VIDEO_MODEL__,
269
269
  prompt: 'A cat walking on a treadmill',
270
270
  });
271
271
  ```
@@ -298,7 +298,7 @@ When generating multiple videos with `n > 1`, you can also access per-call metad
298
298
 
299
299
  ```tsx
300
300
  const { videos, responses } = await generateVideo({
301
- model: google.video('veo-2.0-generate-001'),
301
+ model: __VIDEO_MODEL__,
302
302
  prompt: 'A rocket launching into space',
303
303
  n: 5, // May require multiple API calls
304
304
  });
@@ -12,9 +12,10 @@ such as creating visual content or generating images for data augmentation.
12
12
 
13
13
  ```ts
14
14
  import { generateImage } from 'ai';
15
+ __PROVIDER_IMPORT__;
15
16
 
16
17
  const { images } = await generateImage({
17
- model: openai.image('dall-e-3'),
18
+ model: __IMAGE_MODEL__,
18
19
  prompt: 'A futuristic cityscape at sunset',
19
20
  n: 3,
20
21
  size: '1024x1024',
@@ -17,9 +17,10 @@ such as creating visual content, animations, or generating videos from images.
17
17
 
18
18
  ```ts
19
19
  import { experimental_generateVideo as generateVideo } from 'ai';
20
+ __PROVIDER_IMPORT__;
20
21
 
21
22
  const { videos } = await generateVideo({
22
- model: fal.video('luma-dream-machine/ray-2'),
23
+ model: __VIDEO_MODEL__,
23
24
  prompt: 'A cat walking on a treadmill',
24
25
  aspectRatio: '16:9',
25
26
  });
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: isLoopFinished
3
+ description: API Reference for isLoopFinished.
4
+ ---
5
+
6
+ # `isLoopFinished()`
7
+
8
+ Creates a stop condition that never triggers, letting the agent loop run until it naturally finishes (i.e., the model stops making tool calls).
9
+
10
+ By default, `ToolLoopAgent` uses `stepCountIs(20)` as a safety measure to prevent runaway loops that could result in excessive API calls and costs. If you are confident that your agent will terminate naturally or you are less concerned about costs, `isLoopFinished()` removes that limit and lets the agent run until the model is truly done.
11
+
12
+ ```ts
13
+ import { ToolLoopAgent, isLoopFinished } from 'ai';
14
+ __PROVIDER_IMPORT__;
15
+
16
+ const agent = new ToolLoopAgent({
17
+ model: __MODEL__,
18
+ tools: {
19
+ // your tools
20
+ },
21
+ stopWhen: isLoopFinished(),
22
+ });
23
+
24
+ const result = await agent.generate({
25
+ prompt: 'Analyze this dataset and create a summary report',
26
+ });
27
+ ```
28
+
29
+ ## Import
30
+
31
+ <Snippet text={`import { isLoopFinished } from "ai"`} prompt={false} />
32
+
33
+ ## API Signature
34
+
35
+ ### Parameters
36
+
37
+ This function takes no parameters.
38
+
39
+ ### Returns
40
+
41
+ A `StopCondition` function that always returns `false`, meaning it never triggers the stop condition. The agent loop will only stop through its natural termination conditions:
42
+
43
+ - The model stops making tool calls, or
44
+ - A tool without an `execute` function is called, or
45
+ - A tool call needs approval
46
+
47
+ ## Examples
48
+
49
+ ### Basic Usage
50
+
51
+ Let the agent run until it's finished:
52
+
53
+ ```ts
54
+ import { ToolLoopAgent, isLoopFinished } from 'ai';
55
+
56
+ const agent = new ToolLoopAgent({
57
+ model: yourModel,
58
+ tools: yourTools,
59
+ stopWhen: isLoopFinished(),
60
+ });
61
+ ```
62
+
63
+ ### Combining with Other Conditions
64
+
65
+ You can combine `isLoopFinished()` with other conditions. Since `isLoopFinished()` never triggers, the other conditions still apply:
66
+
67
+ ```ts
68
+ import { ToolLoopAgent, isLoopFinished, hasToolCall } from 'ai';
69
+
70
+ const agent = new ToolLoopAgent({
71
+ model: yourModel,
72
+ tools: yourTools,
73
+ stopWhen: [isLoopFinished(), hasToolCall('finalAnswer')],
74
+ });
75
+ ```
76
+
77
+ In practice, this does not make much sense in this context, since you could just omit `isLoopFinished()`.
78
+
79
+ ## See also
80
+
81
+ - [`stepCountIs()`](/docs/reference/ai-sdk-core/step-count-is)
82
+ - [`hasToolCall()`](/docs/reference/ai-sdk-core/has-tool-call)
83
+ - [`ToolLoopAgent`](/docs/reference/ai-sdk-core/tool-loop-agent)
@@ -130,6 +130,24 @@ It also contains the following helper functions:
130
130
  'Extracts JSON from text content by stripping markdown code fences.',
131
131
  href: '/docs/reference/ai-sdk-core/extract-json-middleware',
132
132
  },
133
+ {
134
+ title: 'stepCountIs()',
135
+ description:
136
+ 'Creates a stop condition that triggers after a specified number of steps.',
137
+ href: '/docs/reference/ai-sdk-core/step-count-is',
138
+ },
139
+ {
140
+ title: 'hasToolCall()',
141
+ description:
142
+ 'Creates a stop condition that triggers when a specific tool is called.',
143
+ href: '/docs/reference/ai-sdk-core/has-tool-call',
144
+ },
145
+ {
146
+ title: 'isLoopFinished()',
147
+ description:
148
+ 'Creates a stop condition that lets the agent loop run until it naturally finishes.',
149
+ href: '/docs/reference/ai-sdk-core/loop-finished',
150
+ },
133
151
  {
134
152
  title: 'simulateStreamingMiddleware()',
135
153
  description:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai",
3
- "version": "6.0.141",
3
+ "version": "6.0.142",
4
4
  "description": "AI SDK by Vercel - build apps like ChatGPT, Claude, Gemini, and more with a single interface for any model using the Vercel AI Gateway or go direct to OpenAI, Anthropic, Google, or any other model provider.",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "dependencies": {
47
47
  "@opentelemetry/api": "1.9.0",
48
- "@ai-sdk/gateway": "3.0.83",
48
+ "@ai-sdk/gateway": "3.0.84",
49
49
  "@ai-sdk/provider": "3.0.8",
50
50
  "@ai-sdk/provider-utils": "4.0.21"
51
51
  },
@@ -24,7 +24,12 @@ export { pruneMessages } from './prune-messages';
24
24
  export type { ReasoningOutput } from './reasoning-output';
25
25
  export { smoothStream, type ChunkDetector } from './smooth-stream';
26
26
  export type { StepResult } from './step-result';
27
- export { hasToolCall, stepCountIs, type StopCondition } from './stop-condition';
27
+ export {
28
+ hasToolCall,
29
+ isLoopFinished,
30
+ stepCountIs,
31
+ type StopCondition,
32
+ } from './stop-condition';
28
33
  export {
29
34
  streamText,
30
35
  type StreamTextOnChunkCallback,
@@ -9,6 +9,10 @@ export function stepCountIs(stepCount: number): StopCondition<any> {
9
9
  return ({ steps }) => steps.length === stepCount;
10
10
  }
11
11
 
12
+ export function isLoopFinished(): StopCondition<any> {
13
+ return () => false;
14
+ }
15
+
12
16
  export function hasToolCall(toolName: string): StopCondition<any> {
13
17
  return ({ steps }) =>
14
18
  steps[steps.length - 1]?.toolCalls?.some(