@@ -44,14 +44,16 @@ class SlidingWindowConversationManager(ConversationManager):
4444 invalid window states.
4545 """
4646
47- def __init__ (self , window_size : int = 40 ):
47+ def __init__ (self , window_size : int = 40 , should_truncate_results : bool = True ):
4848 """Initialize the sliding window conversation manager.
4949
5050 Args:
5151 window_size: Maximum number of messages to keep in the agent's history.
5252 Defaults to 40 messages.
53+ should_truncate_results: Truncate tool results when a message is too large for the model's context window
5354 """
5455 self .window_size = window_size
56+ self .should_truncate_results = should_truncate_results
5557
5658 def apply_management (self , agent : "Agent" ) -> None :
5759 """Apply the sliding window to the agent's messages array to maintain a manageable history size.
@@ -127,6 +129,19 @@ def reduce_context(self, agent: "Agent", e: Optional[Exception] = None) -> None:
127129 converted.
128130 """
129131 messages = agent .messages
132+
133+ # Try to truncate the tool result first
134+ last_message_idx_with_tool_results = self ._find_last_message_with_tool_results (messages )
135+ if last_message_idx_with_tool_results is not None and self .should_truncate_results :
136+ logger .debug (
137+ "message_index=<%s> | found message with tool results at index" , last_message_idx_with_tool_results
138+ )
139+ results_truncated = self ._truncate_tool_results (messages , last_message_idx_with_tool_results )
140+ if results_truncated :
141+ logger .debug ("message_index=<%s> | tool results truncated" , last_message_idx_with_tool_results )
142+ return
143+
144+ # Try to trim index id when tool result cannot be truncated anymore
130145 # If the number of messages is less than the window_size, then we default to 2, otherwise, trim to window size
131146 trim_index = 2 if len (messages ) <= self .window_size else len (messages ) - self .window_size
132147
@@ -151,3 +166,69 @@ def reduce_context(self, agent: "Agent", e: Optional[Exception] = None) -> None:
151166
152167 # Overwrite message history
153168 messages [:] = messages [trim_index :]
169+
170+ def _truncate_tool_results (self , messages : Messages , msg_idx : int ) -> bool :
171+ """Truncate tool results in a message to reduce context size.
172+
173+ When a message contains tool results that are too large for the model's context window, this function
174+ replaces the content of those tool results with a simple error message.
175+
176+ Args:
177+ messages: The conversation message history.
178+ msg_idx: Index of the message containing tool results to truncate.
179+
180+ Returns:
181+ True if any changes were made to the message, False otherwise.
182+ """
183+ if msg_idx >= len (messages ) or msg_idx < 0 :
184+ return False
185+
186+ message = messages [msg_idx ]
187+ changes_made = False
188+ tool_result_too_large_message = "The tool result was too large!"
189+ for i , content in enumerate (message .get ("content" , [])):
190+ if isinstance (content , dict ) and "toolResult" in content :
191+ tool_result_content_text = next (
192+ (item ["text" ] for item in content ["toolResult" ]["content" ] if "text" in item ),
193+ "" ,
194+ )
195+ # make the overwriting logic togglable
196+ if (
197+ message ["content" ][i ]["toolResult" ]["status" ] == "error"
198+ and tool_result_content_text == tool_result_too_large_message
199+ ):
200+ logger .info ("ToolResult has already been updated, skipping overwrite" )
201+ return False
202+ # Update status to error with informative message
203+ message ["content" ][i ]["toolResult" ]["status" ] = "error"
204+ message ["content" ][i ]["toolResult" ]["content" ] = [{"text" : tool_result_too_large_message }]
205+ changes_made = True
206+
207+ return changes_made
208+
209+ def _find_last_message_with_tool_results (self , messages : Messages ) -> Optional [int ]:
210+ """Find the index of the last message containing tool results.
211+
212+ This is useful for identifying messages that might need to be truncated to reduce context size.
213+
214+ Args:
215+ messages: The conversation message history.
216+
217+ Returns:
218+ Index of the last message with tool results, or None if no such message exists.
219+ """
220+ # Iterate backwards through all messages (from newest to oldest)
221+ for idx in range (len (messages ) - 1 , - 1 , - 1 ):
222+ # Check if this message has any content with toolResult
223+ current_message = messages [idx ]
224+ has_tool_result = False
225+
226+ for content in current_message .get ("content" , []):
227+ if isinstance (content , dict ) and "toolResult" in content :
228+ has_tool_result = True
229+ break
230+
231+ if has_tool_result :
232+ return idx
233+
234+ return None
0 commit comments