Description
todoListMiddleware emits ToolMessages for write_todos without setting name. Google Gemini requires name on function responses and rejects the request with HTTP 400. Because the ToolMessage persists in history, every subsequent turn in the session keeps failing.
Anthropic and OpenAI accept the missing field, so the bug only surfaces on Gemini.
Affected code
Two call sites in libs/langchain/src/agents/middleware/todoListMiddleware.ts:
- Successful
write_todos result (≈ line 312).
- Parallel-call error branch in
afterModel (≈ line 382).
Every other ToolMessage producer in the package (ToolNode, hitl, toolCallLimit, toolRetry, toolEmulator, contextEditing, pii) already sets name.
Reproduction
- Build
createAgent with middleware: [todoListMiddleware()] and a Gemini chat model.
- Prompt the agent to trigger
write_todos.
- Send any follow-up — the Gemini call returns 400, and every later turn fails too.
Proposed fix
Set name: "write_todos" at both ToolMessage constructions, with regression tests asserting name is set on both the success and parallel-rejection paths.
Description
todoListMiddlewareemitsToolMessages forwrite_todoswithout settingname. Google Gemini requiresnameon function responses and rejects the request with HTTP 400. Because the ToolMessage persists in history, every subsequent turn in the session keeps failing.Anthropic and OpenAI accept the missing field, so the bug only surfaces on Gemini.
Affected code
Two call sites in libs/langchain/src/agents/middleware/todoListMiddleware.ts:
write_todosresult (≈ line 312).afterModel(≈ line 382).Every other ToolMessage producer in the package (
ToolNode,hitl,toolCallLimit,toolRetry,toolEmulator,contextEditing,pii) already setsname.Reproduction
createAgentwithmiddleware: [todoListMiddleware()]and a Gemini chat model.write_todos.Proposed fix
Set
name: "write_todos"at both ToolMessage constructions, with regression tests assertingnameis set on both the success and parallel-rejection paths.