diff --git a/.changeset/small-actors-explode.md b/.changeset/small-actors-explode.md
new file mode 100644
index 0000000000000000000000000000000000000000..85a1025b7cd6c7818e6d4ed115a1b27f502c9300
--- /dev/null
+++ b/.changeset/small-actors-explode.md
@@ -0,0 +1,7 @@
+---
+"llamaindex": patch
+"@llamaindex/core-test": patch
+"@llamaindex/core-e2e": patch
+---
+
+fix: anthropic agent on multiple chat
diff --git a/packages/core/e2e/node/claude.e2e.ts b/packages/core/e2e/node/claude.e2e.ts
index c22a717f2d1feefe7750c615988f8a0ba8b79708..faa96cd735f9f45eda4635eb4ac85100ee1a46b4 100644
--- a/packages/core/e2e/node/claude.e2e.ts
+++ b/packages/core/e2e/node/claude.e2e.ts
@@ -4,7 +4,7 @@ import { AnthropicAgent } from "llamaindex/agent/anthropic";
 import { extractText } from "llamaindex/llm/utils";
 import { ok, strictEqual } from "node:assert";
 import { beforeEach, test } from "node:test";
-import { sumNumbersTool } from "./fixtures/tools.js";
+import { getWeatherTool, sumNumbersTool } from "./fixtures/tools.js";
 import { mockLLMEvent } from "./utils.js";
 
 let llm: LLM;
@@ -118,14 +118,58 @@ await test("anthropic agent", async (t) => {
   });
 
   await t.test("sum numbers", async () => {
-    const openaiAgent = new AnthropicAgent({
+    const anthropicAgent = new AnthropicAgent({
       tools: [sumNumbersTool],
     });
 
-    const { response } = await openaiAgent.chat({
+    const { response } = await anthropicAgent.chat({
       message: "how much is 1 + 1?",
     });
 
     ok(extractText(response.message.content).includes("2"));
   });
 });
+
+await test("anthropic agent with multiple chat", async (t) => {
+  await mockLLMEvent(t, "anthropic-agent-multiple-chat");
+  await t.test("chat", async () => {
+    const agent = new AnthropicAgent({
+      tools: [getWeatherTool],
+    });
+    {
+      const { response } = await agent.chat({
+        message: 'Hello? Response to me "Yes"',
+      });
+      consola.debug("response:", response.message.content);
+      ok(extractText(response.message.content).includes("Yes"));
+    }
+    {
+      const { response } = await agent.chat({
+        message: 'Hello? Response to me "No"',
+      });
+      consola.debug("response:", response.message.content);
+      ok(extractText(response.message.content).includes("No"));
+    }
+    {
+      const { response } = await agent.chat({
+        message: 'Hello? Response to me "Maybe"',
+      });
+      consola.debug("response:", response.message.content);
+      ok(extractText(response.message.content).includes("Maybe"));
+    }
+    {
+      const { response } = await agent.chat({
+        message: "What is the weather in San Francisco?",
+      });
+      consola.debug("response:", response.message.content);
+      ok(extractText(response.message.content).includes("72"));
+    }
+    {
+      const { response } = await agent.chat({
+        message: "What is the weather in Shanghai?",
+      });
+      consola.debug("response:", response.message.content);
+      ok(extractText(response.message.content).includes("72"));
+    }
+  });
+});
diff --git a/packages/core/e2e/node/snapshot/anthropic-agent-multiple-chat.snap b/packages/core/e2e/node/snapshot/anthropic-agent-multiple-chat.snap
new file mode 100644
index 0000000000000000000000000000000000000000..b77cbcbe3ceb44367d9992d6a809a226b874bfaa
--- /dev/null
+++ b/packages/core/e2e/node/snapshot/anthropic-agent-multiple-chat.snap
@@ -0,0 +1,552 @@
+{
+  "llmEventStart": [
+    {
+      "id": "PRESERVE_0",
+      "messages": [
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Yes\""
+        }
+      ]
+    },
+    {
+      "id": "PRESERVE_1",
+      "messages": [
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Yes\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Yes\".\n</thinking>\n\nYes"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"No\""
+        }
+      ]
+    },
+    {
+      "id": "PRESERVE_2",
+      "messages": [
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Yes\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Yes\".\n</thinking>\n\nYes"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"No\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"No\".\n</thinking>\n\nNo"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Maybe\""
+        }
+      ]
+    },
+    {
+      "id": "PRESERVE_3",
+      "messages": [
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Yes\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Yes\".\n</thinking>\n\nYes"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"No\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"No\".\n</thinking>\n\nNo"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Maybe\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Maybe\".\n</thinking>\n\nMaybe"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "What is the weather in San Francisco?"
+        }
+      ]
+    },
+    {
+      "id": "PRESERVE_4",
+      "messages": [
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Yes\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Yes\".\n</thinking>\n\nYes"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"No\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"No\".\n</thinking>\n\nNo"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Maybe\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Maybe\".\n</thinking>\n\nMaybe"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "What is the weather in San Francisco?"
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has asked for the weather in a specific city, San Francisco. The relevant tool to answer this is the getWeather function.\n\nLooking at the required parameters for getWeather:\ncity (string): The user directly provided the city \"San Francisco\"\n\nSince the required \"city\" parameter has been provided, we can proceed with the getWeather function call.\n</thinking>"
+            }
+          ],
+          "role": "assistant",
+          "options": {
+            "toolCall": {
+              "id": "toolu_01Gy7Gxbx7uGmjVncGH6pubL",
+              "name": "getWeather",
+              "input": {
+                "city": "San Francisco"
+              }
+            }
+          }
+        },
+        {
+          "content": "The weather in San Francisco is 72 degrees",
+          "role": "user",
+          "options": {
+            "toolResult": {
+              "result": "The weather in San Francisco is 72 degrees",
+              "isError": false,
+              "id": "toolu_01Gy7Gxbx7uGmjVncGH6pubL"
+            }
+          }
+        }
+      ]
+    },
+    {
+      "id": "PRESERVE_5",
+      "messages": [
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Yes\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Yes\".\n</thinking>\n\nYes"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"No\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"No\".\n</thinking>\n\nNo"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Maybe\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Maybe\".\n</thinking>\n\nMaybe"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "What is the weather in San Francisco?"
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has asked for the weather in a specific city, San Francisco. The relevant tool to answer this is the getWeather function.\n\nLooking at the required parameters for getWeather:\ncity (string): The user directly provided the city \"San Francisco\"\n\nSince the required \"city\" parameter has been provided, we can proceed with the getWeather function call.\n</thinking>"
+            }
+          ],
+          "role": "assistant",
+          "options": {
+            "toolCall": {
+              "id": "toolu_01Gy7Gxbx7uGmjVncGH6pubL",
+              "name": "getWeather",
+              "input": {
+                "city": "San Francisco"
+              }
+            }
+          }
+        },
+        {
+          "content": "The weather in San Francisco is 72 degrees",
+          "role": "user",
+          "options": {
+            "toolResult": {
+              "result": "The weather in San Francisco is 72 degrees",
+              "isError": false,
+              "id": "toolu_01Gy7Gxbx7uGmjVncGH6pubL"
+            }
+          }
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "The current weather in San Francisco is 72 degrees."
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "What is the weather in Shanghai?"
+        }
+      ]
+    },
+    {
+      "id": "PRESERVE_6",
+      "messages": [
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Yes\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Yes\".\n</thinking>\n\nYes"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"No\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"No\".\n</thinking>\n\nNo"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "Hello? Response to me \"Maybe\""
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Maybe\".\n</thinking>\n\nMaybe"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "What is the weather in San Francisco?"
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has asked for the weather in a specific city, San Francisco. The relevant tool to answer this is the getWeather function.\n\nLooking at the required parameters for getWeather:\ncity (string): The user directly provided the city \"San Francisco\"\n\nSince the required \"city\" parameter has been provided, we can proceed with the getWeather function call.\n</thinking>"
+            }
+          ],
+          "role": "assistant",
+          "options": {
+            "toolCall": {
+              "id": "toolu_01Gy7Gxbx7uGmjVncGH6pubL",
+              "name": "getWeather",
+              "input": {
+                "city": "San Francisco"
+              }
+            }
+          }
+        },
+        {
+          "content": "The weather in San Francisco is 72 degrees",
+          "role": "user",
+          "options": {
+            "toolResult": {
+              "result": "The weather in San Francisco is 72 degrees",
+              "isError": false,
+              "id": "toolu_01Gy7Gxbx7uGmjVncGH6pubL"
+            }
+          }
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "The current weather in San Francisco is 72 degrees."
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        },
+        {
+          "role": "user",
+          "content": "What is the weather in Shanghai?"
+        },
+        {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has asked for the weather in a specific city, Shanghai. The relevant tool to answer this is the getWeather function.\n\nLooking at the required parameters for getWeather:\ncity (string): The user directly provided the city \"Shanghai\"\n\nSince the required \"city\" parameter has been provided, we can proceed with the getWeather function call.\n</thinking>"
+            }
+          ],
+          "role": "assistant",
+          "options": {
+            "toolCall": {
+              "id": "toolu_01NHyahSUqrPjxQk9mvCvvGe",
+              "name": "getWeather",
+              "input": {
+                "city": "Shanghai"
+              }
+            }
+          }
+        },
+        {
+          "content": "The weather in Shanghai is 72 degrees",
+          "role": "user",
+          "options": {
+            "toolResult": {
+              "result": "The weather in Shanghai is 72 degrees",
+              "isError": false,
+              "id": "toolu_01NHyahSUqrPjxQk9mvCvvGe"
+            }
+          }
+        }
+      ]
+    }
+  ],
+  "llmEventEnd": [
+    {
+      "id": "PRESERVE_0",
+      "response": {
+        "raw": null,
+        "message": {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Yes\".\n</thinking>\n\nYes"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        }
+      }
+    },
+    {
+      "id": "PRESERVE_1",
+      "response": {
+        "raw": null,
+        "message": {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"No\".\n</thinking>\n\nNo"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        }
+      }
+    },
+    {
+      "id": "PRESERVE_2",
+      "response": {
+        "raw": null,
+        "message": {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has not asked a question that requires using any of the available tools. They have simply requested that I respond with the word \"Maybe\".\n</thinking>\n\nMaybe"
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        }
+      }
+    },
+    {
+      "id": "PRESERVE_3",
+      "response": {
+        "raw": null,
+        "message": {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has asked for the weather in a specific city, San Francisco. The relevant tool to answer this is the getWeather function.\n\nLooking at the required parameters for getWeather:\ncity (string): The user directly provided the city \"San Francisco\"\n\nSince the required \"city\" parameter has been provided, we can proceed with the getWeather function call.\n</thinking>"
+            }
+          ],
+          "role": "assistant",
+          "options": {
+            "toolCall": {
+              "id": "toolu_01Gy7Gxbx7uGmjVncGH6pubL",
+              "name": "getWeather",
+              "input": {
+                "city": "San Francisco"
+              }
+            }
+          }
+        }
+      }
+    },
+    {
+      "id": "PRESERVE_4",
+      "response": {
+        "raw": null,
+        "message": {
+          "content": [
+            {
+              "type": "text",
+              "text": "The current weather in San Francisco is 72 degrees."
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        }
+      }
+    },
+    {
+      "id": "PRESERVE_5",
+      "response": {
+        "raw": null,
+        "message": {
+          "content": [
+            {
+              "type": "text",
+              "text": "<thinking>\nThe user has asked for the weather in a specific city, Shanghai. The relevant tool to answer this is the getWeather function.\n\nLooking at the required parameters for getWeather:\ncity (string): The user directly provided the city \"Shanghai\"\n\nSince the required \"city\" parameter has been provided, we can proceed with the getWeather function call.\n</thinking>"
+            }
+          ],
+          "role": "assistant",
+          "options": {
+            "toolCall": {
+              "id": "toolu_01NHyahSUqrPjxQk9mvCvvGe",
+              "name": "getWeather",
+              "input": {
+                "city": "Shanghai"
+              }
+            }
+          }
+        }
+      }
+    },
+    {
+      "id": "PRESERVE_6",
+      "response": {
+        "raw": null,
+        "message": {
+          "content": [
+            {
+              "type": "text",
+              "text": "The current weather in Shanghai is 72 degrees."
+            }
+          ],
+          "role": "assistant",
+          "options": {}
+        }
+      }
+    }
+  ],
+  "llmEventStream": []
+}
\ No newline at end of file
diff --git a/packages/core/src/agent/base.ts b/packages/core/src/agent/base.ts
index aa0a192cb35f94d0416c5725b10701ecda1cacad..cb2ce97b118bc0c36c539ae1efe874f85b157774 100644
--- a/packages/core/src/agent/base.ts
+++ b/packages/core/src/agent/base.ts
@@ -348,6 +348,8 @@ export abstract class AgentRunner<
         >,
       ) => {
         for await (const stepOutput of iter) {
+          // update chat history for each round
+          this.#chatHistory = [...stepOutput.taskStep.context.store.messages];
           if (stepOutput.isLast) {
             return stepOutput;
           }
@@ -356,7 +358,6 @@ export abstract class AgentRunner<
       },
     );
     const { output, taskStep } = stepOutput;
-    this.#chatHistory = [...taskStep.context.store.messages];
     if (isAsyncIterable(output)) {
       return output.pipeThrough<
         AgentStreamChatResponse<AdditionalMessageOptions>
diff --git a/packages/core/src/llm/anthropic.ts b/packages/core/src/llm/anthropic.ts
index e6d4bfa4e85bb0d1b59a0023cfca812cd89797e4..78f5b7461245f6446d87f16749a1bffce949fa09 100644
--- a/packages/core/src/llm/anthropic.ts
+++ b/packages/core/src/llm/anthropic.ts
@@ -156,58 +156,104 @@ export class Anthropic extends ToolCallLLM<AnthropicAdditionalChatOptions> {
   formatMessages<Beta = false>(
     messages: ChatMessage<ToolCallLLMMessageOptions>[],
   ): Beta extends true ? ToolsBetaMessageParam[] : MessageParam[] {
-    return messages.map<any>((message) => {
-      if (message.role !== "user" && message.role !== "assistant") {
-        throw new Error("Unsupported Anthropic role");
-      }
-      const options = message.options ?? {};
-      if ("toolResult" in options) {
-        const { id, isError } = options.toolResult;
-        return {
-          role: "user",
-          content: [
-            {
-              type: "tool_result",
-              is_error: isError,
-              content: [
-                {
-                  type: "text",
-                  text: extractText(message.content),
-                },
-              ],
-              tool_use_id: id,
-            },
-          ] satisfies ToolResultBlockParam[],
-        } satisfies ToolsBetaMessageParam;
-      } else if ("toolCall" in options) {
-        const aiThinkingText = extractText(message.content);
-        return {
-          role: "assistant",
-          content: [
-            // this could be empty when you call two tools in one query
-            ...(aiThinkingText.trim()
-              ? [
+    const result: ToolsBetaMessageParam[] = messages
+      .filter(
+        (message) => message.role === "user" || message.role === "assistant",
+      )
+      .map((message) => {
+        const options = message.options ?? {};
+        if ("toolResult" in options) {
+          const { id, isError } = options.toolResult;
+          return {
+            role: "user",
+            content: [
+              {
+                type: "tool_result",
+                is_error: isError,
+                content: [
                   {
                     type: "text",
-                    text: aiThinkingText,
-                  } satisfies TextBlockParam,
-                ]
-              : []),
-            {
-              type: "tool_use",
-              id: options.toolCall.id,
-              name: options.toolCall.name,
-              input: options.toolCall.input,
-            } satisfies ToolUseBlockParam,
-          ] satisfies ToolsBetaContentBlock[],
-        } satisfies ToolsBetaMessageParam;
+                    text: extractText(message.content),
+                  },
+                ],
+                tool_use_id: id,
+              },
+            ] satisfies ToolResultBlockParam[],
+          } satisfies ToolsBetaMessageParam;
+        } else if ("toolCall" in options) {
+          const aiThinkingText = extractText(message.content);
+          return {
+            role: "assistant",
+            content: [
+              // this could be empty when you call two tools in one query
+              ...(aiThinkingText.trim()
+                ? [
+                    {
+                      type: "text",
+                      text: aiThinkingText,
+                    } satisfies TextBlockParam,
+                  ]
+                : []),
+              {
+                type: "tool_use",
+                id: options.toolCall.id,
+                name: options.toolCall.name,
+                input: options.toolCall.input,
+              } satisfies ToolUseBlockParam,
+            ] satisfies ToolsBetaContentBlock[],
+          } satisfies ToolsBetaMessageParam;
+        }
+
+        return {
+          content: extractText(message.content),
+          role: message.role as "user" | "assistant",
+        } satisfies MessageParam;
+      });
+    // merge messages with the same role
+    // in case of 'messages: roles must alternate between "user" and "assistant", but found multiple "user" roles in a row'
+    const realResult: ToolsBetaMessageParam[] = [];
+    for (let i = 0; i < result.length; i++) {
+      if (i === 0) {
+        realResult.push(result[i]);
+        continue;
+      }
+      const current = result[i];
+      const previous = result[i - 1];
+      if (current.role === previous.role) {
+        // merge two messages with the same role
+        if (Array.isArray(previous.content)) {
+          if (Array.isArray(current.content)) {
+            previous.content.push(...current.content);
+          } else {
+            previous.content.push({
+              type: "text",
+              text: current.content,
+            });
+          }
+        } else {
+          if (Array.isArray(current.content)) {
+            previous.content = [
+              {
+                type: "text",
+                text: previous.content,
+              },
+              ...current.content,
+            ];
+          } else {
+            previous.content += `\n${current.content}`;
+          }
+        }
+        // no need to push the message
+      }
+      // if the roles are different, just push the message
+      else {
+        realResult.push(current);
       }
+    }
 
-      return {
-        content: extractText(message.content),
-        role: message.role,
-      } satisfies MessageParam;
-    });
+    return realResult as Beta extends true
+      ? ToolsBetaMessageParam[]
+      : MessageParam[];
   }
 
   chat(
diff --git a/packages/core/tests/llm/index.test.ts b/packages/core/tests/llm/index.test.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fbde9f13caef427d947284dc8e2c262f2e09d94e
--- /dev/null
+++ b/packages/core/tests/llm/index.test.ts
@@ -0,0 +1,66 @@
+import { setEnvs } from "@llamaindex/env";
+import { Anthropic } from "llamaindex";
+import { beforeAll, describe, expect, test } from "vitest";
+
+beforeAll(() => {
+  setEnvs({
+    ANTHROPIC_API_KEY: "valid",
+  });
+});
+
+describe("Anthropic llm", () => {
+  test("format messages", () => {
+    const anthropic = new Anthropic();
+    expect(
+      anthropic.formatMessages([
+        {
+          content: "You are a helpful assistant.",
+          role: "assistant",
+        },
+        {
+          content: "Hello?",
+          role: "user",
+        },
+      ]),
+    ).toEqual([
+      {
+        content: "You are a helpful assistant.",
+        role: "assistant",
+      },
+      {
+        content: "Hello?",
+        role: "user",
+      },
+    ]);
+
+    expect(
+      anthropic.formatMessages([
+        {
+          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",
+        },
+      ]),
+    ).toEqual([
+      {
+        content: "You are a helpful assistant.",
+        role: "assistant",
+      },
+      {
+        content: "Hello?\nWhat is your name?",
+        role: "user",
+      },
+    ]);
+  });
+});