Skip to content

Commit 5e91ee4

Browse files
committed
refactor(hooks): fire Before/AfterReduceContextEvent inside reduce_context() implementations
Hooks were previously fired only from agent.py around the overflow-path call to reduce_context(). SlidingWindowConversationManager.apply_management() also calls reduce_context() for per-turn trimming, so hooks never fired on that path. Move hook invocations into reduce_context() in both SlidingWindowConversationManager and SummarizerConversationManager, using the synchronous invoke_callbacks(). Remove the now-redundant async calls from agent.py. Update tests accordingly.
1 parent d19f029 commit 5e91ee4

File tree

4 files changed

+12
-8
lines changed

4 files changed

+12
-8
lines changed

src/strands/agent/conversation_manager/sliding_window_conversation_manager.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
if TYPE_CHECKING:
77
from ...agent.agent import Agent
88

9-
from ...hooks import BeforeModelCallEvent, BeforeReduceContextEvent, AfterReduceContextEvent, HookRegistry
9+
from ...hooks import AfterReduceContextEvent, BeforeModelCallEvent, BeforeReduceContextEvent, HookRegistry
1010
from ...types.content import ContentBlock, Messages
1111
from ...types.exceptions import ContextWindowOverflowException
1212
from ...types.tools import ToolResultContent
@@ -171,7 +171,6 @@ def reduce_context(self, agent: "Agent", e: Exception | None = None, **kwargs: A
171171
Such as when the conversation is already minimal or when tool result messages cannot be properly
172172
converted.
173173
"""
174-
# Fire before event
175174
agent.hooks.invoke_callbacks(BeforeReduceContextEvent(agent=agent, exception=e))
176175

177176
messages = agent.messages
@@ -185,6 +184,7 @@ def reduce_context(self, agent: "Agent", e: Exception | None = None, **kwargs: A
185184
results_truncated = self._truncate_tool_results(messages, oldest_message_idx_with_tool_results)
186185
if results_truncated:
187186
logger.debug("message_index=<%s> | tool results truncated", oldest_message_idx_with_tool_results)
187+
agent.hooks.invoke_callbacks(AfterReduceContextEvent(agent=agent))
188188
return
189189

190190
# Try to trim index id when tool result cannot be truncated anymore
@@ -216,7 +216,6 @@ def reduce_context(self, agent: "Agent", e: Exception | None = None, **kwargs: A
216216
# Overwrite message history
217217
messages[:] = messages[trim_index:]
218218

219-
# Fire after event
220219
agent.hooks.invoke_callbacks(AfterReduceContextEvent(agent=agent))
221220

222221
def _truncate_tool_results(self, messages: Messages, msg_idx: int) -> bool:

src/strands/agent/conversation_manager/summarizing_conversation_manager.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
from ..._async import run_async
99
from ...event_loop.streaming import process_stream
10+
from ...hooks import AfterReduceContextEvent, BeforeReduceContextEvent
1011
from ...tools._tool_helpers import noop_tool
1112
from ...tools.registry import ToolRegistry
1213
from ...types.content import Message
1314
from ...types.exceptions import ContextWindowOverflowException
1415
from ...types.tools import AgentTool
1516
from .conversation_manager import ConversationManager
16-
from ...hooks import BeforeReduceContextEvent, AfterReduceContextEvent
1717

1818
if TYPE_CHECKING:
1919
from ..agent import Agent
@@ -136,7 +136,6 @@ def reduce_context(self, agent: "Agent", e: Exception | None = None, **kwargs: A
136136
Raises:
137137
ContextWindowOverflowException: If the context cannot be summarized.
138138
"""
139-
# Fire before event
140139
agent.hooks.invoke_callbacks(BeforeReduceContextEvent(agent=agent, exception=e))
141140

142141
try:
@@ -175,7 +174,6 @@ def reduce_context(self, agent: "Agent", e: Exception | None = None, **kwargs: A
175174
# Replace the summarized messages with the summary
176175
agent.messages[:] = [self._summary_message] + remaining_messages
177176

178-
# Fire after event
179177
agent.hooks.invoke_callbacks(AfterReduceContextEvent(agent=agent))
180178

181179
except Exception as summarization_error:

tests/strands/agent/test_agent.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2781,13 +2781,18 @@ async def test_stream_async_fires_before_and_after_reduce_context_hook_events(mo
27812781
),
27822782
]
27832783

2784+
# Seed messages so SlidingWindowConversationManager.reduce_context() can trim them.
2785+
agent.messages[:] = [
2786+
{"role": "user", "content": [{"text": "msg1"}]},
2787+
{"role": "assistant", "content": [{"text": "resp1"}]},
2788+
{"role": "user", "content": [{"text": "msg2"}]},
2789+
]
2790+
27842791
before_events = []
27852792
after_events = []
27862793
agent.add_hook(lambda e: before_events.append(e), BeforeReduceContextEvent)
27872794
agent.add_hook(lambda e: after_events.append(e), AfterReduceContextEvent)
27882795

2789-
agent.conversation_manager.reduce_context = unittest.mock.Mock()
2790-
27912796
await alist(agent.stream_async("hello"))
27922797

27932798
assert len(before_events) == 1

tests/strands/agent/test_summarizing_conversation_manager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55

66
from strands.agent.agent import Agent
7+
from strands.hooks.registry import HookRegistry
78
from strands.agent.conversation_manager.summarizing_conversation_manager import (
89
DEFAULT_SUMMARIZATION_PROMPT,
910
SummarizingConversationManager,
@@ -45,6 +46,7 @@ def __init__(self, summary_response="This is a summary of the conversation."):
4546
self.summary_response = summary_response
4647
self.system_prompt = None
4748
self.messages = []
49+
self.hooks = HookRegistry()
4850
self.model = Mock()
4951
self.model.stream = Mock(side_effect=lambda *a, **kw: _mock_model_stream(self.summary_response))
5052
self.call_tracker = Mock()

0 commit comments

Comments
 (0)