fix(agents): normalize Command-wrapped tool results - #4977
fix(agents): normalize Command-wrapped tool results#4977BetterAndBetterII wants to merge 1 commit into
Conversation
Command-wrapped ToolMessages skipped result metadata and progress tracking, so error receipts could be recorded as success.
| continue | ||
| if tool_call_id and str(message.tool_call_id) != tool_call_id: | ||
| continue | ||
| normalize_tool_message(message) |
There was a problem hiding this comment.
[P1] Delegated task failures still get a success receipt through this path. _task_result_command carries the authoritative subagent_status (failed, cancelled, timed_out, or polling_timed_out) but leaves ToolMessage.status at LangChain's default success; its text starts with Task failed... / Task cancelled..., not the Error: prefix that normalize_tool_message recognizes. As a result this call stamps deerflow_tool_meta.status="success", and the outer receipt layer records success as well. I reproduced all four non-completed statuses with the production error-handling + receipt chain. Please derive task metadata from the structured subagent_status (or stamp it in _task_result_command) and add regression cases for these statuses, otherwise one of the principal Command producers named in #4976 remains unfixed.
willem-bd
left a comment
There was a problem hiding this comment.
The Command handling is correct for the newly covered setup_agent/view_image cases, but delegated task failures remain misclassified: failed, cancelled, timed-out, and polling-timeout task results all receive deerflow_tool_meta.status=success and therefore a success receipt. I reproduced this against the current head using the production error-handling and receipt chain. Please use the structured subagent_status when normalizing task results and add coverage for the non-completed statuses. Details are in the inline comment.
Closes #4976
Why
ToolMessages returned insideCommand(update={"messages": [...]})skip result normalization and progress tracking. Error payloads then get a defaultsuccessreceipt even though the content isError: ....What changed
normalize_tool_resultnow stamps matchingToolMessages inside aCommand(same metadata contract as a bare result; producer-supplied meta is left alone).ToolErrorHandlingMiddlewarepasses the currenttool_call_idinto that normalization.ToolProgressMiddlewareassesses the matching Command message instead of ignoring everyCommand.Receipts already match Command messages by
tool_call_id; they now see the normalized status.Surface area
langgraph.json, or prompt changeBug fix verification
backend/tests/test_command_tool_result_semantics.pymain, green on this branch: yessetup_agent/view_imagethrough the production middleware chain.Validation
20 new tests passed. Related suites passed except one pre-existing
test_build_subagent_runtime_middlewares_threads_app_config_to_llm_middlewareordering failure onmain.AI assistance
Tool(s) used: none
How you used it: n/a