@ai-sdk/anthropic 3.0.101 → 3.0.102

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.
@@ -191,7 +191,9 @@ const result = streamText({
191
191
 
192
192
  ### Effort
193
193
 
194
- Anthropic introduced an `effort` option with `claude-opus-4-5` that affects thinking, text responses, and function calls. Effort defaults to `high` and you can set it to `medium` or `low` to save tokens and to lower time-to-last-token latency (TTLT). `claude-opus-4-7` and `claude-sonnet-5` additionally support `xhigh` for maximum reasoning effort.
194
+ Anthropic introduced an `effort` option with `claude-opus-4-5` that affects thinking, text responses, and function calls. Effort defaults to `high` and you can set it to `medium` or `low` to save tokens and to lower time-to-last-token latency (TTLT). `claude-opus-4-7`, `claude-opus-5`, and `claude-sonnet-5` additionally support `xhigh` for maximum reasoning effort.
195
+
196
+ On `claude-opus-5`, thinking can only be disabled at effort levels up to and including `high`. When you combine `thinking: { type: 'disabled' }` with `effort: 'xhigh'` or `effort: 'max'`, the AI SDK lowers the effort to `high` and emits a warning instead of sending a request that the API would reject.
195
197
 
196
198
  ```ts highlight="8-10"
197
199
  import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
@@ -317,7 +319,26 @@ A classifier block looks like this:
317
319
 
318
320
  Branch on the finish reason rather than on the presence of `stop_details` — the API may return a refusal with no details at all.
319
321
 
320
- To avoid receiving a classifier block, pass the `fallbacks` option. When the primary model's classifiers block a turn, the API automatically retries it server-side on the next model in the chain and returns that model's answer. The required beta header is added for you.
322
+ To avoid receiving a classifier block, pass the `fallbacks` option. When the primary model's classifiers block a turn, the API automatically retries it server-side on a fallback model and returns that model's answer. The required beta header is added for you.
323
+
324
+ The recommended configuration is `fallbacks: 'default'`, which lets the API route the retry to Anthropic's recommended fallback model based on the refusal category and removes the need to migrate when a fallback model is deprecated:
325
+
326
+ ```ts highlight="8-10"
327
+ import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
328
+ import { generateText } from 'ai';
329
+
330
+ const { text } = await generateText({
331
+ model: anthropic('claude-fable-5'),
332
+ prompt: 'Explain the history of cryptography.',
333
+ providerOptions: {
334
+ anthropic: {
335
+ fallbacks: 'default',
336
+ } satisfies AnthropicLanguageModelOptions,
337
+ },
338
+ });
339
+ ```
340
+
341
+ You can also pin an explicit fallback chain:
321
342
 
322
343
  ```ts highlight="8-10"
323
344
  import { anthropic, AnthropicLanguageModelOptions } from '@ai-sdk/anthropic';
@@ -1177,6 +1198,61 @@ const result = await generateText({
1177
1198
 
1178
1199
  This sends `tool_reference` blocks to Anthropic, which loads the corresponding deferred tool schemas into Claude's context.
1179
1200
 
1201
+ ### Mid-Conversation Tool Changes
1202
+
1203
+ With `claude-opus-4-8`, you can add or remove tools between turns of a conversation without invalidating the prompt cache. Attach `toolChanges` to a system message that appears mid-conversation (right before an assistant message or at the end of the messages). The required `mid-conversation-tool-changes-2026-07-01` beta header is added automatically.
1204
+
1205
+ Tools referenced by a `tool_addition` must be declared in the `tools` option — typically with `deferLoading: true`, so they are not loaded into context until the addition surfaces them. A `tool_removal` removes a previously available tool from the conversation going forward.
1206
+
1207
+ ```ts
1208
+ import { anthropic } from '@ai-sdk/anthropic';
1209
+ import { generateText, tool } from 'ai';
1210
+ import { z } from 'zod';
1211
+
1212
+ const result = await generateText({
1213
+ model: anthropic('claude-opus-4-8'),
1214
+ // required for system messages inside `messages`:
1215
+ allowSystemInMessages: true,
1216
+ tools: {
1217
+ get_weather: tool({
1218
+ description: 'Get weather',
1219
+ inputSchema: z.object({ city: z.string() }),
1220
+ }),
1221
+ get_forecast: tool({
1222
+ description: 'Get 5-day forecast',
1223
+ inputSchema: z.object({ city: z.string() }),
1224
+ providerOptions: {
1225
+ // declared up front but not loaded until a tool_addition surfaces it
1226
+ anthropic: { deferLoading: true },
1227
+ },
1228
+ }),
1229
+ },
1230
+ messages: [
1231
+ { role: 'user', content: 'What tools do you have for weather in Paris?' },
1232
+ {
1233
+ role: 'system',
1234
+ content: '',
1235
+ providerOptions: {
1236
+ anthropic: {
1237
+ toolChanges: [
1238
+ { type: 'tool_addition', toolName: 'get_forecast' },
1239
+ { type: 'tool_removal', toolName: 'get_weather' },
1240
+ ],
1241
+ },
1242
+ },
1243
+ },
1244
+ ],
1245
+ });
1246
+ ```
1247
+
1248
+ To change a tool's definition, remove the old definition at the end of one request, then carry the conversation forward with the updated definition in `tools` on the next request.
1249
+
1250
+ <Note>
1251
+ Tool changes are not supported on the initial system message. The AI SDK
1252
+ ignores them there and emits a warning — configure the initial tool set via
1253
+ the `tools` option instead.
1254
+ </Note>
1255
+
1180
1256
  ### MCP Connectors
1181
1257
 
1182
1258
  Anthropic supports connecting to [MCP servers](https://docs.claude.com/en/docs/agents-and-tools/mcp-connector) as part of their execution.
@@ -1559,6 +1635,7 @@ and the `mediaType` should be set to `'application/pdf'`.
1559
1635
 
1560
1636
  | Model | Image Input | Object Generation | Tool Usage | Computer Use | Web Search | Tool Search | Compaction |
1561
1637
  | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- | ------------------- |
1638
+ | `claude-opus-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
1562
1639
  | `claude-sonnet-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
1563
1640
  | `claude-fable-5` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
1564
1641
  | `claude-opus-4-8` | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> | <Check size={18} /> |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/anthropic",
3
- "version": "3.0.101",
3
+ "version": "3.0.102",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -23,7 +23,20 @@ export type AnthropicCacheControl = {
23
23
 
24
24
  export interface AnthropicSystemMessage {
25
25
  role: 'system';
26
- content: Array<AnthropicTextContent>;
26
+ content: Array<AnthropicTextContent | AnthropicToolChangeContent>;
27
+ }
28
+
29
+ /**
30
+ * Mid-conversation tool change content block. Adds or removes a tool from the
31
+ * conversation's tool set without invalidating the prompt cache.
32
+ *
33
+ * Only valid inside system messages that appear in the `messages` array.
34
+ * Requires the `mid-conversation-tool-changes-2026-07-01` beta.
35
+ */
36
+ export interface AnthropicToolChangeContent {
37
+ type: 'tool_addition' | 'tool_removal';
38
+ tool: { type: 'tool_reference'; name: string };
39
+ cache_control?: never;
27
40
  }
28
41
 
29
42
  export interface AnthropicUserMessage {
@@ -276,6 +276,7 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
276
276
  maxOutputTokens: maxOutputTokensForModel,
277
277
  supportsStructuredOutput: modelSupportsStructuredOutput,
278
278
  rejectsSamplingParameters,
279
+ rejectsThinkingDisabledAboveHighEffort,
279
280
  isKnownModel,
280
281
  } = getModelCapabilities(this.modelId);
281
282
 
@@ -397,6 +398,25 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
397
398
  toolNameMapping,
398
399
  });
399
400
 
401
+ // Newer models only allow disabling thinking at effort levels up to and
402
+ // including `high`; at `xhigh` and `max` the API returns a 400. Lower
403
+ // the effort to `high` to preserve the explicit request to run without
404
+ // thinking.
405
+ if (
406
+ rejectsThinkingDisabledAboveHighEffort &&
407
+ anthropicOptions?.thinking?.type === 'disabled' &&
408
+ (anthropicOptions.effort === 'xhigh' || anthropicOptions.effort === 'max')
409
+ ) {
410
+ warnings.push({
411
+ type: 'unsupported',
412
+ feature: 'providerOptions.anthropic.effort',
413
+ details:
414
+ `effort '${anthropicOptions.effort}' is not supported by ${this.modelId} when thinking is disabled. ` +
415
+ `The effort has been lowered to 'high'.`,
416
+ });
417
+ anthropicOptions.effort = 'high';
418
+ }
419
+
400
420
  const thinkingType = anthropicOptions?.thinking?.type;
401
421
  const isThinking =
402
422
  thinkingType === 'enabled' || thinkingType === 'adaptive';
@@ -468,8 +488,9 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
468
488
  ...(anthropicOptions?.inferenceGeo && {
469
489
  inference_geo: anthropicOptions.inferenceGeo,
470
490
  }),
471
- ...(anthropicOptions?.fallbacks &&
472
- anthropicOptions.fallbacks.length > 0 && {
491
+ ...(anthropicOptions?.fallbacks != null &&
492
+ (anthropicOptions.fallbacks === 'default' ||
493
+ anthropicOptions.fallbacks.length > 0) && {
473
494
  fallbacks: anthropicOptions.fallbacks,
474
495
  }),
475
496
  ...(anthropicOptions?.cacheControl && {
@@ -698,7 +719,12 @@ export class AnthropicMessagesLanguageModel implements LanguageModelV3 {
698
719
  betas.add('fast-mode-2026-02-01');
699
720
  }
700
721
 
701
- if (anthropicOptions?.fallbacks && anthropicOptions.fallbacks.length > 0) {
722
+ if (anthropicOptions?.fallbacks === 'default') {
723
+ betas.add('server-side-fallback-2026-07-01');
724
+ } else if (
725
+ anthropicOptions?.fallbacks &&
726
+ anthropicOptions.fallbacks.length > 0
727
+ ) {
702
728
  betas.add('server-side-fallback-2026-06-01');
703
729
  }
704
730
 
@@ -2602,9 +2628,18 @@ export function getModelCapabilities(modelId: string): {
2602
2628
  maxOutputTokens: number;
2603
2629
  supportsStructuredOutput: boolean;
2604
2630
  rejectsSamplingParameters: boolean;
2631
+ rejectsThinkingDisabledAboveHighEffort: boolean;
2605
2632
  isKnownModel: boolean;
2606
2633
  } {
2607
- if (
2634
+ if (modelId.includes('claude-opus-5')) {
2635
+ return {
2636
+ maxOutputTokens: 128000,
2637
+ supportsStructuredOutput: true,
2638
+ rejectsSamplingParameters: true,
2639
+ rejectsThinkingDisabledAboveHighEffort: true,
2640
+ isKnownModel: true,
2641
+ };
2642
+ } else if (
2608
2643
  modelId.includes('claude-opus-4-8') ||
2609
2644
  modelId.includes('claude-opus-4-7') ||
2610
2645
  modelId.includes('claude-fable-5') ||
@@ -2614,6 +2649,7 @@ export function getModelCapabilities(modelId: string): {
2614
2649
  maxOutputTokens: 128000,
2615
2650
  supportsStructuredOutput: true,
2616
2651
  rejectsSamplingParameters: true,
2652
+ rejectsThinkingDisabledAboveHighEffort: false,
2617
2653
  isKnownModel: true,
2618
2654
  };
2619
2655
  } else if (
@@ -2624,6 +2660,7 @@ export function getModelCapabilities(modelId: string): {
2624
2660
  maxOutputTokens: 128000,
2625
2661
  supportsStructuredOutput: true,
2626
2662
  rejectsSamplingParameters: false,
2663
+ rejectsThinkingDisabledAboveHighEffort: false,
2627
2664
  isKnownModel: true,
2628
2665
  };
2629
2666
  } else if (
@@ -2635,6 +2672,7 @@ export function getModelCapabilities(modelId: string): {
2635
2672
  maxOutputTokens: 64000,
2636
2673
  supportsStructuredOutput: true,
2637
2674
  rejectsSamplingParameters: false,
2675
+ rejectsThinkingDisabledAboveHighEffort: false,
2638
2676
  isKnownModel: true,
2639
2677
  };
2640
2678
  } else if (modelId.includes('claude-opus-4-1')) {
@@ -2642,6 +2680,7 @@ export function getModelCapabilities(modelId: string): {
2642
2680
  maxOutputTokens: 32000,
2643
2681
  supportsStructuredOutput: true,
2644
2682
  rejectsSamplingParameters: false,
2683
+ rejectsThinkingDisabledAboveHighEffort: false,
2645
2684
  isKnownModel: true,
2646
2685
  };
2647
2686
  } else if (modelId.includes('claude-sonnet-4-')) {
@@ -2649,6 +2688,7 @@ export function getModelCapabilities(modelId: string): {
2649
2688
  maxOutputTokens: 64000,
2650
2689
  supportsStructuredOutput: false,
2651
2690
  rejectsSamplingParameters: false,
2691
+ rejectsThinkingDisabledAboveHighEffort: false,
2652
2692
  isKnownModel: true,
2653
2693
  };
2654
2694
  } else if (modelId.includes('claude-opus-4-')) {
@@ -2656,6 +2696,7 @@ export function getModelCapabilities(modelId: string): {
2656
2696
  maxOutputTokens: 32000,
2657
2697
  supportsStructuredOutput: false,
2658
2698
  rejectsSamplingParameters: false,
2699
+ rejectsThinkingDisabledAboveHighEffort: false,
2659
2700
  isKnownModel: true,
2660
2701
  };
2661
2702
  } else if (modelId.includes('claude-3-haiku')) {
@@ -2663,6 +2704,7 @@ export function getModelCapabilities(modelId: string): {
2663
2704
  maxOutputTokens: 4096,
2664
2705
  supportsStructuredOutput: false,
2665
2706
  rejectsSamplingParameters: false,
2707
+ rejectsThinkingDisabledAboveHighEffort: false,
2666
2708
  isKnownModel: true,
2667
2709
  };
2668
2710
  } else if (
@@ -2672,6 +2714,7 @@ export function getModelCapabilities(modelId: string): {
2672
2714
  maxOutputTokens: 4096,
2673
2715
  supportsStructuredOutput: false,
2674
2716
  rejectsSamplingParameters: false,
2717
+ rejectsThinkingDisabledAboveHighEffort: false,
2675
2718
  isKnownModel: false,
2676
2719
  };
2677
2720
  } else if (modelId.includes('claude-')) {
@@ -2682,13 +2725,17 @@ export function getModelCapabilities(modelId: string): {
2682
2725
  maxOutputTokens: 128000,
2683
2726
  supportsStructuredOutput: true,
2684
2727
  rejectsSamplingParameters: true,
2728
+ rejectsThinkingDisabledAboveHighEffort: true,
2685
2729
  isKnownModel: false,
2686
2730
  };
2687
2731
  } else {
2732
+ // Non-Claude models (e.g. served through Anthropic-compatible APIs)
2733
+ // keep conservative defaults.
2688
2734
  return {
2689
2735
  maxOutputTokens: 4096,
2690
2736
  supportsStructuredOutput: false,
2691
2737
  rejectsSamplingParameters: false,
2738
+ rejectsThinkingDisabledAboveHighEffort: false,
2692
2739
  isKnownModel: false,
2693
2740
  };
2694
2741
  }
@@ -19,6 +19,7 @@ export type AnthropicMessagesModelId =
19
19
  | 'claude-opus-4-6'
20
20
  | 'claude-opus-4-7'
21
21
  | 'claude-opus-4-8'
22
+ | 'claude-opus-5'
22
23
  | 'claude-fable-5'
23
24
  | 'claude-sonnet-5'
24
25
  | (string & {});
@@ -59,6 +60,44 @@ export type AnthropicFilePartProviderOptions = z.infer<
59
60
  typeof anthropicFilePartProviderOptions
60
61
  >;
61
62
 
63
+ /**
64
+ * Anthropic provider options for system messages.
65
+ */
66
+ export const anthropicSystemMessageProviderOptions = z.object({
67
+ /**
68
+ * Mid-conversation tool changes. Adds or removes tools from the
69
+ * conversation's tool set between turns without invalidating the prompt
70
+ * cache.
71
+ *
72
+ * Only supported on system messages that appear mid-conversation (not the
73
+ * initial system prompt). A system message carrying tool changes must come
74
+ * right before an assistant message or at the end of the messages.
75
+ *
76
+ * Tools referenced by a `tool_addition` must be declared in the `tools`
77
+ * option (typically with `deferLoading: true` so they are not loaded until
78
+ * the addition surfaces them). The required
79
+ * `mid-conversation-tool-changes-2026-07-01` beta is added automatically.
80
+ */
81
+ toolChanges: z
82
+ .array(
83
+ z.discriminatedUnion('type', [
84
+ z.object({
85
+ type: z.literal('tool_addition'),
86
+ toolName: z.string(),
87
+ }),
88
+ z.object({
89
+ type: z.literal('tool_removal'),
90
+ toolName: z.string(),
91
+ }),
92
+ ]),
93
+ )
94
+ .optional(),
95
+ });
96
+
97
+ export type AnthropicSystemMessageProviderOptions = z.infer<
98
+ typeof anthropicSystemMessageProviderOptions
99
+ >;
100
+
62
101
  export const anthropicLanguageModelOptions = z.object({
63
102
  /**
64
103
  * Whether to send reasoning to the model.
@@ -227,31 +266,36 @@ export const anthropicLanguageModelOptions = z.object({
227
266
  inferenceGeo: z.enum(['us', 'global']).optional(),
228
267
 
229
268
  /**
230
- * Server-side fallback chain.
269
+ * Server-side fallback configuration.
231
270
  *
232
271
  * When the primary model's safety classifiers block a turn, the API
233
- * automatically retries it on the next model in the chain, server-side. A
234
- * `content-filter` finish reason means the entire chain refused.
272
+ * automatically retries it server-side on a fallback model. A
273
+ * `content-filter` finish reason means the fallback(s) refused as well.
235
274
  *
236
- * Each entry is merged into the request as a direct request to that entry's
237
- * model, so it must be formatted accordingly: `model` is required, and an
238
- * entry may additionally override `max_tokens`, `thinking`, `output_config`,
239
- * and `speed` for that attempt only (`speed` additionally requires the speed
240
- * beta). The value is passed through to the API as-is.
241
- *
242
- * The required `server-side-fallback-2026-06-01` beta is added automatically
243
- * when this option is set.
275
+ * - `'default'` (recommended): the API routes the retry to Anthropic's
276
+ * recommended fallback model based on the refusal category. Requires the
277
+ * `server-side-fallback-2026-07-01` beta, which is added automatically.
278
+ * - Array form: an explicit fallback chain. Each entry is merged into the
279
+ * request as a direct request to that entry's model, so it must be
280
+ * formatted accordingly: `model` is required, and an entry may
281
+ * additionally override `max_tokens`, `thinking`, `output_config`, and
282
+ * `speed` for that attempt only (`speed` additionally requires the speed
283
+ * beta). The value is passed through to the API as-is, and the
284
+ * `server-side-fallback-2026-06-01` beta is added automatically.
244
285
  */
245
286
  fallbacks: z
246
- .array(
247
- z.object({
248
- model: z.string(),
249
- max_tokens: z.number().int().optional(),
250
- thinking: z.record(z.string(), z.unknown()).optional(),
251
- output_config: z.record(z.string(), z.unknown()).optional(),
252
- speed: z.enum(['fast', 'standard']).optional(),
253
- }),
254
- )
287
+ .union([
288
+ z.literal('default'),
289
+ z.array(
290
+ z.object({
291
+ model: z.string(),
292
+ max_tokens: z.number().int().optional(),
293
+ thinking: z.record(z.string(), z.unknown()).optional(),
294
+ output_config: z.record(z.string(), z.unknown()).optional(),
295
+ speed: z.enum(['fast', 'standard']).optional(),
296
+ }),
297
+ ),
298
+ ])
255
299
  .optional(),
256
300
 
257
301
  /**
@@ -20,12 +20,18 @@ import {
20
20
  anthropicReasoningMetadataSchema,
21
21
  type AnthropicAssistantMessage,
22
22
  type AnthropicMessagesPrompt,
23
+ type AnthropicSystemMessage,
24
+ type AnthropicTextContent,
25
+ type AnthropicToolChangeContent,
23
26
  type AnthropicToolResultContent,
24
27
  type AnthropicUserMessage,
25
28
  type AnthropicWebFetchToolResultContent,
26
29
  type Citation,
27
30
  } from './anthropic-messages-api';
28
- import { anthropicFilePartProviderOptions } from './anthropic-messages-options';
31
+ import {
32
+ anthropicFilePartProviderOptions,
33
+ anthropicSystemMessageProviderOptions,
34
+ } from './anthropic-messages-options';
29
35
  import { CacheControlValidator } from './get-cache-control';
30
36
  import { advisor_20260301OutputSchema } from './tool/advisor_20260301';
31
37
  import { codeExecution_20250522OutputSchema } from './tool/code-execution_20250522';
@@ -159,20 +165,66 @@ export async function convertToAnthropicMessagesPrompt({
159
165
 
160
166
  switch (type) {
161
167
  case 'system': {
162
- const content = block.messages.map(({ content, providerOptions }) => ({
163
- type: 'text' as const,
164
- text: content,
165
- cache_control: validator.getCacheControl(providerOptions, {
166
- type: 'system message',
167
- canCache: true,
168
- }),
169
- }));
170
-
171
- if (system == null) {
172
- system = content;
168
+ const content: AnthropicSystemMessage['content'] = [];
169
+ let toolChangeCount = 0;
170
+
171
+ for (const { content: text, providerOptions } of block.messages) {
172
+ const systemMessageOptions = await parseProviderOptions({
173
+ provider: 'anthropic',
174
+ providerOptions,
175
+ schema: anthropicSystemMessageProviderOptions,
176
+ });
177
+ const toolChanges = systemMessageOptions?.toolChanges ?? [];
178
+
179
+ // A system message that only carries tool changes may have empty
180
+ // text; do not emit an empty text block for it.
181
+ if (text !== '' || toolChanges.length === 0) {
182
+ content.push({
183
+ type: 'text' as const,
184
+ text,
185
+ cache_control: validator.getCacheControl(providerOptions, {
186
+ type: 'system message',
187
+ canCache: true,
188
+ }),
189
+ });
190
+ }
191
+
192
+ for (const toolChange of toolChanges) {
193
+ toolChangeCount++;
194
+ content.push({
195
+ type: toolChange.type,
196
+ tool: {
197
+ type: 'tool_reference',
198
+ name: toolNameMapping.toProviderToolName(toolChange.toolName),
199
+ },
200
+ } satisfies AnthropicToolChangeContent);
201
+ }
202
+ }
203
+
204
+ // The first block becomes the top-level system prompt. Later system
205
+ // blocks are sent as inline system messages — always when they carry
206
+ // tool changes (which are only valid mid-conversation), and otherwise
207
+ // only when a top-level system prompt already exists (preserving the
208
+ // existing hoisting behavior for plain text).
209
+ if (i === 0 || (system == null && toolChangeCount === 0)) {
210
+ if (toolChangeCount > 0) {
211
+ warnings.push({
212
+ type: 'other',
213
+ message:
214
+ 'tool changes on the initial system message are not supported by Anthropic. ' +
215
+ 'Configure the initial tool set via the tools option instead. ' +
216
+ 'The tool changes have been ignored.',
217
+ });
218
+ }
219
+ system = content.filter(
220
+ (part): part is AnthropicTextContent => part.type === 'text',
221
+ );
173
222
  } else {
174
223
  messages.push({ role: 'system', content });
175
224
  betas.add('mid-conversation-system-2026-04-07');
225
+ if (toolChangeCount > 0) {
226
+ betas.add('mid-conversation-tool-changes-2026-07-01');
227
+ }
176
228
  }
177
229
 
178
230
  break;
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ export type {
6
6
  AnthropicLanguageModelOptions,
7
7
  /** @deprecated Use `AnthropicLanguageModelOptions` instead. */
8
8
  AnthropicLanguageModelOptions as AnthropicProviderOptions,
9
+ AnthropicSystemMessageProviderOptions,
9
10
  } from './anthropic-messages-options';
10
11
  export type { AnthropicToolOptions } from './anthropic-prepare-tools';
11
12
  export { anthropic, createAnthropic } from './anthropic-provider';