fix(agent): strip orphan tool_calls in repair_message_sequence (#56980) - #56990
fix(agent): strip orphan tool_calls in repair_message_sequence (#56980)#56990liuhao1024 wants to merge 1 commit into
Conversation
When context compaction, partial session resume, or retry loops remove tool results from history, assistant messages with tool_calls may end up with no matching tool responses. Strict providers (DeepSeek v4, Kimi) reject such sequences with HTTP 400: "insufficient tool messages following tool_calls message". Add Pass 3 to repair_message_sequence: scan all tool messages for present tool_call_ids, then strip any tool_calls whose ids are absent. Preserves assistant text content and keeps calls that do have results. Fixes NousResearch#56980
|
Thanks for digging into this @liuhao1024 — clean patch, tests, and a correct read of the symptom. But we're going to close this without merging, because the outgoing API path already handles this case, and doing it in The orphan-tool_calls case is already fixed before every request. Right before each API call, I verified this end-to-end against the exact scenario from #56980 (trailing Why Pass 3 is also the wrong shape: If you can still reproduce the 400 on latest |
What does this PR do?
Adds Pass 3 to
repair_message_sequencethat strips orphantool_callsfrom assistant messages whosetool_call_ids have no matchingtoolresult messages in the sequence. This prevents HTTP 400 "insufficient tool messages following tool_calls message" from strict providers (DeepSeek v4, Kimi) when context compaction, partial session resume, or retry loops leave dangling tool-call references.Related Issue
Fixes #56980
Type of Change
Changes Made
agent/agent_runtime_helpers.py: Added Pass 3 inrepair_message_sequence— builds a set of alltool_call_ids present intoolmessages, then stripstool_callsentries from assistant messages whose ids are absent. Keeps assistant text content intact; only removes the orphan calls.tests/run_agent/test_message_sequence_repair.py: Added 3 tests covering the new pass — orphan tool_calls at sequence end, parallel tool_calls with partial results missing, and no-op when all tool_calls have matching results.How to Test
python -m pytest tests/run_agent/test_message_sequence_repair.py -v— all 28 tests should pass, including the 3 new ones (test_repair_strips_orphan_tool_calls_at_end,test_repair_strips_orphan_parallel_tool_calls,test_repair_preserves_complete_tool_calls).test_repair_strips_orphan_tool_calls_at_endwhich simulates the exact scenario from the issue: an assistant message withtool_callsat the end of the sequence with no matching tool result.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A