Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(autocontext): preserve tool_calls/tool_result pairing during large message offloading#1042

Merged
LearningGp merged 2 commits into
agentscope-ai:mainfrom
shiyiyue1102:main
Mar 27, 2026
Merged

fix(autocontext): preserve tool_calls/tool_result pairing during large message offloading#1042
LearningGp merged 2 commits into
agentscope-ai:mainfrom
shiyiyue1102:main

Conversation

@shiyiyue1102
Copy link
Copy Markdown
Contributor

@shiyiyue1102 shiyiyue1102 commented Mar 25, 2026

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

…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]>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown

codecov Bot commented Mar 25, 2026

Codecov Report

❌ Patch coverage is 90.90909% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ope/core/memory/autocontext/AutoContextMemory.java 90.90% 2 Missing and 3 partials ⚠️

📢 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]>
Copy link
Copy Markdown
Collaborator

@LearningGp LearningGp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@LearningGp LearningGp merged commit a79da27 into agentscope-ai:main Mar 27, 2026
6 checks passed
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants