From 77b8ef79cad6d77f2a445a980e636981deca9684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?d=20=F0=9F=94=B9?= Date: Wed, 25 Mar 2026 08:00:01 +0800 Subject: [PATCH] fix(middleware): use HumanMessage in LoopDetectionMiddleware for Anthropic compat (#1300) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LoopDetectionMiddleware injected SystemMessage mid-conversation to warn about repetitive tool calls. This crashes Anthropic models because langchain_anthropic's _format_messages() requires system messages to appear only at the start of the conversation — interleaved system messages raise 'Received multiple non-consecutive system messages'. Switch the warning injection from SystemMessage to HumanMessage, which works with all providers (Anthropic, OpenAI, Google, etc.). Fixes #1299 Co-authored-by: voidborne-d --- .../agents/middlewares/loop_detection_middleware.py | 11 ++++++++--- backend/tests/test_loop_detection_middleware.py | 4 ++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/backend/packages/harness/deerflow/agents/middlewares/loop_detection_middleware.py b/backend/packages/harness/deerflow/agents/middlewares/loop_detection_middleware.py index f96373e..0ae892a 100644 --- a/backend/packages/harness/deerflow/agents/middlewares/loop_detection_middleware.py +++ b/backend/packages/harness/deerflow/agents/middlewares/loop_detection_middleware.py @@ -21,7 +21,7 @@ from typing import override from langchain.agents import AgentState from langchain.agents.middleware import AgentMiddleware -from langchain_core.messages import SystemMessage +from langchain_core.messages import HumanMessage from langgraph.runtime import Runtime logger = logging.getLogger(__name__) @@ -203,8 +203,13 @@ class LoopDetectionMiddleware(AgentMiddleware[AgentState]): return {"messages": [stripped_msg]} if warning: - # Inject a system message warning the model - return {"messages": [SystemMessage(content=warning)]} + # Inject as HumanMessage instead of SystemMessage to avoid + # Anthropic's "multiple non-consecutive system messages" error. + # Anthropic models require system messages only at the start of + # the conversation; injecting one mid-conversation crashes + # langchain_anthropic's _format_messages(). HumanMessage works + # with all providers. See #1299. + return {"messages": [HumanMessage(content=warning)]} return None diff --git a/backend/tests/test_loop_detection_middleware.py b/backend/tests/test_loop_detection_middleware.py index b9aa2da..3bd0c36 100644 --- a/backend/tests/test_loop_detection_middleware.py +++ b/backend/tests/test_loop_detection_middleware.py @@ -2,7 +2,7 @@ from unittest.mock import MagicMock -from langchain_core.messages import AIMessage, SystemMessage +from langchain_core.messages import AIMessage, HumanMessage, SystemMessage from deerflow.agents.middlewares.loop_detection_middleware import ( _HARD_STOP_MSG, @@ -81,7 +81,7 @@ class TestLoopDetection: assert result is not None msgs = result["messages"] assert len(msgs) == 1 - assert isinstance(msgs[0], SystemMessage) + assert isinstance(msgs[0], HumanMessage) assert "LOOP DETECTED" in msgs[0].content def test_warn_only_injected_once(self):