Skip to content

Conversation

@zastrowm
Copy link
Member

@zastrowm zastrowm commented Dec 19, 2025

Description

Allow conversation managers to act as hook providers and add an option to built-in conversation managers to proactively apply message management during the agent loop execution.

Use that functionality to add an option to SlidingWindowConversationManager to allow per_turn management application

Addresses #509

Public API Changes

manager = SlidingWindowConversationManager(
    window_size=40,
    should_truncate_results=True,
    per_turn=True  # or per_turn=5 for every 5 model calls
)
# Can be changed dynamically
manager.per_turn = 3

Default per_turn=False maintains current behavior

Parameter Options

  • per_turn=False (default): Current behavior - management only at end
  • per_turn=True: Apply management before every model call
  • per_turn=N (int): Apply management before every N model calls

ConversationManager as HookProviders

ConversationManager now provides a register_hooks() method that subclasses can override to integrate with the agent's event lifecycle and at initialization time, it will have it's hook subscribed to. SlidingWindowConversationManager leverages this underneath the hood.

Added @runtime_checkable to HookProvider protocol to enable proper isinstance checks.

Before:

class CustomConversationManager(ConversationManager):
    def apply_management(self, agent, **kwargs):
        # Only called at end of execution
        pass

After:

class CustomConversationManager(ConversationManager):
    def register_hooks(self, registry, **kwargs):
        super().register_hooks(registry, **kwargs)
        # Can now respond to lifecycle events
        registry.add_callback(BeforeModelCallEvent, self._on_before_model_call)
        registry.add_callback(AfterToolCallEvent, self._on_after_tool_call)
    
    def apply_management(self, agent, **kwargs):
        # Still called at end of execution
        pass

We guide folks to call super().register_hooks(registry, **kwargs) because in the future I'd like to re-implement the default conversation-management behavior (where apply_management and reduce_context is called) using hooks - if we do that and folks aren't calling super().register_hooks(registry, **kwargs) then once we migrate to hooks then derived classes that do not call super().register_hooks would lose the default behavior which would be a breaking change.

Related Issues

#509

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

  • I ran hatch run prepare

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • 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.

Allow conversation managers to act as hook providers and add an option to built-in conversation managers to proactively apply message management during the agent loop execution.

Use that functionality to add an option to SlidingWindowConversationManager to allow per_turn management application

Fixes strands-agents#509
@codecov
Copy link

codecov bot commented Dec 19, 2025

Codecov Report

❌ Patch coverage is 97.22222% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...ion_manager/sliding_window_conversation_manager.py 96.55% 0 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!


# Validate per_turn parameter
# Note: Must check bool before int since bool is a subclass of int in Python
if not isinstance(per_turn, bool) and isinstance(per_turn, int) and per_turn <= 0:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In our SDK I don't think we validate input parameters

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we against it or just that this is contrary to other places?

Personally I don't see a problem with enforcing it for new things, but can remove it if we want

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While validation wouldn't hurt, we intentionally avoid it. @pgrayy mentioned it will make SDK cumbersome, and yes, if we do it here, we can do else where.

Long term plan is to allow every ConversationManager to add hooks as needed
self.hooks.add_hook(self._session_manager)

# Allow conversation_managers to subscribe to hooks
self.hooks.add_hook(self.conversation_manager)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

session manager uses conversation manager, right? Should we put conversation_manager hooks before it in case there is something the conversation manager needs to do earlier?

Also what are you thinking for documentation? It is a bit unclear now that conversation manager is now both called manually and via hooks

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, what is the story for transitioning from "manual" conversation management, meaning conversation_manager.apply_management, to using only hooks.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we put conversation_manager hooks before it in case there is something the conversation manager needs to do earlier?

I actually think we want to do it after, in case the conversation_manager wants to trim after the session-manager


Also what are you thinking for documentation?

I will have to do a docs PR for this; specifically I need to update it to account for the per_turn parameter AND conversation managers being able to register for hooks.

Also, what is the story for transitioning from "manual" conversation management, meaning conversation_manager.apply_management, to using only hooks.

I'll cut an issue - though IMHO it's low priority

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.

3 participants