Skip to content

feat(conversation-manager): add protected_messages to SlidingWindowConversationManager#2196

Open
ghgcm24 wants to merge 1 commit intostrands-agents:mainfrom
ghgcm24:feat/protected-messages-sliding-window
Open

feat(conversation-manager): add protected_messages to SlidingWindowConversationManager#2196
ghgcm24 wants to merge 1 commit intostrands-agents:mainfrom
ghgcm24:feat/protected-messages-sliding-window

Conversation

@ghgcm24
Copy link
Copy Markdown

@ghgcm24 ghgcm24 commented Apr 24, 2026

The sliding window can trim the first user message during context overflow recovery, causing the agent to lose its task prompt. Add a protected_messages parameter that preserves the first N messages from being removed during trimming.

Before trimming, the first protected_messages messages are snapshot-ted. The trim index is clamped to never fall inside the protected region, and any protected messages removed by aggressive overflow trimming are re-inserted afterward.

Default is 0 (no protection), preserving full backward compatibility.

Description

Motivation

SlidingWindowConversationManager can trim the first user message during context overflow recovery. When a tool returns a response large enough to overflow the context window, the manager removes
the oldest messages — including the initial task prompt — to make room. The model then sees tool results with no originating prompt and produces meaningless output.

PR #2087 fixed the structural issue (trimmed conversations now start with a role: "user" message), but the semantic issue remains: that user message may be a toolResult, not the original task
prompt. This is critical for batch/report workloads where the initial prompt defines the entire task.

Public API Changes

SlidingWindowConversationManager accepts a new optional protected_messages keyword argument:

# Before: first message can be trimmed during overflow recovery                                                                                                                                       
manager = SlidingWindowConversationManager(window_size=40)                                                                                                                                            
                                                                                                                                                                                                      
# After: first message is preserved regardless of trimming                                                                                                                                            
manager = SlidingWindowConversationManager(window_size=40, protected_messages=1)                                                                                                                      
                                                                                                                                                                                                      
- protected_messages=0 (default): no change in behavior, fully backward-compatible                                                                                                                    
- protected_messages=1: the first user message is never trimmed                                                                                                                                       
- protected_messages=N: the first N messages are never trimmed                                                                                                                                        
- Negative values raise ValueError                                                                                                                                                                    
                                                                                                                                                                                                      
The parameter is keyword-only and defaults to 0, so existing code is unaffected.                                                                                                                      
                                                                                                                                                                                                      
How it works:                                                                                                                                                                                         
                                                                                                                                                                                                      
1. Before trimming, snapshot the first protected_messages messages                                                                                                                                    
2. Clamp trim_index so it never falls inside the protected region                                                                                                                                     
3. After trimming, re-insert any protected messages that were removed (handles aggressive overflow trimming)                                                                                          
                                                                                                                                                                                                      
Use Cases                                                                                                                                                                                             
                                                                                                                                                                                                      
- Batch report agents: The initial prompt defines the entire task (e.g., "Generate the missing entries report"). If trimmed, the agent loses its purpose and produces generic output instead of the   
requested report.                                                                                                                                                                                     
- Long-running tool-heavy agents: Many tool calls accumulate large results. Context overflow trims from the oldest messages, which includes the task prompt. protected_messages=1 ensures the prompt  
survives.                                                                                                                                                                                             
- Multi-turn research agents: The first message often contains critical context (data sources, constraints, output format) that must persist throughout the conversation.                             
                                                                                                                                                                                                                                                                                                                                                                                                
## Related Issues

N/A

## Documentation PR

N/A

## Type of Change

New feature

## Testing

How have you tested the change?  Verify that the changes do not break functionality or introduce warnings in consuming repositories: agents-docs, agents-tools, agents-cli

- [X] I ran `hatch run prepare`

## Checklist
- [X] I have read the CONTRIBUTING document
- [X] I have added any necessary tests that prove my fix is effective or my feature works
- [X] I have updated the documentation accordingly
- [X] I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
- [X] My changes generate no new warnings
- [X] Any dependent changes have been merged and published

----

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

…nversationManager

The sliding window can trim the first user message during context overflow
recovery, causing the agent to lose its task prompt. Add a protected_messages
parameter that preserves the first N messages from being removed during
trimming.

Before trimming, the first protected_messages messages are snapshotted.
The trim index is clamped to never fall inside the protected region, and
any protected messages removed by aggressive overflow trimming are
re-inserted afterward.

Default is 0 (no protection), preserving full backward compatibility.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant