diff --git a/.changeset/shiny-maps-thank.md b/.changeset/shiny-maps-thank.md
new file mode 100644
index 0000000000000000000000000000000000000000..c80e1b67ba9c6b73b4a545800e0b9a892d5cf505
--- /dev/null
+++ b/.changeset/shiny-maps-thank.md
@@ -0,0 +1,6 @@
+---
+"@llamaindex/anthropic": patch
+"@llamaindex/llamaindex-test": patch
+---
+
+fix: missing condition to stringify tool input
diff --git a/packages/llamaindex/tests/llm/index.test.ts b/packages/llamaindex/tests/llm/index.test.ts
index 1509df3a190a33f7d70438b3948a4b33a59e1204..ac1d0fc44a1338880814a94e9a26335034a7d2ce 100644
--- a/packages/llamaindex/tests/llm/index.test.ts
+++ b/packages/llamaindex/tests/llm/index.test.ts
@@ -1,6 +1,5 @@
-import type { MessageParam } from "@anthropic-ai/sdk/resources/messages";
 import { setEnvs } from "@llamaindex/env";
-import { Anthropic, OpenAI, type ChatMessage } from "llamaindex";
+import { OpenAI, type ChatMessage } from "llamaindex";
 import { beforeAll, describe, expect, test } from "vitest";
 
 beforeAll(() => {
@@ -25,32 +24,6 @@ describe("Message Formatting", () => {
       expect(OpenAI.toOpenAIMessage(inputMessages)).toEqual(expectedOutput);
     });
 
-    test("Anthropic formats basic messages correctly", () => {
-      const anthropic = new Anthropic();
-      const inputMessages: ChatMessage[] = [
-        {
-          content: "You are a helpful assistant.",
-          role: "assistant",
-        },
-        {
-          content: "Hello?",
-          role: "user",
-        },
-      ];
-      const expectedOutput: MessageParam[] = [
-        {
-          content: "You are a helpful assistant.",
-          role: "assistant",
-        },
-        {
-          content: "Hello?",
-          role: "user",
-        },
-      ];
-
-      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
-    });
-
     test("OpenAI handles system messages correctly", () => {
       const inputMessages: ChatMessage[] = [
         { content: "You are a coding assistant", role: "system" },
@@ -62,133 +35,6 @@ describe("Message Formatting", () => {
       ];
       expect(OpenAI.toOpenAIMessage(inputMessages)).toEqual(expectedOutput);
     });
-
-    test("Anthropic handles multi-turn conversation correctly", () => {
-      const anthropic = new Anthropic();
-      const inputMessages: ChatMessage[] = [
-        { content: "Hi", role: "user" },
-        { content: "Hello! How can I help?", role: "assistant" },
-        { content: "What's the weather?", role: "user" },
-      ];
-      const expectedOutput: MessageParam[] = [
-        { content: "Hi", role: "user" },
-        { content: "Hello! How can I help?", role: "assistant" },
-        { content: "What's the weather?", role: "user" },
-      ];
-      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
-    });
-  });
-
-  describe("Advanced Message Formatting", () => {
-    test("Anthropic filters out system messages", () => {
-      const anthropic = new Anthropic();
-      const inputMessages: ChatMessage[] = [
-        {
-          content: "You are a helpful assistant.",
-          role: "assistant",
-        },
-        {
-          content: "Hello?",
-          role: "user",
-        },
-        {
-          content: "I am a system message.",
-          role: "system",
-        },
-        {
-          content: "What is your name?",
-          role: "user",
-        },
-      ];
-      const expectedOutput: MessageParam[] = [
-        {
-          content: "You are a helpful assistant.",
-          role: "assistant",
-        },
-        {
-          content: "Hello?\nWhat is your name?",
-          role: "user",
-        },
-      ];
-
-      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
-    });
-
-    test("Anthropic merges consecutive messages from the same role", () => {
-      const anthropic = new Anthropic();
-      const inputMessages: ChatMessage[] = [
-        {
-          content: "Hello?",
-          role: "user",
-        },
-        {
-          content: "How are you?",
-          role: "user",
-        },
-        {
-          content: "I am fine, thank you!",
-          role: "assistant",
-        },
-        {
-          content: "And you?",
-          role: "assistant",
-        },
-      ];
-      const expectedOutput: MessageParam[] = [
-        {
-          content: "Hello?\nHow are you?",
-          role: "user",
-        },
-        {
-          content: "I am fine, thank you!\nAnd you?",
-          role: "assistant",
-        },
-      ];
-
-      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
-    });
-
-    test("Anthropic handles image content", () => {
-      const anthropic = new Anthropic();
-      const inputMessages: ChatMessage[] = [
-        {
-          content: [
-            {
-              text: "What do you see in the image?",
-              type: "text",
-            },
-            {
-              type: "image_url",
-              image_url: {
-                url: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAQDAwQDAwQEAwQFBAQFBgoHBgYGBg0JCggKDw0QEA8NDw4RExgUERIXEg4PFRwVFxkZGxsbEBQdHx0aHxgaGxr/2wBDAQQFBQYFBgwHBwwaEQ8RGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhr/wAARCAAgACADASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAACAQHCQb/xAAvEAABAgUCBAUDBQEAAAAAAAACAQMEBQYHERIhAAgTYSIxMkJxI2KCFBVBUVKh/8QAGAEAAwEBAAAAAAAAAAAAAAAAAwQFAQL/xAAnEQABBAECAwkAAAAAAAAAAAACAQMEEQAFMiExYRITFCJBcXKBof/aAAwDAQACEQMRAD8Aufmb5mnbWREFRdvIMZ3cWcaBh2NHUGEFwtIKQp63CX0h+S7YQgRzGSq6kgqGAS8NQRc6fmkIMWwSxJEyP+m0bwggQr5iIom6KnnxXty61jK+uJUVUxzxm/M5g5EASr6G9WGwTsIIIp2FOHJfi0kyvzS9Cv0zGwEF+2whOAUY4a6mnm2lREURLPoTggNG5tS6xpmOT4GQptwNUZc6sbexzcZRVSTKTOgudMPEL0j7E2uQNOxIqcaYcqXNaxe2HKnauBiAraDZ6n0k0tTBpPNwE9pptqDP3DtlBC1Q8qNw5K4AwLEunYkWMwcYg6fnqoH/ADPHA2/qeZWquhJJ3pODmEhmg/qGl2XAloebL5HWK/K8dOMOM7xVPfJrMhmQiq0SFXOlyPc+jIq3lwakpeYNq27K491kfvbzls07ECiSdlThhWKvj1LLx0VVLWGqSBuFJ1jc3WBEUb8K4TUieHz3xni7ea3lSZvZDhUVImxAVtBso39VdLUe0nk2a+0030n+K7YUc95/J66tRIp3SVXUpGyUI7wvPxDBoJ/UaLIuIqtuInRwiiqp4z3XbBYr3cGp9P30zJXiSjk1HLsqdIvxvzV1q8ZtB3ppa5bkwZkDz7LsF09Qxgi0Roa6UUU1LnxYH5JP74D1LUjNrkXigabc6kZM5vPFZi3NPi3dVXnFT+EQUM17IvEi1tL1xUkcEHb+lo6duvRUO644wwSDpaPWgG7sAApIKqqqm4jvxo1yvcrjdoTiqtrQ2I+u5nr19ItbUA2a5IAX3GvuP8U2ypMS5pSwFC5peTtM0lnSkMWVVUJb48a+8//Z`,
-              },
-            },
-          ],
-          role: "user",
-        },
-      ];
-      const expectedOutput: MessageParam[] = [
-        {
-          role: "user",
-          content: [
-            {
-              type: "text",
-              text: "What do you see in the image?",
-            },
-            {
-              type: "image",
-              source: {
-                type: "base64",
-                media_type: "image/jpeg",
-                data: "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAQDAwQDAwQEAwQFBAQFBgoHBgYGBg0JCggKDw0QEA8NDw4RExgUERIXEg4PFRwVFxkZGxsbEBQdHx0aHxgaGxr/2wBDAQQFBQYFBgwHBwwaEQ8RGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhr/wAARCAAgACADASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAACAQHCQb/xAAvEAABAgUCBAUDBQEAAAAAAAACAQMEBQYHERIhAAgTYSIxMkJxI2KCFBVBUVKh/8QAGAEAAwEBAAAAAAAAAAAAAAAAAwQFAQL/xAAnEQABBAECAwkAAAAAAAAAAAACAQMEEQAFMiExYRITFCJBcXKBof/aAAwDAQACEQMRAD8Aufmb5mnbWREFRdvIMZ3cWcaBh2NHUGEFwtIKQp63CX0h+S7YQgRzGSq6kgqGAS8NQRc6fmkIMWwSxJEyP+m0bwggQr5iIom6KnnxXty61jK+uJUVUxzxm/M5g5EASr6G9WGwTsIIIp2FOHJfi0kyvzS9Cv0zGwEF+2whOAUY4a6mnm2lREURLPoTggNG5tS6xpmOT4GQptwNUZc6sbexzcZRVSTKTOgudMPEL0j7E2uQNOxIqcaYcqXNaxe2HKnauBiAraDZ6n0k0tTBpPNwE9pptqDP3DtlBC1Q8qNw5K4AwLEunYkWMwcYg6fnqoH/ADPHA2/qeZWquhJJ3pODmEhmg/qGl2XAloebL5HWK/K8dOMOM7xVPfJrMhmQiq0SFXOlyPc+jIq3lwakpeYNq27K491kfvbzls07ECiSdlThhWKvj1LLx0VVLWGqSBuFJ1jc3WBEUb8K4TUieHz3xni7ea3lSZvZDhUVImxAVtBso39VdLUe0nk2a+0030n+K7YUc95/J66tRIp3SVXUpGyUI7wvPxDBoJ/UaLIuIqtuInRwiiqp4z3XbBYr3cGp9P30zJXiSjk1HLsqdIvxvzV1q8ZtB3ppa5bkwZkDz7LsF09Qxgi0Roa6UUU1LnxYH5JP74D1LUjNrkXigabc6kZM5vPFZi3NPi3dVXnFT+EQUM17IvEi1tL1xUkcEHb+lo6duvRUO644wwSDpaPWgG7sAApIKqqqm4jvxo1yvcrjdoTiqtrQ2I+u5nr19ItbUA2a5IAX3GvuP8U2ypMS5pSwFC5peTtM0lnSkMWVVUJb48a+8//Z",
-              },
-            },
-          ],
-        },
-      ];
-
-      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
-    });
   });
 
   describe("Tool Message Formatting", () => {
@@ -251,47 +97,6 @@ describe("Message Formatting", () => {
       expect(OpenAI.toOpenAIMessage(toolCallMessages)).toEqual(expectedOutput);
     });
 
-    test("Anthropic formats tool calls correctly", () => {
-      const anthropic = new Anthropic();
-      const expectedOutput: MessageParam[] = [
-        {
-          role: "user",
-          content: "What's the weather in London?",
-        },
-        {
-          role: "assistant",
-          content: [
-            {
-              type: "text",
-              text: "Let me check the weather.",
-            },
-            {
-              type: "tool_use",
-              id: "call_123",
-              name: "weather",
-              input: {
-                location: "London",
-              },
-            },
-          ],
-        },
-        {
-          role: "user", // anthropic considers all that comes not from their inference API is user role
-          content: [
-            {
-              type: "tool_result",
-              tool_use_id: "call_123",
-              content: "The weather in London is sunny, +20°C",
-            },
-          ],
-        },
-      ];
-
-      expect(anthropic.formatMessages(toolCallMessages)).toEqual(
-        expectedOutput,
-      );
-    });
-
     test("OpenAI formats multiple tool calls correctly", () => {
       const multiToolMessages: ChatMessage[] = [
         {
diff --git a/packages/llamaindex/tests/package.json b/packages/llamaindex/tests/package.json
index d0700dfaeda4c73addc97ef90456de98eb69ae81..afbf4bf2994d5207b1413e95334460788df54558 100644
--- a/packages/llamaindex/tests/package.json
+++ b/packages/llamaindex/tests/package.json
@@ -16,7 +16,6 @@
     "dotenv": "^16.4.5",
     "llamaindex": "workspace:*",
     "msw": "^2.6.5",
-    "@anthropic-ai/sdk": "0.32.1",
     "vitest": "^2.1.5"
   }
 }
diff --git a/packages/providers/anthropic/package.json b/packages/providers/anthropic/package.json
index 51abb1a14dafb2db071198e68860641f61ccc636..9819c5bdf1cf751bf3ab0fca75841f70e9bfa70d 100644
--- a/packages/providers/anthropic/package.json
+++ b/packages/providers/anthropic/package.json
@@ -27,7 +27,8 @@
   },
   "scripts": {
     "build": "bunchee",
-    "dev": "bunchee --watch"
+    "dev": "bunchee --watch",
+    "test": "vitest run"
   },
   "devDependencies": {
     "bunchee": "6.2.0"
@@ -36,6 +37,7 @@
     "@anthropic-ai/sdk": "0.32.1",
     "@llamaindex/core": "workspace:*",
     "@llamaindex/env": "workspace:*",
-    "remeda": "^2.17.3"
+    "remeda": "^2.17.3",
+    "vitest": "^2.1.5"
   }
 }
diff --git a/packages/providers/anthropic/src/llm.ts b/packages/providers/anthropic/src/llm.ts
index 853d3238ade218ec762ccfe06635aa9b3c359c8f..ca9747d9d1cb0d649d501ec72df169125e6ccb28 100644
--- a/packages/providers/anthropic/src/llm.ts
+++ b/packages/providers/anthropic/src/llm.ts
@@ -12,6 +12,7 @@ import type {
   ToolUseBlock,
 } from "@anthropic-ai/sdk/resources/messages";
 import { wrapLLMEvent } from "@llamaindex/core/decorator";
+import type { JSONObject } from "@llamaindex/core/global";
 import type {
   BaseTool,
   ChatMessage,
@@ -183,6 +184,18 @@ export class Anthropic extends ToolCallLLM<
     return model;
   };
 
+  parseToolInput = (input: string | JSONObject) => {
+    if (typeof input === "object" && !Array.isArray(input)) return input;
+
+    if (typeof input === "string") {
+      const parsed = JSON.parse(input);
+      if (typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
+    }
+
+    console.error("Invalid tool input:", input);
+    throw new Error("Tool input must be a dictionary");
+  };
+
   formatMessages(
     messages: ChatMessage<ToolCallLLMMessageOptions>[],
   ): MessageParam[] {
@@ -205,10 +218,7 @@ export class Anthropic extends ToolCallLLM<
               type: "tool_use" as const,
               id: tool.id,
               name: tool.name,
-              input:
-                typeof tool.input === "string"
-                  ? JSON.parse(tool.input)
-                  : tool.input,
+              input: this.parseToolInput(tool.input),
             })),
           ],
         };
@@ -444,7 +454,10 @@ export class Anthropic extends ToolCallLLM<
                 toolCall: toolUseBlock.map((block) => ({
                   id: block.id,
                   name: block.name,
-                  input: JSON.stringify(block.input),
+                  input:
+                    typeof block.input === "string"
+                      ? block.input
+                      : JSON.stringify(block.input),
                 })),
               }
             : {},
diff --git a/packages/providers/anthropic/tests/index.test.ts b/packages/providers/anthropic/tests/index.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..73c907138c07a034b178aadfbc48c57a38cb8fda
--- /dev/null
+++ b/packages/providers/anthropic/tests/index.test.ts
@@ -0,0 +1,279 @@
+import type { MessageParam } from "@anthropic-ai/sdk/resources/messages";
+import type { ChatMessage } from "@llamaindex/core/llms";
+import { setEnvs } from "@llamaindex/env";
+import { beforeAll, describe, expect, test } from "vitest";
+import { Anthropic } from "../src/index";
+
+beforeAll(() => {
+  setEnvs({
+    ANTHROPIC_API_KEY: "valid",
+  });
+});
+
+describe("Message Formatting", () => {
+  describe("Basic Message Formatting", () => {
+    test("Anthropic formats basic messages correctly", () => {
+      const anthropic = new Anthropic();
+      const inputMessages: ChatMessage[] = [
+        {
+          content: "You are a helpful assistant.",
+          role: "assistant",
+        },
+        {
+          content: "Hello?",
+          role: "user",
+        },
+      ];
+      const expectedOutput: MessageParam[] = [
+        {
+          content: "You are a helpful assistant.",
+          role: "assistant",
+        },
+        {
+          content: "Hello?",
+          role: "user",
+        },
+      ];
+
+      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
+    });
+
+    test("Anthropic handles multi-turn conversation correctly", () => {
+      const anthropic = new Anthropic();
+      const inputMessages: ChatMessage[] = [
+        { content: "Hi", role: "user" },
+        { content: "Hello! How can I help?", role: "assistant" },
+        { content: "What's the weather?", role: "user" },
+      ];
+      const expectedOutput: MessageParam[] = [
+        { content: "Hi", role: "user" },
+        { content: "Hello! How can I help?", role: "assistant" },
+        { content: "What's the weather?", role: "user" },
+      ];
+      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
+    });
+  });
+
+  describe("Advanced Message Formatting", () => {
+    test("Anthropic filters out system messages", () => {
+      const anthropic = new Anthropic();
+      const inputMessages: ChatMessage[] = [
+        {
+          content: "You are a helpful assistant.",
+          role: "assistant",
+        },
+        {
+          content: "Hello?",
+          role: "user",
+        },
+        {
+          content: "I am a system message.",
+          role: "system",
+        },
+        {
+          content: "What is your name?",
+          role: "user",
+        },
+      ];
+      const expectedOutput: MessageParam[] = [
+        {
+          content: "You are a helpful assistant.",
+          role: "assistant",
+        },
+        {
+          content: "Hello?\nWhat is your name?",
+          role: "user",
+        },
+      ];
+
+      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
+    });
+
+    test("Anthropic merges consecutive messages from the same role", () => {
+      const anthropic = new Anthropic();
+      const inputMessages: ChatMessage[] = [
+        {
+          content: "Hello?",
+          role: "user",
+        },
+        {
+          content: "How are you?",
+          role: "user",
+        },
+        {
+          content: "I am fine, thank you!",
+          role: "assistant",
+        },
+        {
+          content: "And you?",
+          role: "assistant",
+        },
+      ];
+      const expectedOutput: MessageParam[] = [
+        {
+          content: "Hello?\nHow are you?",
+          role: "user",
+        },
+        {
+          content: "I am fine, thank you!\nAnd you?",
+          role: "assistant",
+        },
+      ];
+
+      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
+    });
+
+    test("Anthropic handles image content", () => {
+      const anthropic = new Anthropic();
+      const inputMessages: ChatMessage[] = [
+        {
+          content: [
+            {
+              text: "What do you see in the image?",
+              type: "text",
+            },
+            {
+              type: "image_url",
+              image_url: {
+                url: `data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAQDAwQDAwQEAwQFBAQFBgoHBgYGBg0JCggKDw0QEA8NDw4RExgUERIXEg4PFRwVFxkZGxsbEBQdHx0aHxgaGxr/2wBDAQQFBQYFBgwHBwwaEQ8RGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhr/wAARCAAgACADASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAACAQHCQb/xAAvEAABAgUCBAUDBQEAAAAAAAACAQMEBQYHERIhAAgTYSIxMkJxI2KCFBVBUVKh/8QAGAEAAwEBAAAAAAAAAAAAAAAAAwQFAQL/xAAnEQABBAECAwkAAAAAAAAAAAACAQMEEQAFMiExYRITFCJBcXKBof/aAAwDAQACEQMRAD8Aufmb5mnbWREFRdvIMZ3cWcaBh2NHUGEFwtIKQp63CX0h+S7YQgRzGSq6kgqGAS8NQRc6fmkIMWwSxJEyP+m0bwggQr5iIom6KnnxXty61jK+uJUVUxzxm/M5g5EASr6G9WGwTsIIIp2FOHJfi0kyvzS9Cv0zGwEF+2whOAUY4a6mnm2lREURLPoTggNG5tS6xpmOT4GQptwNUZc6sbexzcZRVSTKTOgudMPEL0j7E2uQNOxIqcaYcqXNaxe2HKnauBiAraDZ6n0k0tTBpPNwE9pptqDP3DtlBC1Q8qNw5K4AwLEunYkWMwcYg6fnqoH/ADPHA2/qeZWquhJJ3pODmEhmg/qGl2XAloebL5HWK/K8dOMOM7xVPfJrMhmQiq0SFXOlyPc+jIq3lwakpeYNq27K491kfvbzls07ECiSdlThhWKvj1LLx0VVLWGqSBuFJ1jc3WBEUb8K4TUieHz3xni7ea3lSZvZDhUVImxAVtBso39VdLUe0nk2a+0030n+K7YUc95/J66tRIp3SVXUpGyUI7wvPxDBoJ/UaLIuIqtuInRwiiqp4z3XbBYr3cGp9P30zJXiSjk1HLsqdIvxvzV1q8ZtB3ppa5bkwZkDz7LsF09Qxgi0Roa6UUU1LnxYH5JP74D1LUjNrkXigabc6kZM5vPFZi3NPi3dVXnFT+EQUM17IvEi1tL1xUkcEHb+lo6duvRUO644wwSDpaPWgG7sAApIKqqqm4jvxo1yvcrjdoTiqtrQ2I+u5nr19ItbUA2a5IAX3GvuP8U2ypMS5pSwFC5peTtM0lnSkMWVVUJb48a+8//Z`,
+              },
+            },
+          ],
+          role: "user",
+        },
+      ];
+      const expectedOutput: MessageParam[] = [
+        {
+          role: "user",
+          content: [
+            {
+              type: "text",
+              text: "What do you see in the image?",
+            },
+            {
+              type: "image",
+              source: {
+                type: "base64",
+                media_type: "image/jpeg",
+                data: "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAQDAwQDAwQEAwQFBAQFBgoHBgYGBg0JCggKDw0QEA8NDw4RExgUERIXEg4PFRwVFxkZGxsbEBQdHx0aHxgaGxr/2wBDAQQFBQYFBgwHBwwaEQ8RGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhr/wAARCAAgACADASIAAhEBAxEB/8QAGAABAAMBAAAAAAAAAAAAAAAACAQHCQb/xAAvEAABAgUCBAUDBQEAAAAAAAACAQMEBQYHERIhAAgTYSIxMkJxI2KCFBVBUVKh/8QAGAEAAwEBAAAAAAAAAAAAAAAAAwQFAQL/xAAnEQABBAECAwkAAAAAAAAAAAACAQMEEQAFMiExYRITFCJBcXKBof/aAAwDAQACEQMRAD8Aufmb5mnbWREFRdvIMZ3cWcaBh2NHUGEFwtIKQp63CX0h+S7YQgRzGSq6kgqGAS8NQRc6fmkIMWwSxJEyP+m0bwggQr5iIom6KnnxXty61jK+uJUVUxzxm/M5g5EASr6G9WGwTsIIIp2FOHJfi0kyvzS9Cv0zGwEF+2whOAUY4a6mnm2lREURLPoTggNG5tS6xpmOT4GQptwNUZc6sbexzcZRVSTKTOgudMPEL0j7E2uQNOxIqcaYcqXNaxe2HKnauBiAraDZ6n0k0tTBpPNwE9pptqDP3DtlBC1Q8qNw5K4AwLEunYkWMwcYg6fnqoH/ADPHA2/qeZWquhJJ3pODmEhmg/qGl2XAloebL5HWK/K8dOMOM7xVPfJrMhmQiq0SFXOlyPc+jIq3lwakpeYNq27K491kfvbzls07ECiSdlThhWKvj1LLx0VVLWGqSBuFJ1jc3WBEUb8K4TUieHz3xni7ea3lSZvZDhUVImxAVtBso39VdLUe0nk2a+0030n+K7YUc95/J66tRIp3SVXUpGyUI7wvPxDBoJ/UaLIuIqtuInRwiiqp4z3XbBYr3cGp9P30zJXiSjk1HLsqdIvxvzV1q8ZtB3ppa5bkwZkDz7LsF09Qxgi0Roa6UUU1LnxYH5JP74D1LUjNrkXigabc6kZM5vPFZi3NPi3dVXnFT+EQUM17IvEi1tL1xUkcEHb+lo6duvRUO644wwSDpaPWgG7sAApIKqqqm4jvxo1yvcrjdoTiqtrQ2I+u5nr19ItbUA2a5IAX3GvuP8U2ypMS5pSwFC5peTtM0lnSkMWVVUJb48a+8//Z",
+              },
+            },
+          ],
+        },
+      ];
+
+      expect(anthropic.formatMessages(inputMessages)).toEqual(expectedOutput);
+    });
+  });
+
+  describe("Tool Message Formatting", () => {
+    const toolCallMessages: ChatMessage[] = [
+      {
+        role: "user",
+        content: "What's the weather in London?",
+      },
+      {
+        role: "assistant",
+        content: "Let me check the weather.",
+        options: {
+          toolCall: [
+            {
+              id: "call_123",
+              name: "weather",
+              input: JSON.stringify({ location: "London" }),
+            },
+          ],
+        },
+      },
+      {
+        role: "assistant",
+        content: "The weather in London is sunny, +20°C",
+        options: {
+          toolResult: {
+            id: "call_123",
+          },
+        },
+      },
+    ];
+
+    test("Anthropic formats tool calls correctly", () => {
+      const anthropic = new Anthropic();
+      const expectedOutput: MessageParam[] = [
+        {
+          role: "user",
+          content: "What's the weather in London?",
+        },
+        {
+          role: "assistant",
+          content: [
+            {
+              type: "text",
+              text: "Let me check the weather.",
+            },
+            {
+              type: "tool_use",
+              id: "call_123",
+              name: "weather",
+              input: {
+                location: "London",
+              },
+            },
+          ],
+        },
+        {
+          role: "user", // anthropic considers all that comes not from their inference API is user role
+          content: [
+            {
+              type: "tool_result",
+              tool_use_id: "call_123",
+              content: "The weather in London is sunny, +20°C",
+            },
+          ],
+        },
+      ];
+
+      expect(anthropic.formatMessages(toolCallMessages)).toEqual(
+        expectedOutput,
+      );
+    });
+
+    test("Anthropic throws error for invalid tool input", () => {
+      const anthropic = new Anthropic();
+      const invalidToolMessages: ChatMessage[] = [
+        {
+          role: "assistant",
+          content: "Let me check that for you",
+          options: {
+            toolCall: [
+              {
+                id: "toolu_123",
+                name: "search_tool",
+                input: '"{\\"query\\":\\"test\\"}}"', // Invalid JSON string
+              },
+            ],
+          },
+        },
+      ];
+
+      expect(() => anthropic.formatMessages(invalidToolMessages)).toThrow();
+
+      const stringToolMessages: ChatMessage[] = [
+        {
+          role: "assistant",
+          content: "Let me check that for you",
+          options: {
+            toolCall: [
+              {
+                id: "toolu_123",
+                name: "search_tool",
+                input: "not a json string",
+              },
+            ],
+          },
+        },
+      ];
+
+      expect(() => anthropic.formatMessages(stringToolMessages)).toThrow();
+    });
+  });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index cfc24b1d773de98dea7c936d0033a9e8f069b6b4..3c224b9fe23572a4d85b82ba4c65dc49899a2f26 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1059,9 +1059,6 @@ importers:
 
   packages/llamaindex/tests:
     devDependencies:
-      '@anthropic-ai/sdk':
-        specifier: 0.32.1
-        version: 0.32.1(encoding@0.1.13)
       '@azure/cosmos':
         specifier: ^4.1.1
         version: 4.1.1
@@ -1135,6 +1132,9 @@ importers:
       remeda:
         specifier: ^2.17.3
         version: 2.17.3
+      vitest:
+        specifier: ^2.1.5
+        version: 2.1.5(@edge-runtime/vm@4.0.4)(@types/node@22.9.0)(happy-dom@15.11.6)(msw@2.6.5(@types/node@22.9.0)(typescript@5.7.2))(terser@5.37.0)
     devDependencies:
       bunchee:
         specifier: 6.2.0
@@ -11645,37 +11645,6 @@ packages:
       terser:
         optional: true
 
-  vite@5.4.11:
-    resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==}
-    engines: {node: ^18.0.0 || >=20.0.0}
-    hasBin: true
-    peerDependencies:
-      '@types/node': ^18.0.0 || >=20.0.0
-      less: '*'
-      lightningcss: ^1.21.0
-      sass: '*'
-      sass-embedded: '*'
-      stylus: '*'
-      sugarss: '*'
-      terser: ^5.4.0
-    peerDependenciesMeta:
-      '@types/node':
-        optional: true
-      less:
-        optional: true
-      lightningcss:
-        optional: true
-      sass:
-        optional: true
-      sass-embedded:
-        optional: true
-      stylus:
-        optional: true
-      sugarss:
-        optional: true
-      terser:
-        optional: true
-
   vite@5.4.12:
     resolution: {integrity: sha512-KwUaKB27TvWwDJr1GjjWthLMATbGEbeWYZIbGZ5qFIsgPP3vWzLu4cVooqhm5/Z2SPDUMjyPVjTztm5tYKwQxA==}
     engines: {node: ^18.0.0 || >=20.0.0}
@@ -16470,14 +16439,14 @@ snapshots:
       chai: 5.1.2
       tinyrainbow: 1.2.0
 
-  '@vitest/mocker@2.1.5(msw@2.6.5(@types/node@22.9.0)(typescript@5.7.2))(vite@5.4.11(@types/node@22.9.0)(terser@5.37.0))':
+  '@vitest/mocker@2.1.5(msw@2.6.5(@types/node@22.9.0)(typescript@5.7.2))(vite@5.4.12(@types/node@22.9.0)(terser@5.37.0))':
     dependencies:
       '@vitest/spy': 2.1.5
       estree-walker: 3.0.3
       magic-string: 0.30.17
     optionalDependencies:
       msw: 2.6.5(@types/node@22.9.0)(typescript@5.7.2)
-      vite: 5.4.11(@types/node@22.9.0)(terser@5.37.0)
+      vite: 5.4.12(@types/node@22.9.0)(terser@5.37.0)
 
   '@vitest/pretty-format@2.1.5':
     dependencies:
@@ -24301,16 +24270,6 @@ snapshots:
       fsevents: 2.3.3
       terser: 5.37.0
 
-  vite@5.4.11(@types/node@22.9.0)(terser@5.37.0):
-    dependencies:
-      esbuild: 0.21.5
-      postcss: 8.5.1
-      rollup: 4.34.1
-    optionalDependencies:
-      '@types/node': 22.9.0
-      fsevents: 2.3.3
-      terser: 5.37.0
-
   vite@5.4.12(@types/node@22.9.0)(terser@5.37.0):
     dependencies:
       esbuild: 0.21.5
@@ -24324,7 +24283,7 @@ snapshots:
   vitest@2.1.5(@edge-runtime/vm@4.0.4)(@types/node@22.9.0)(happy-dom@15.11.6)(msw@2.6.5(@types/node@22.9.0)(typescript@5.7.2))(terser@5.37.0):
     dependencies:
       '@vitest/expect': 2.1.5
-      '@vitest/mocker': 2.1.5(msw@2.6.5(@types/node@22.9.0)(typescript@5.7.2))(vite@5.4.11(@types/node@22.9.0)(terser@5.37.0))
+      '@vitest/mocker': 2.1.5(msw@2.6.5(@types/node@22.9.0)(typescript@5.7.2))(vite@5.4.12(@types/node@22.9.0)(terser@5.37.0))
       '@vitest/pretty-format': 2.1.8
       '@vitest/runner': 2.1.5
       '@vitest/snapshot': 2.1.5
@@ -24340,7 +24299,7 @@ snapshots:
       tinyexec: 0.3.1
       tinypool: 1.0.2
       tinyrainbow: 1.2.0
-      vite: 5.4.11(@types/node@22.9.0)(terser@5.37.0)
+      vite: 5.4.12(@types/node@22.9.0)(terser@5.37.0)
       vite-node: 2.1.5(@types/node@22.9.0)(terser@5.37.0)
       why-is-node-running: 2.3.0
     optionalDependencies: