fix(autocontext): preserve tool_calls/tool_result pairing during large message offloading#1042
Merged
Merged
Conversation
…e payload offloading In offloadingLargePayload (Strategy 2/3), messages were offloaded as plain TextBlock stubs regardless of role, which caused two bugs: 1. ASSISTANT messages with ToolUseBlock (tool_calls) were stripped of their ToolUseBlock when offloaded. The subsequent TOOL result messages then had no preceding tool_calls message, triggering DashScope 400: 'messages with role tool must be a response to a preceding message with tool_calls'. 2. TOOL result messages were never actually compressed because Msg.getTextContent() only extracts top-level TextBlocks and returns empty string for TOOL messages (whose content is a ToolResultBlock). Fix: - Skip ASSISTANT+ToolUseBlock messages entirely; these pairs are handled exclusively by Strategy 1 (summaryToolsMessages). - Handle TOOL result messages separately: extract output text from ToolResultBlock.output for size comparison, offload the original message, then rebuild a replacement that preserves the ToolResultBlock shell (id + name) while replacing only the output text with the offload hint. This keeps tool_call_id/name intact for API formatters. Add three regression tests covering: - Strategy 2/3 must not offload ASSISTANT tool-call messages as plain stubs - Compressed TOOL result must preserve ToolResultBlock id and name - Full conversation integrity: every TOOL result must follow a tool-call assistant Change-Id: If62a76459d0bdb681cf04fbfd10c7df093b2ab8a Co-developed-by: Qoder <[email protected]>
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes AutoContext large-payload offloading (Strategies 2/3) to preserve valid tool-call / tool-result sequencing and to properly offload oversized TOOL result outputs without breaking API formatting constraints.
Changes:
- Skip offloading ASSISTANT tool-call messages (ToolUseBlock) during large payload offloading to avoid orphaning subsequent TOOL results.
- Add specialized offloading for TOOL result messages: offload based on ToolResultBlock output size, then rebuild a replacement message that keeps tool_call_id/name intact.
- Add regression tests for tool-call pairing and ToolResultBlock preservation during offloading.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| agentscope-extensions/agentscope-extensions-autocontext-memory/src/main/java/io/agentscope/core/memory/autocontext/AutoContextMemory.java | Updates Strategy 2/3 offloading to avoid stripping tool_calls and to offload TOOL results while preserving ToolResultBlock shell. |
| agentscope-extensions/agentscope-extensions-autocontext-memory/src/test/java/io/agentscope/core/memory/autocontext/AutoContextMemoryTest.java | Adds regression tests around tool_calls/tool_result integrity and ToolResultBlock id/name preservation during offloading. |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…arge tool results When compressing a large TOOL result message, the replacement ToolResultBlock was built without the original metadata, silently dropping semantic flags such as agentscope_suspended and any custom tool execution metadata written by tool implementations. Pass originalResult.getMetadata() to ToolResultBlock.of() so all metadata is carried through to the compressed stub. Change-Id: I54e37a5b7e1dee6ec2de8462450016f9a1bf1124 Co-developed-by: Qoder <[email protected]>
liangxingguang
pushed a commit
to liangxingguang/agentscope-java
that referenced
this pull request
May 21, 2026
…e message offloading (agentscope-ai#1042) In offloadingLargePayload (Strategy 2/3), messages were offloaded as plain TextBlock stubs regardless of role, which caused two bugs: 1. ASSISTANT messages with ToolUseBlock (tool_calls) were stripped of their ToolUseBlock when offloaded. The subsequent TOOL result messages then had no preceding tool_calls message, triggering DashScope 400: 'messages with role tool must be a response to a preceding message with tool_calls'. 2. TOOL result messages were never actually compressed because Msg.getTextContent() only extracts top-level TextBlocks and returns empty string for TOOL messages (whose content is a ToolResultBlock). Fix: - Skip ASSISTANT+ToolUseBlock messages entirely; these pairs are handled exclusively by Strategy 1 (summaryToolsMessages). - Handle TOOL result messages separately: extract output text from ToolResultBlock.output for size comparison, offload the original message, then rebuild a replacement that preserves the ToolResultBlock shell (id + name) while replacing only the output text with the offload hint. This keeps tool_call_id/name intact for API formatters. Add three regression tests covering: - Strategy 2/3 must not offload ASSISTANT tool-call messages as plain stubs - Compressed TOOL result must preserve ToolResultBlock id and name - Full conversation integrity: every TOOL result must follow a tool-call assistant Change-Id: If62a76459d0bdb681cf04fbfd10c7df093b2ab8a Co-developed-by: Qoder <[email protected]> ## AgentScope-Java Version [The version of AgentScope-Java you are working on, e.g. 1.0.9, check your pom.xml dependency version or run `mvn dependency:tree | grep agentscope-parent:pom`(only mac/linux)] ## Description [Please describe the background, purpose, changes made, and how to test this PR] ## Checklist Please check the following items before code is ready to be reviewed. - [ ] Code has been formatted with `mvn spotless:apply` - [ ] All tests are passing (`mvn test`) - [ ] Javadoc comments are complete and follow project conventions - [ ] Related documentation has been updated (e.g. links, examples, etc.) - [ ] Code is ready for review
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
In offloadingLargePayload (Strategy 2/3), messages were offloaded as plain TextBlock stubs regardless of role, which caused two bugs:
ASSISTANT messages with ToolUseBlock (tool_calls) were stripped of their ToolUseBlock when offloaded. The subsequent TOOL result messages then had no preceding tool_calls message, triggering DashScope 400: 'messages with role tool must be a response to a preceding message with tool_calls'.
TOOL result messages were never actually compressed because Msg.getTextContent() only extracts top-level TextBlocks and returns empty string for TOOL messages (whose content is a ToolResultBlock).
Fix:
Add three regression tests covering:
Change-Id: If62a76459d0bdb681cf04fbfd10c7df093b2ab8a
Co-developed-by: Qoder [email protected]
AgentScope-Java Version
[The version of AgentScope-Java you are working on, e.g. 1.0.9, check your pom.xml dependency version or run
mvn dependency:tree | grep agentscope-parent:pom(only mac/linux)]Description
[Please describe the background, purpose, changes made, and how to test this PR]
Checklist
Please check the following items before code is ready to be reviewed.
mvn spotless:applymvn test)