-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Checked other resources
- This is a bug, not a usage question.
- I added a clear and descriptive title that summarizes this issue.
- I used the GitHub search to find a similar question and didn't find it.
- I am sure that this is a bug in LangChain rather than my code.
- The bug is not resolved by updating to the latest stable version of LangChain (or the specific integration package).
- This is not related to the langchain-community package.
- I read what a minimal reproducible example is (https://stackoverflow.com/help/minimal-reproducible-example).
- I posted a self-contained, minimal, reproducible example. A maintainer can copy it and run it AS IS.
Example Code
import "dotenv/config"
import { createAgent, HumanMessage, SystemMessage, summarizationMiddleware, tool } from "langchain"
import { MemorySaver } from "@langchain/langgraph"
import { ChatGoogleGenerativeAI } from "@langchain/google-genai"
import { z } from "zod"
const model = new ChatGoogleGenerativeAI({
model: "models/gemini-2.5-flash-preview-09-2025",
temperature: 0,
apiKey: process.env.GEMINI_API_KEY,
baseUrl: "https://generativelanguage.googleapis.com",
})
const searchTool = tool(
({ query }: { query: string }) => {
console.log(`Searching for: ${query}`)
return `Found results for: ${query}`
},
{
name: "search",
description: "Search for information",
schema: z.object({
query: z.string().describe("The search query"),
}),
}
)
const agent = createAgent({
model,
tools: [searchTool],
checkpointer: new MemorySaver(),
middleware: [
summarizationMiddleware({
model: model,
maxTokensBeforeSummary: 100,
messagesToKeep: 10,
})
],
})
const threadId = "bug-reproduction"
console.log("\n=== Message 1: Hi (with system message) ===")
await agent.invoke(
{ messages: [new SystemMessage("You are a helpful assistant."), new HumanMessage("Hi")] },
{ configurable: { thread_id: threadId } }
)
console.log("\n=== Message 2: Search for cats ===")
await agent.invoke(
{ messages: [new HumanMessage("Search for cats")] },
{ configurable: { thread_id: threadId } }
)
console.log("\n=== Message 3: Search for dogs ===")
await agent.invoke(
{ messages: [new HumanMessage("Search for dogs")] },
{ configurable: { thread_id: threadId } }
)
console.log("\n=== Message 4: Search for birds (should trigger summarization and fail) ===")
try {
await agent.invoke(
{ messages: [new HumanMessage("Search for birds")] },
{ configurable: { thread_id: threadId } }
)
console.log("✓ Success - no error (bug not reproduced)")
} catch (error: any) {
if (error.message.includes("function call turn comes immediately after")) {
console.log("\n✗ BUG REPRODUCED!")
console.log("Error:", error.message)
} else {
console.log("✗ Different error:", error.message)
}
}Error Message and Stack Trace (if applicable)
[GoogleGenerativeAI Error]: Error fetching from https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-09-2025:generateContent: [400 Bad Request] Please ensure that function call turn comes immediately after a user turn or after a function response turn.
Description
After summarization with messagesToKeep: 10, the preserved messages
start with an AI message that has tool calls, without its preceding human message.
Gemini requires: human → ai (with tool calls) → tool
But gets after summarization: system → ai (with tool calls) → tool
I believe this should be handled in summarizationMiddleware.findSafeCutoff().
It ensures tool call/response pairs stay together, but doesn't ensure that
preserved messages don't start with an AI message containing tool calls.
System Info
LangChain v1.0.1 on macOS