Repository: vercel/ai (2025-07-25T14:51:03Z)

Issue:
Support Anthropic prompt caching for tool definitions
### Feature Description

The AI SDK currently supports Anthropic's prompt caching for system messages and messages (including tool calls and tool results), but not tool definitions: https://github.com/vercel/ai/discussions/3062#discussioncomment-10702467

Anthropic docs: https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching#what-can-be-cached
AI SDK docs: https://sdk.vercel.ai/providers/ai-sdk-providers/anthropic#cache-control

I'd like to be able to implement prompt caching on the tool definitions using the AI SDK. Thank you!


Discussion:
@lgrammel, any ETA on this one? We're hitting the 40K input token limit/minute, and since cache reads don't count against that limit, having this would help quite a lot.
It's on the roadmap, expected in v5.0 or v5.1
This shouldn't be a major blocker to getting good caching, since putting cache control on the last tool is effectively equivalent to putting cache control on a zero-size system block inserted at the start.

The only use-case that _can't_ be served by caching early or late in the system prompt is creating a cache point in the middle of the tool list, which is likely to result in poor cache performance anyways. That would imply you have tool definitions changing request-to-request which will prevent system and message sections from (realistically) ever caching.
@lgrammel was this fixed in the v5.0? I don't see us hitting cache at all.



Patch:
diff --git a/.changeset/wild-beans-help.md b/.changeset/wild-beans-help.md
new file mode 100644
index 000000000000..11ce4611e0c3
--- /dev/null
+++ b/.changeset/wild-beans-help.md
@@ -0,0 +1,6 @@
+---
+'@ai-sdk/anthropic': patch
+'ai': patch
+---
+
+feat (provider/anthropic): cache control for tools
diff --git a/content/providers/01-ai-sdk-providers/05-anthropic.mdx b/content/providers/01-ai-sdk-providers/05-anthropic.mdx
index f1625a250b94..7fdc9f9190c4 100644
--- a/content/providers/01-ai-sdk-providers/05-anthropic.mdx
+++ b/content/providers/01-ai-sdk-providers/05-anthropic.mdx
@@ -139,13 +139,6 @@ on how to integrate reasoning into your chatbot.
 
 ### Cache Control
 
-<Note>
-  Anthropic cache control was originally a beta feature and required passing an
-  opt-in `cacheControl` setting when creating the model instance. It is now
-  Generally Available and enabled by default. The `cacheControl` setting is no
-  longer needed and will be removed in a future release.
-</Note>
-
 In the messages and message parts, you can use the `providerOptions` property to set cache control breakpoints.
 You need to set the `anthropic` property in the `providerOptions` object to `{ cacheControl: { type: 'ephemeral' } }` to set a cache control breakpoint.
 
@@ -211,6 +204,30 @@ const result = await generateText({
 });
 ```
 
+Cache control for tools:
+
+```ts
+const result = await generateText({
+  model: anthropic('claude-3-5-haiku-latest'),
+  tools: {
+    cityAttractions: tool({
+      inputSchema: z.object({ city: z.string() }),
+      providerOptions: {
+        anthropic: {
+          cacheControl: { type: 'ephemeral' },
+        },
+      },
+    }),
+  },
+  messages: [
+    {
+      role: 'user',
+      content: 'User prompt',
+    },
+  ],
+});
+```
+
 The minimum cacheable prompt length is:
 
 - 1024 tokens for Claude 3.7 Sonnet, Claude 3.5 Sonnet and Claude 3 Opus
diff --git a/examples/ai-core/src/generate-text/anthropic-tool-call-cache.ts b/examples/ai-core/src/generate-text/anthropic-tool-call-cache.ts
new file mode 100644
index 000000000000..ea7cb9884401
--- /dev/null
+++ b/examples/ai-core/src/generate-text/anthropic-tool-call-cache.ts
@@ -0,0 +1,25 @@
+import { anthropic } from '@ai-sdk/anthropic';
+import { generateText, tool } from 'ai';
+import 'dotenv/config';
+import { z } from 'zod/v4';
+
+async function main() {
+  const result = await generateText({
+    model: anthropic('claude-3-5-haiku-latest'),
+    tools: {
+      cityAttractions: tool({
+        inputSchema: z.object({ city: z.string() }),
+        providerOptions: {
+          anthropic: {
+            cacheControl: { type: 'ephemeral' },
+          },
+        },
+      }),
+    },
+    prompt: 'What attractions should I visit in San Francisco?',
+  });
+
+  console.log(JSON.stringify(result.request.body, null, 2));
+}
+
+main().catch(console.error);
diff --git a/packages/ai/src/prompt/prepare-tools-and-tool-choice.ts b/packages/ai/src/prompt/prepare-tools-and-tool-choice.ts
index 8138d7537ca5..1e0494ba3d65 100644
--- a/packages/ai/src/prompt/prepare-tools-and-tool-choice.ts
+++ b/packages/ai/src/prompt/prepare-tools-and-tool-choice.ts
@@ -48,6 +48,7 @@ export function prepareToolsAndToolChoice<TOOLS extends ToolSet>({
             name,
             description: tool.description,
             inputSchema: asSchema(tool.inputSchema).jsonSchema,
+            providerOptions: tool.providerOptions,
           };
         case 'provider-defined':
           return {
diff --git a/packages/anthropic/src/anthropic-api-types.ts b/packages/anthropic/src/anthropic-api-types.ts
index 434d80588020..d872bc17c096 100644
--- a/packages/anthropic/src/anthropic-api-types.ts
+++ b/packages/anthropic/src/anthropic-api-types.ts
@@ -7,7 +7,9 @@ export type AnthropicMessagesPrompt = {
 
 export type AnthropicMessage = AnthropicUserMessage | AnthropicAssistantMessage;
 
-export type AnthropicCacheControl = { type: 'ephemeral' };
+export type AnthropicCacheControl = {
+  type: 'ephemeral';
+};
 
 export interface AnthropicUserMessage {
   role: 'user';
@@ -123,6 +125,7 @@ export type AnthropicTool =
       name: string;
       description: string | undefined;
       input_schema: JSONSchema7;
+      cache_control: AnthropicCacheControl | undefined;
     }
   | {
       name: string;
diff --git a/packages/anthropic/src/anthropic-prepare-tools.ts b/packages/anthropic/src/anthropic-prepare-tools.ts
index f89936cf2fdc..9248d3534722 100644
--- a/packages/anthropic/src/anthropic-prepare-tools.ts
+++ b/packages/anthropic/src/anthropic-prepare-tools.ts
@@ -4,6 +4,7 @@ import {
   UnsupportedFunctionalityError,
 } from '@ai-sdk/provider';
 import { AnthropicTool, AnthropicToolChoice } from './anthropic-api-types';
+import { getCacheControl } from './get-cache-control';
 import { webSearch_20250305ArgsSchema } from './tool/web-search_20250305';
 
 function isWebSearchTool(
@@ -52,10 +53,13 @@ export function prepareTools({
 
     switch (tool.type) {
       case 'function':
+        const cacheControl = getCacheControl(tool.providerOptions);
+
         anthropicTools.push({
           name: tool.name,
           description: tool.description,
           input_schema: tool.inputSchema,
+          cache_control: cacheControl,
         });
         break;
       case 'provider-defined':
diff --git a/packages/anthropic/src/convert-to-anthropic-messages-prompt.ts b/packages/anthropic/src/convert-to-anthropic-messages-prompt.ts
index 435334532579..46c2c6dd7908 100644
--- a/packages/anthropic/src/convert-to-anthropic-messages-prompt.ts
+++ b/packages/anthropic/src/convert-to-anthropic-messages-prompt.ts
@@ -6,16 +6,16 @@ import {
   SharedV2ProviderMetadata,
   UnsupportedFunctionalityError,
 } from '@ai-sdk/provider';
+import { convertToBase64, parseProviderOptions } from '@ai-sdk/provider-utils';
 import {
   AnthropicAssistantMessage,
-  AnthropicCacheControl,
   AnthropicMessagesPrompt,
   AnthropicToolResultContent,
   AnthropicUserMessage,
 } from './anthropic-api-types';
-import { convertToBase64, parseProviderOptions } from '@ai-sdk/provider-utils';
 import { anthropicReasoningMetadataSchema } from './anthropic-messages-language-model';
 import { anthropicFilePartProviderOptions } from './anthropic-messages-options';
+import { getCacheControl } from './get-cache-control';
 import { webSearch_20250305OutputSchema } from './tool/web-search_20250305';
 
 function convertToString(data: LanguageModelV2DataContent): string {
@@ -56,20 +56,6 @@ export async function convertToAnthropicMessagesPrompt({
   let system: AnthropicMessagesPrompt['system'] = undefined;
   const messages: AnthropicMessagesPrompt['messages'] = [];
 
-  function getCacheControl(
-    providerMetadata: SharedV2ProviderMetadata | undefined,
-  ): AnthropicCacheControl | undefined {
-    const anthropic = providerMetadata?.anthropic;
-
-    // allow both cacheControl and cache_control:
-    const cacheControlValue =
-      anthropic?.cacheControl ?? anthropic?.cache_control;
-
-    // Pass through value assuming it is of the correct type.
-    // The Anthropic API will validate the value.
-    return cacheControlValue as AnthropicCacheControl | undefined;
-  }
-
   async function shouldEnableCitations(
     providerMetadata: SharedV2ProviderMetadata | undefined,
   ): Promise<boolean> {
diff --git a/packages/anthropic/src/get-cache-control.ts b/packages/anthropic/src/get-cache-control.ts
new file mode 100644
index 000000000000..36fc374df284
--- /dev/null
+++ b/packages/anthropic/src/get-cache-control.ts
@@ -0,0 +1,15 @@
+import { SharedV2ProviderMetadata } from '@ai-sdk/provider';
+import { AnthropicCacheControl } from './anthropic-api-types';
+
+export function getCacheControl(
+  providerMetadata: SharedV2ProviderMetadata | undefined,
+): AnthropicCacheControl | undefined {
+  const anthropic = providerMetadata?.anthropic;
+
+  // allow both cacheControl and cache_control:
+  const cacheControlValue = anthropic?.cacheControl ?? anthropic?.cache_control;
+
+  // Pass through value assuming it is of the correct type.
+  // The Anthropic API will validate the value.
+  return cacheControlValue as AnthropicCacheControl | undefined;
+}


Test patch:
diff --git a/packages/ai/src/generate-text/generate-text.test.ts b/packages/ai/src/generate-text/generate-text.test.ts
index c4805ef6865a..d090949b692d 100644
--- a/packages/ai/src/generate-text/generate-text.test.ts
+++ b/packages/ai/src/generate-text/generate-text.test.ts
@@ -320,6 +320,7 @@ describe('generateText', () => {
                   required: ['value'],
                   type: 'object',
                 },
+                providerOptions: undefined,
               },
               {
                 type: 'function',
@@ -332,6 +333,7 @@ describe('generateText', () => {
                   required: ['somethingElse'],
                   type: 'object',
                 },
+                providerOptions: undefined,
               },
             ]);
 
@@ -411,6 +413,7 @@ describe('generateText', () => {
                   required: ['value'],
                   type: 'object',
                 },
+                providerOptions: undefined,
               },
             ]);
 
@@ -627,6 +630,7 @@ describe('generateText', () => {
                         required: ['value'],
                         type: 'object',
                       },
+                      providerOptions: undefined,
                     },
                   ]);
 
@@ -1262,6 +1266,7 @@ describe('generateText', () => {
                     "type": "object",
                   },
                   "name": "tool1",
+                  "providerOptions": undefined,
                   "type": "function",
                 },
               ],
@@ -1769,6 +1774,7 @@ describe('generateText', () => {
             "type": "object",
           },
           "name": "tool1",
+          "providerOptions": undefined,
           "type": "function",
         },
       ]
@@ -2124,6 +2130,7 @@ describe('generateText', () => {
                   required: ['value'],
                   type: 'object',
                 },
+                providerOptions: undefined,
               },
               {
                 type: 'function',
@@ -2135,6 +2142,7 @@ describe('generateText', () => {
                   required: ['somethingElse'],
                   type: 'object',
                 },
+                providerOptions: undefined,
               },
             ]);
 
diff --git a/packages/ai/src/generate-text/stream-text.test.ts b/packages/ai/src/generate-text/stream-text.test.ts
index f59a41fc5fd0..7a17b5eb3e2f 100644
--- a/packages/ai/src/generate-text/stream-text.test.ts
+++ b/packages/ai/src/generate-text/stream-text.test.ts
@@ -1007,6 +1007,7 @@ describe('streamText', () => {
                   required: ['value'],
                   type: 'object',
                 },
+                providerOptions: undefined,
               },
             ]);
 
@@ -5245,6 +5246,7 @@ describe('streamText', () => {
                     "type": "object",
                   },
                   "name": "tool1",
+                  "providerOptions": undefined,
                   "type": "function",
                 },
               ],
@@ -5319,6 +5321,7 @@ describe('streamText', () => {
                     "type": "object",
                   },
                   "name": "tool1",
+                  "providerOptions": undefined,
                   "type": "function",
                 },
               ],
@@ -6373,6 +6376,7 @@ describe('streamText', () => {
                     "type": "object",
                   },
                   "name": "tool1",
+                  "providerOptions": undefined,
                   "type": "function",
                 },
               ],
@@ -9071,6 +9075,7 @@ describe('streamText', () => {
                   required: ['value'],
                   type: 'object',
                 },
+                providerOptions: undefined,
               },
             ]);
             expect(toolChoice).toStrictEqual({ type: 'required' });
@@ -11244,6 +11249,7 @@ describe('streamText', () => {
               "type": "object",
             },
             "name": "tool1",
+            "providerOptions": undefined,
             "type": "function",
           },
         ]
diff --git a/packages/ai/src/prompt/prepare-tools-and-tool-choice.test.ts b/packages/ai/src/prompt/prepare-tools-and-tool-choice.test.ts
index e506f70a0b2f..43f4d8e432f4 100644
--- a/packages/ai/src/prompt/prepare-tools-and-tool-choice.test.ts
+++ b/packages/ai/src/prompt/prepare-tools-and-tool-choice.test.ts
@@ -1,10 +1,8 @@
 import { z } from 'zod/v4';
-import { ToolSet } from '../generate-text/tool-set';
 import { prepareToolsAndToolChoice } from './prepare-tools-and-tool-choice';
 import { Tool, tool } from '@ai-sdk/provider-utils';
-import { LanguageModelV2FunctionTool } from '@ai-sdk/provider';
 
-const mockTools: ToolSet = {
+const mockTools = {
   tool1: tool({
     description: 'Tool 1 description',
     inputSchema: z.object({}),
@@ -23,93 +21,352 @@ const mockProviderDefinedTool: Tool = {
   inputSchema: z.object({}),
 };
 
-const mockToolsWithProviderDefined: ToolSet = {
+const mockToolsWithProviderDefined = {
   ...mockTools,
   providerTool: mockProviderDefinedTool,
 };
 
-it('should return undefined for both tools and toolChoice when tools is not provided', () => {
-  const result = prepareToolsAndToolChoice({
-    tools: undefined,
-    toolChoice: undefined,
-    activeTools: undefined,
-  });
-  expect(result).toEqual({ tools: undefined, toolChoice: undefined });
-});
+describe('prepareToolsAndToolChoice', () => {
+  it('should return undefined for both tools and toolChoice when tools is not provided', () => {
+    const result = prepareToolsAndToolChoice({
+      tools: undefined,
+      toolChoice: undefined,
+      activeTools: undefined,
+    });
 
-it('should return all tools when activeTools is not provided', () => {
-  const result = prepareToolsAndToolChoice({
-    tools: mockTools,
-    toolChoice: undefined,
-    activeTools: undefined,
+    expect(result).toMatchInlineSnapshot(`
+      {
+        "toolChoice": undefined,
+        "tools": undefined,
+      }
+    `);
   });
-  expect(result.tools).toHaveLength(2);
-  expect((result.tools?.[0] as LanguageModelV2FunctionTool).name).toBe('tool1');
-  expect((result.tools?.[1] as LanguageModelV2FunctionTool).name).toBe('tool2');
-  expect(result.toolChoice).toEqual({ type: 'auto' });
-});
 
-it('should filter tools based on activeTools', () => {
-  const result = prepareToolsAndToolChoice({
-    tools: mockTools,
-    toolChoice: undefined,
-    activeTools: ['tool1'],
+  it('should return all tools when activeTools is not provided', () => {
+    const result = prepareToolsAndToolChoice({
+      tools: mockTools,
+      toolChoice: undefined,
+      activeTools: undefined,
+    });
+
+    expect(result).toMatchInlineSnapshot(`
+      {
+        "toolChoice": {
+          "type": "auto",
+        },
+        "tools": [
+          {
+            "description": "Tool 1 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {},
+              "type": "object",
+            },
+            "name": "tool1",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+          {
+            "description": "Tool 2 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {
+                "city": {
+                  "type": "string",
+                },
+              },
+              "required": [
+                "city",
+              ],
+              "type": "object",
+            },
+            "name": "tool2",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+        ],
+      }
+    `);
   });
-  expect(result.tools).toHaveLength(1);
-  expect((result.tools?.[0] as LanguageModelV2FunctionTool).name).toBe('tool1');
-  expect(result.toolChoice).toEqual({ type: 'auto' });
-});
 
-it('should handle string toolChoice', () => {
-  const result = prepareToolsAndToolChoice({
-    tools: mockTools,
-    toolChoice: 'none',
-    activeTools: undefined,
+  it('should filter tools based on activeTools', () => {
+    const result = prepareToolsAndToolChoice({
+      tools: mockTools,
+      toolChoice: undefined,
+      activeTools: ['tool1'],
+    });
+
+    expect(result).toMatchInlineSnapshot(`
+      {
+        "toolChoice": {
+          "type": "auto",
+        },
+        "tools": [
+          {
+            "description": "Tool 1 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {},
+              "type": "object",
+            },
+            "name": "tool1",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+        ],
+      }
+    `);
   });
-  expect(result.tools).toHaveLength(2);
-  expect(result.toolChoice).toEqual({ type: 'none' });
-});
 
-it('should handle object toolChoice', () => {
-  const result = prepareToolsAndToolChoice({
-    tools: mockTools,
-    toolChoice: { type: 'tool', toolName: 'tool2' },
-    activeTools: undefined,
+  it('should handle string toolChoice', () => {
+    const result = prepareToolsAndToolChoice({
+      tools: mockTools,
+      toolChoice: 'none',
+      activeTools: undefined,
+    });
+
+    expect(result).toMatchInlineSnapshot(`
+      {
+        "toolChoice": {
+          "type": "none",
+        },
+        "tools": [
+          {
+            "description": "Tool 1 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {},
+              "type": "object",
+            },
+            "name": "tool1",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+          {
+            "description": "Tool 2 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {
+                "city": {
+                  "type": "string",
+                },
+              },
+              "required": [
+                "city",
+              ],
+              "type": "object",
+            },
+            "name": "tool2",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+        ],
+      }
+    `);
   });
-  expect(result.tools).toHaveLength(2);
-  expect(result.toolChoice).toEqual({ type: 'tool', toolName: 'tool2' });
-});
 
-it('should correctly map tool properties', () => {
-  const result = prepareToolsAndToolChoice({
-    tools: mockTools,
-    toolChoice: undefined,
-    activeTools: undefined,
+  it('should handle object toolChoice', () => {
+    const result = prepareToolsAndToolChoice({
+      tools: mockTools,
+      toolChoice: { type: 'tool', toolName: 'tool2' },
+      activeTools: undefined,
+    });
+
+    expect(result).toMatchInlineSnapshot(`
+      {
+        "toolChoice": {
+          "toolName": "tool2",
+          "type": "tool",
+        },
+        "tools": [
+          {
+            "description": "Tool 1 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {},
+              "type": "object",
+            },
+            "name": "tool1",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+          {
+            "description": "Tool 2 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {
+                "city": {
+                  "type": "string",
+                },
+              },
+              "required": [
+                "city",
+              ],
+              "type": "object",
+            },
+            "name": "tool2",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+        ],
+      }
+    `);
   });
-  expect(result.tools?.[0]).toEqual({
-    type: 'function',
-    name: 'tool1',
-    description: 'Tool 1 description',
-    inputSchema: {
-      $schema: 'http://json-schema.org/draft-07/schema#',
-      additionalProperties: false,
-      type: 'object',
-      properties: {},
-    },
+
+  it('should correctly map tool properties', () => {
+    const result = prepareToolsAndToolChoice({
+      tools: mockTools,
+      toolChoice: undefined,
+      activeTools: undefined,
+    });
+
+    expect(result).toMatchInlineSnapshot(`
+      {
+        "toolChoice": {
+          "type": "auto",
+        },
+        "tools": [
+          {
+            "description": "Tool 1 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {},
+              "type": "object",
+            },
+            "name": "tool1",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+          {
+            "description": "Tool 2 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {
+                "city": {
+                  "type": "string",
+                },
+              },
+              "required": [
+                "city",
+              ],
+              "type": "object",
+            },
+            "name": "tool2",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+        ],
+      }
+    `);
   });
-});
 
-it('should handle provider-defined tool type', () => {
-  const result = prepareToolsAndToolChoice({
-    tools: mockToolsWithProviderDefined,
-    toolChoice: undefined,
-    activeTools: undefined,
+  it('should handle provider-defined tool type', () => {
+    const result = prepareToolsAndToolChoice({
+      tools: mockToolsWithProviderDefined,
+      toolChoice: undefined,
+      activeTools: undefined,
+    });
+
+    expect(result).toMatchInlineSnapshot(`
+      {
+        "toolChoice": {
+          "type": "auto",
+        },
+        "tools": [
+          {
+            "description": "Tool 1 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {},
+              "type": "object",
+            },
+            "name": "tool1",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+          {
+            "description": "Tool 2 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {
+                "city": {
+                  "type": "string",
+                },
+              },
+              "required": [
+                "city",
+              ],
+              "type": "object",
+            },
+            "name": "tool2",
+            "providerOptions": undefined,
+            "type": "function",
+          },
+          {
+            "args": {
+              "key": "value",
+            },
+            "id": "provider.tool-id",
+            "name": "providerTool",
+            "type": "provider-defined",
+          },
+        ],
+      }
+    `);
   });
-  expect(result.tools).toHaveLength(3);
-  expect(result.tools?.[2]).toEqual({
-    type: 'provider-defined',
-    name: 'providerTool',
-    id: 'provider.tool-id',
-    args: { key: 'value' },
+
+  it('should pass through provider options', () => {
+    const result = prepareToolsAndToolChoice({
+      tools: {
+        tool1: tool({
+          description: 'Tool 1 description',
+          inputSchema: z.object({}),
+          providerOptions: {
+            aProvider: {
+              aSetting: 'aValue',
+            },
+          },
+        }),
+      },
+      toolChoice: undefined,
+      activeTools: undefined,
+    });
+
+    expect(result).toMatchInlineSnapshot(`
+      {
+        "toolChoice": {
+          "type": "auto",
+        },
+        "tools": [
+          {
+            "description": "Tool 1 description",
+            "inputSchema": {
+              "$schema": "http://json-schema.org/draft-07/schema#",
+              "additionalProperties": false,
+              "properties": {},
+              "type": "object",
+            },
+            "name": "tool1",
+            "providerOptions": {
+              "aProvider": {
+                "aSetting": "aValue",
+              },
+            },
+            "type": "function",
+          },
+        ],
+      }
+    `);
   });
 });
diff --git a/packages/anthropic/src/anthropic-prepare-tools.test.ts b/packages/anthropic/src/anthropic-prepare-tools.test.ts
index 8faf40af9fa3..1f2ece9c8b23 100644
--- a/packages/anthropic/src/anthropic-prepare-tools.test.ts
+++ b/packages/anthropic/src/anthropic-prepare-tools.test.ts
@@ -1,105 +1,106 @@
 import { prepareTools } from './anthropic-prepare-tools';
 
-it('should return undefined tools and tool_choice when tools are null', () => {
-  const result = prepareTools({ tools: undefined });
-  expect(result).toEqual({
-    tools: undefined,
-    tool_choice: undefined,
-    toolWarnings: [],
-    betas: new Set(),
+describe('prepareTools', () => {
+  it('should return undefined tools and tool_choice when tools are null', () => {
+    const result = prepareTools({ tools: undefined });
+    expect(result).toEqual({
+      tools: undefined,
+      tool_choice: undefined,
+      toolWarnings: [],
+      betas: new Set(),
+    });
   });
-});
 
-it('should return undefined tools and tool_choice when tools are empty', () => {
-  const result = prepareTools({ tools: [] });
-  expect(result).toEqual({
-    tools: undefined,
-    tool_choice: undefined,
-    toolWarnings: [],
-    betas: new Set(),
+  it('should return undefined tools and tool_choice when tools are empty', () => {
+    const result = prepareTools({ tools: [] });
+    expect(result).toEqual({
+      tools: undefined,
+      tool_choice: undefined,
+      toolWarnings: [],
+      betas: new Set(),
+    });
   });
-});
 
-it('should correctly prepare function tools', () => {
-  const result = prepareTools({
-    tools: [
+  it('should correctly prepare function tools', () => {
+    const result = prepareTools({
+      tools: [
+        {
+          type: 'function',
+          name: 'testFunction',
+          description: 'A test function',
+          inputSchema: { type: 'object', properties: {} },
+        },
+      ],
+    });
+    expect(result.tools).toEqual([
       {
-        type: 'function',
         name: 'testFunction',
         description: 'A test function',
-        inputSchema: { type: 'object', properties: {} },
+        input_schema: { type: 'object', properties: {} },
       },
-    ],
+    ]);
+    expect(result.toolChoice).toBeUndefined();
+    expect(result.toolWarnings).toEqual([]);
   });
-  expect(result.tools).toEqual([
-    {
-      name: 'testFunction',
-      description: 'A test function',
-      input_schema: { type: 'object', properties: {} },
-    },
-  ]);
-  expect(result.toolChoice).toBeUndefined();
-  expect(result.toolWarnings).toEqual([]);
-});
 
-it('should correctly prepare provider-defined tools', () => {
-  const result = prepareTools({
-    tools: [
+  it('should correctly prepare provider-defined tools', () => {
+    const result = prepareTools({
+      tools: [
+        {
+          type: 'provider-defined',
+          id: 'anthropic.computer_20241022',
+          name: 'computer',
+          args: { displayWidthPx: 800, displayHeightPx: 600, displayNumber: 1 },
+        },
+        {
+          type: 'provider-defined',
+          id: 'anthropic.text_editor_20241022',
+          name: 'text_editor',
+          args: {},
+        },
+        {
+          type: 'provider-defined',
+          id: 'anthropic.bash_20241022',
+          name: 'bash',
+          args: {},
+        },
+      ],
+    });
+    expect(result.tools).toEqual([
       {
-        type: 'provider-defined',
-        id: 'anthropic.computer_20241022',
         name: 'computer',
-        args: { displayWidthPx: 800, displayHeightPx: 600, displayNumber: 1 },
+        type: 'computer_20241022',
+        display_width_px: 800,
+        display_height_px: 600,
+        display_number: 1,
       },
       {
-        type: 'provider-defined',
-        id: 'anthropic.text_editor_20241022',
-        name: 'text_editor',
-        args: {},
+        name: 'str_replace_editor',
+        type: 'text_editor_20241022',
       },
       {
-        type: 'provider-defined',
-        id: 'anthropic.bash_20241022',
         name: 'bash',
-        args: {},
+        type: 'bash_20241022',
       },
-    ],
+    ]);
+    expect(result.toolChoice).toBeUndefined();
+    expect(result.toolWarnings).toEqual([]);
   });
-  expect(result.tools).toEqual([
-    {
-      name: 'computer',
-      type: 'computer_20241022',
-      display_width_px: 800,
-      display_height_px: 600,
-      display_number: 1,
-    },
-    {
-      name: 'str_replace_editor',
-      type: 'text_editor_20241022',
-    },
-    {
-      name: 'bash',
-      type: 'bash_20241022',
-    },
-  ]);
-  expect(result.toolChoice).toBeUndefined();
-  expect(result.toolWarnings).toEqual([]);
-});
 
-it('should add warnings for unsupported tools', () => {
-  const result = prepareTools({
-    tools: [
-      {
-        type: 'provider-defined',
-        id: 'unsupported.tool',
-        name: 'unsupported_tool',
-        args: {},
-      },
-    ],
-  });
-  expect(result.tools).toEqual([]);
-  expect(result.toolChoice).toBeUndefined();
-  expect(result.toolWarnings).toMatchInlineSnapshot(`
+  it('should add warnings for unsupported tools', () => {
+    const result = prepareTools({
+      tools: [
+        {
+          type: 'provider-defined',
+          id: 'unsupported.tool',
+          name: 'unsupported_tool',
+          args: {},
+        },
+      ],
+    });
+    expect(result.tools).toEqual([]);
+    expect(result.toolChoice).toBeUndefined();
+    expect(result.toolWarnings).toMatchInlineSnapshot(`
     [
       {
         "tool": {
@@ -112,65 +113,97 @@ it('should add warnings for unsupported tools', () => {
       },
     ]
   `);
-});
+  });
 
-it('should handle tool choice "auto"', () => {
-  const result = prepareTools({
-    tools: [
-      {
-        type: 'function',
-        name: 'testFunction',
-        description: 'Test',
-        inputSchema: {},
-      },
-    ],
-    toolChoice: { type: 'auto' },
+  it('should handle tool choice "auto"', () => {
+    const result = prepareTools({
+      tools: [
+        {
+          type: 'function',
+          name: 'testFunction',
+          description: 'Test',
+          inputSchema: {},
+        },
+      ],
+      toolChoice: { type: 'auto' },
+    });
+    expect(result.toolChoice).toEqual({ type: 'auto' });
   });
-  expect(result.toolChoice).toEqual({ type: 'auto' });
-});
 
-it('should handle tool choice "required"', () => {
-  const result = prepareTools({
-    tools: [
-      {
-        type: 'function',
-        name: 'testFunction',
-        description: 'Test',
-        inputSchema: {},
-      },
-    ],
-    toolChoice: { type: 'required' },
+  it('should handle tool choice "required"', () => {
+    const result = prepareTools({
+      tools: [
+        {
+          type: 'function',
+          name: 'testFunction',
+          description: 'Test',
+          inputSchema: {},
+        },
+      ],
+      toolChoice: { type: 'required' },
+    });
+    expect(result.toolChoice).toEqual({ type: 'any' });
   });
-  expect(result.toolChoice).toEqual({ type: 'any' });
-});
 
-it('should handle tool choice "none"', () => {
-  const result = prepareTools({
-    tools: [
-      {
-        type: 'function',
-        name: 'testFunction',
-        description: 'Test',
-        inputSchema: {},
-      },
-    ],
-    toolChoice: { type: 'none' },
+  it('should handle tool choice "none"', () => {
+    const result = prepareTools({
+      tools: [
+        {
+          type: 'function',
+          name: 'testFunction',
+          description: 'Test',
+          inputSchema: {},
+        },
+      ],
+      toolChoice: { type: 'none' },
+    });
+    expect(result.tools).toBeUndefined();
+    expect(result.toolChoice).toBeUndefined();
   });
-  expect(result.tools).toBeUndefined();
-  expect(result.toolChoice).toBeUndefined();
-});
 
-it('should handle tool choice "tool"', () => {
-  const result = prepareTools({
-    tools: [
-      {
-        type: 'function',
-        name: 'testFunction',
-        description: 'Test',
-        inputSchema: {},
-      },
-    ],
-    toolChoice: { type: 'tool', toolName: 'testFunction' },
+  it('should handle tool choice "tool"', () => {
+    const result = prepareTools({
+      tools: [
+        {
+          type: 'function',
+          name: 'testFunction',
+          description: 'Test',
+          inputSchema: {},
+        },
+      ],
+      toolChoice: { type: 'tool', toolName: 'testFunction' },
+    });
+    expect(result.toolChoice).toEqual({ type: 'tool', name: 'testFunction' });
+  });
+
+  it('should set cache control', () => {
+    const result = prepareTools({
+      tools: [
+        {
+          type: 'function',
+          name: 'testFunction',
+          description: 'Test',
+          inputSchema: {},
+          providerOptions: {
+            anthropic: {
+              cacheControl: { type: 'ephemeral' },
+            },
+          },
+        },
+      ],
+    });
+
+    expect(result.tools).toMatchInlineSnapshot(`
+      [
+        {
+          "cache_control": {
+            "type": "ephemeral",
+          },
+          "description": "Test",
+          "input_schema": {},
+          "name": "testFunction",
+        },
+      ]
+    `);
   });
-  expect(result.toolChoice).toEqual({ type: 'tool', name: 'testFunction' });
 });