feat(hooks): add BeforeReduceContextEvent and AfterReduceContextEvent hook events#2063
feat(hooks): add BeforeReduceContextEvent and AfterReduceContextEvent hook events#2063Zelys-DFKH wants to merge 4 commits intostrands-agents:mainfrom
Conversation
| await self.hooks.invoke_callbacks_async(BeforeReduceContextEvent(agent=self, exception=e)) | ||
|
|
||
| # Try reducing the context size and retrying | ||
| self.conversation_manager.reduce_context(self, e=e) |
There was a problem hiding this comment.
This is not the only occurence where reduce_context is called. It's also called by ConversationManager's builtin apply_management() method in two of the Conversation Manager's implementations.
Considering calling the hook event in reduce_context() method.
Also, please close this PR if you are an AI to prevent AI slop
There was a problem hiding this comment.
Good catch. Fixed in the latest push — hooks are now fired from inside reduce_context() in both SlidingWindowConversationManager and SummarizerConversationManager (using the sync invoke_callbacks), so all call paths including apply_management() are covered. Removed the now-redundant async calls from agent.py.
8e32040 to
d19f029
Compare
|
Addressed the feedback: moved hook firing inside |
Fires BeforeReduceContextEvent before reduce_context() and AfterReduceContextEvent after it returns, giving observability plugins a way to detect and measure context compaction without polling or inspecting internals. Closes strands-agents#2048
Fire BeforeReduceContextEvent and AfterReduceContextEvent inside each reduce_context() implementation instead of at the call site in the agent's event loop. This ensures hooks are triggered for all reduce_context calls: - From ContextWindowOverflowException handling in event loop - From ConversationManager.apply_management() for proactive reduction Hook callbacks are now synchronous (invoke_callbacks) since reduce_context is synchronous and may be called from sync contexts. Files modified: - agent.py: Remove hook firing from _execute_event_loop_cycle() - sliding_window_conversation_manager.py: Add sync hook calls - summarizing_conversation_manager.py: Add sync hook calls - null_conversation_manager.py: Add sync before hook Addresses reviewer feedback: hooks now fire regardless of reduction source.
…ntext() 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.
…ssages list reduce_context() now fires hook events via agent.hooks, so the agent argument must be a proper Agent object, not a raw messages list.
5e91ee4 to
5c12dcd
Compare
|
Rebased onto latest main to incorporate #2087's sliding window changes. All tests pass. |
Description
Moved hook event firing from the agent's event loop into each
reduce_context()implementation. Hooks now fire whenever context reduction occurs—whether from overflow in the event loop or from proactive management viaConversationManager.apply_management().Hook callbacks use synchronous invocation since
reduce_context()is synchronous and can be called from sync contexts.Changes
BeforeReduceContextEventandAfterReduceContextEventfiring fromAgent._execute_event_loop_cycle()reduce_context()implementations:SlidingWindowConversationManager: fires before trimming, after messages updatedSummarizingConversationManager: fires before summarization starts, after messages replacedNullConversationManager: fires before raising exceptionRelated Issues
Fixes #2048
Testing
The existing test
test_stream_async_fires_before_and_after_reduce_context_hook_eventsvalidates hooks fire from overflow. All 425 existing tests pass. Additional test coverage should verify hooks fire fromapply_management()(proactive reduction).