What happened
DynamicContextMiddleware._make_reminder_and_user_messages rebuilds the original user turn as a fresh HumanMessage carrying only content, id, name and additional_kwargs (backend/packages/harness/deerflow/agents/middlewares/dynamic_context_middleware.py, main @ 827acf5):
messages.append(
HumanMessage(
content=original.content,
id=f"{stable_id}{INJECTED_USER_MESSAGE_ID_SUFFIX}",
name=original.name,
additional_kwargs=original.additional_kwargs,
)
)
Any other field the caller attached to the incoming turn — notably response_metadata — is silently dropped from the message the agent run actually sees.
Steps to reproduce
Pure-logic repro (no model needed):
from langchain_core.messages import HumanMessage
from types import SimpleNamespace
from deerflow.agents.middlewares.dynamic_context_middleware import DynamicContextMiddleware
mw = DynamicContextMiddleware()
original = HumanMessage(content="Hello", id="abc", response_metadata={"external": "value"})
result = mw.before_agent({"messages": [original]}, SimpleNamespace(context={}))
print(result["messages"][1].response_metadata) # {} on main — "external" is gone
Expected behavior
The re-id'd user message keeps caller-attached fields such as response_metadata. The sibling middlewares already guarantee this — pii_redaction_middleware.py:450 uses model_copy(update=...) with the comment "preserves artifact / response_metadata that a hand-built constructor call would silently drop", and thread_data_middleware.py:106 / input_sanitization_middleware.py:362 follow the same pattern. The documented {id}__user id-swap can be kept exactly as-is; only the field preservation changes.
Environment
- deer-flow: main @
827acf5 (2026-09-27)
- OS: any (logic-level; reproduced in the unit suite with mocked runtime, no API key)
What happened
DynamicContextMiddleware._make_reminder_and_user_messagesrebuilds the original user turn as a freshHumanMessagecarrying onlycontent,id,nameandadditional_kwargs(backend/packages/harness/deerflow/agents/middlewares/dynamic_context_middleware.py, main @827acf5):Any other field the caller attached to the incoming turn — notably
response_metadata— is silently dropped from the message the agent run actually sees.Steps to reproduce
Pure-logic repro (no model needed):
Expected behavior
The re-id'd user message keeps caller-attached fields such as
response_metadata. The sibling middlewares already guarantee this —pii_redaction_middleware.py:450usesmodel_copy(update=...)with the comment "preserves artifact / response_metadata that a hand-built constructor call would silently drop", andthread_data_middleware.py:106/input_sanitization_middleware.py:362follow the same pattern. The documented{id}__userid-swap can be kept exactly as-is; only the field preservation changes.Environment
827acf5(2026-09-27)