Before you start
Problem summary
UploadsMiddleware rebuilds the last HumanMessage from a subset of fields, silently dropping response_metadata and other message fields.
Affected area(s)
Agents / LangGraph — uploads middleware.
What happened?
UploadsMiddleware.before_agent() rewrites the last HumanMessage to prepend the <current_uploads> block. It constructs a fresh HumanMessage carrying only content, id, name, and additional_kwargs, so a message with response_metadata={"source": "gateway"} reaches the model with that field emptied.
This is the same partial-reconstruction family already fixed twice:
The reproduction matches #5822 and #5874: a message carrying response_metadata passes through the middleware and comes out with an empty dict. Reachability is the same as those two — normalize_input() delegates to convert_to_messages, which preserves caller-supplied response_metadata on a role: human entry, so an API client can put the field there without going through the UI.
Minimal reproduction:
from langchain_core.messages import HumanMessage
from deerflow.agents.middlewares.uploads_middleware import UploadsMiddleware
mw = UploadsMiddleware(base_dir=str(tmp_path))
message = HumanMessage(
content="check image",
id="msg-1",
additional_kwargs={"files": [{"filename": "img.png", "size": 3,
"path": "/mnt/user-data/uploads/img.png",
"status": "uploaded"}]},
response_metadata={"source": "gateway"},
)
result = mw.before_agent({"messages": [message]}, runtime)
result["messages"][-1].content # <current_uploads> block prepended — intended
result["messages"][-1].response_metadata # {} — the field was dropped
Expected behavior
Prepending the uploads context should change only content and the deliberately updated additional_kwargs. Other fields — response_metadata, id, name, and the message subclass — should survive the rebuild, while the original request message stays unchanged and unaliased.
Steps to reproduce
- Build a
HumanMessage whose additional_kwargs.files lists an uploaded file, and which carries response_metadata={"source": "gateway"}.
- Call
UploadsMiddleware.before_agent(state, runtime) with it as the last message.
- Inspect the returned message:
response_metadata is {} instead of {"source": "gateway"}.
Additional context
I have a fix plus a red test ready (backend/tests/test_uploads_middleware_core_logic.py, verified red on main and green on the branch); opening the PR next.
Before you start
main(827acf5).Problem summary
UploadsMiddlewarerebuilds the lastHumanMessagefrom a subset of fields, silently droppingresponse_metadataand other message fields.Affected area(s)
Agents / LangGraph — uploads middleware.
What happened?
UploadsMiddleware.before_agent()rewrites the lastHumanMessageto prepend the<current_uploads>block. It constructs a freshHumanMessagecarrying onlycontent,id,name, andadditional_kwargs, so a message withresponse_metadata={"source": "gateway"}reaches the model with that field emptied.This is the same partial-reconstruction family already fixed twice:
ThreadDataMiddleware— fixed in fix(middleware): preserve human message metadata #5823 (issue [bug] ThreadDataMiddleware drops HumanMessage response metadata #5822)InputSanitizationMiddleware— both sites fixed in fix(middleware): preserve metadata during input sanitization #5875 (issue [bug] Input sanitization drops human message metadata #5874)PiiRedactionMiddleware._process_request— fix(middleware): preserve message fields when PII redaction rebuilds a user message #5968 (issue [bug] PII redaction drops human message metadata #5967)UploadsMiddleware.before_agent— still unfixed onmainThe reproduction matches #5822 and #5874: a message carrying
response_metadatapasses through the middleware and comes out with an empty dict. Reachability is the same as those two —normalize_input()delegates toconvert_to_messages, which preserves caller-suppliedresponse_metadataon arole: humanentry, so an API client can put the field there without going through the UI.Minimal reproduction:
Expected behavior
Prepending the uploads context should change only
contentand the deliberately updatedadditional_kwargs. Other fields —response_metadata,id,name, and the message subclass — should survive the rebuild, while the original request message stays unchanged and unaliased.Steps to reproduce
HumanMessagewhoseadditional_kwargs.fileslists an uploaded file, and which carriesresponse_metadata={"source": "gateway"}.UploadsMiddleware.before_agent(state, runtime)with it as the last message.response_metadatais{}instead of{"source": "gateway"}.Additional context
I have a fix plus a red test ready (
backend/tests/test_uploads_middleware_core_logic.py, verified red onmainand green on the branch); opening the PR next.