.NET: Introduce ToolResultReductionStrategy#4910
Open
arjendev wants to merge 1 commit intomicrosoft:mainfrom
Open
.NET: Introduce ToolResultReductionStrategy#4910arjendev wants to merge 1 commit intomicrosoft:mainfrom
arjendev wants to merge 1 commit intomicrosoft:mainfrom
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces a new .NET compaction strategy to reduce individual tool results (per-tool reducers) while preserving assistant tool-call + tool-result message structure, and refactors shared tool-group processing into a new base class used by both reduction and existing compaction.
Changes:
- Added
ToolResultReductionStrategyto apply per-toolFunc<string,string>reducers toFunctionResultContentwhile keeping tool-call group structure. - Added
ToolResultStrategyBaseto centralize the shared protected-group / eligibility / exclude+insert loop for tool-call-group strategies. - Refactored
ToolResultCompactionStrategyto inherit fromToolResultStrategyBaseand added unit tests for reduction behavior.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultStrategyBase.cs | New shared base class implementing the common “exclude + insert replacement group” loop for tool-call groups. |
| dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultReductionStrategy.cs | New strategy that reduces per-tool results while attempting to preserve tool-call message structure. |
| dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultCompactionStrategy.cs | Refactor to use the new base class; core behavior moved into TransformToolGroup. |
| dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/ToolResultReductionStrategyTests.cs | New unit tests validating reducer application, preservation semantics, and pipeline composition. |
dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultReductionStrategy.cs
Outdated
Show resolved
Hide resolved
dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultReductionStrategy.cs
Outdated
Show resolved
Hide resolved
dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultReductionStrategy.cs
Show resolved
Hide resolved
dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultReductionStrategy.cs
Show resolved
Hide resolved
f293963 to
75c6468
Compare
dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultReductionStrategy.cs
Show resolved
Hide resolved
dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultReductionStrategy.cs
Show resolved
Hide resolved
dotnet/src/Microsoft.Agents.AI/Compaction/ToolResultReductionStrategy.cs
Outdated
Show resolved
Hide resolved
75c6468 to
692a40d
Compare
692a40d to
1e29650
Compare
1e29650 to
4c88d46
Compare
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.
Motivation and Context
When using tools that return very large results — such as the M365 Retrieval API returning hundreds of thousands of tokens with relevance scores — there is currently no way for a framework user to selectively reduce individual tool results while preserving the tool-call message structure. The existing
ToolResultCompactionStrategycollapses entire tool-call groups into YAML summaries, which loses the assistant/tool message pairing needed for multi-turn tool interactions.This PR proposes a new
ToolResultReductionStrategythat allows users to register per-toolFunc<string, string>reducers — enabling them to deserialize, filter, sort, and re-serialize tool results within their own logic, while the framework handles the plumbing. I've submitted this as a PR (rather than an issue) to best convey the intent and proposed implementation for discussion.Description
New classes:
ToolResultStrategyBase— Abstract base class extracted from the shared logic between compaction and reduction. Implements a sealedCompactCoreAsyncwith a template-method pattern, delegating to two hooks:IsToolGroupEligible(group)— virtual, defaults totrueTransformToolGroup(group)— abstract, returns the transformed messagesToolResultReductionStrategy— Applies per-toolFunc<string, string>reducers toFunctionResultContentwhile preserving the original message structure (assistant tool-call + tool result messages). DefaultsminimumPreservedGroupsto0so reducers apply even to the current turn. Only tool-call groups containing at least one registered tool name are eligible; unregistered tools within a group are preserved as-is.Refactored:
ToolResultCompactionStrategy— Now extendsToolResultStrategyBaseinstead ofCompactionStrategydirectly, removing ~110 lines of duplicated loop/protect/eligibility logic. Behavior is unchanged.Tests:
ToolResultReductionStrategyTestscovering: trigger/target, reducer application, unregistered tool preservation, message structure preservation, current-turn reduction, minimum preserved groups, eligibility filtering, system message preservation, pre-excluded groups, no tool groups, pipeline composition, and a real-world RAG scenario (JSON chunks with relevance scores filtered within a character budget).Key design decisions:
minimumPreservedGroupsdefaultSummaryToolCallToolCallFormatterdelegateFunc<string, string>reducersBoth strategies compose naturally in a
PipelineCompactionStrategy— reduction first (shrink results), then compaction (collapse older groups).Contribution Checklist
ToolResultCompactionStrategybehavior is identical after the base-class refactor.