feat(agent): add add_hook convenience method for hook registration#1706
feat(agent): add add_hook convenience method for hook registration#1706
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
Assessment: Comment This PR adds a useful convenience method for hook registration that improves the developer experience. The implementation is functional and well-documented. Review Categories
The feature addresses a real need per issue #1686 and the type inference capability is a nice touch. Consider the API consistency feedback before merging. |
Add a public add_hook method to the Agent class that provides a cleaner API for registering hook callbacks. This is a convenience method that delegates to self.hooks.add_callback but provides a more discoverable interface for users. Changes: - Add Agent.add_hook(callback, event_type=None) method - Support inferring event_type from callback's type hint - Update HookRegistry.add_callback to support type inference - Raise clear ValueError when type cannot be inferred The method: - Accepts both sync and async callbacks - Uses proper type hints with TEvent and HookCallback - Includes comprehensive Google-style docstring with examples Resolves #1686
0198c55 to
5b8a264
Compare
|
/strands review the current pull request and add the @ overload changes proposed in the review |
Implementation of Review FeedbackI've implemented the Changes Made1.
2.
Verification
Diff# src/strands/hooks/registry.py
+from typing import (..., overload, ...)
+ @overload
+ def add_callback(self, callback: HookCallback[TEvent]) -> None: ...
+
+ @overload
+ def add_callback(self, event_type: type[TEvent], callback: HookCallback[TEvent]) -> None: ...
# src/strands/agent/agent.py
+from typing import (..., overload, ...)
+ @overload
+ def add_hook(self, callback: HookCallback[TEvent]) -> None: ...
+
+ @overload
+ def add_hook(self, callback: HookCallback[TEvent], event_type: type[TEvent]) -> None: ...Note: I don't have push access to apply these changes directly. The PR author will need to apply them. |
|
/strands review |
| agent.add_hook(typed_callback) | ||
|
|
||
| # Verify callback was registered by checking it gets invoked | ||
| agent("test prompt") |
There was a problem hiding this comment.
Issue: Test doesn't verify the callback was actually invoked.
This test registers a typed callback and calls the agent, but doesn't assert that the callback was actually called. Without this assertion, the test could pass even if the callback registration failed silently.
Suggestion: Add assertion to verify the callback was invoked:
def test_agent_add_hook_infers_event_type_from_callback():
from strands.hooks import BeforeModelCallEvent
agent = Agent(model=MockedModelProvider([{"role": "assistant", "content": [{"text": "response"}]}]))
callback_invoked = []
def typed_callback(event: BeforeModelCallEvent) -> None:
callback_invoked.append(event)
agent.add_hook(typed_callback)
agent("test prompt")
assert len(callback_invoked) == 1
assert isinstance(callback_invoked[0], BeforeModelCallEvent)|
Assessment: Approve The Review Status
The API design with type inference is a nice convenience feature. The |
|
Assessment: Approve The latest update (f552d46) makes a reasonable decision to keep Final Review Status
The PR is ready to merge. The remaining test feedback is minor and can be addressed in a follow-up if desired. |
|
/strands can you update the unit tests to address the review feedback, and increase the unit test coverage for the |
| """ | ||
| self.tool_registry.cleanup() | ||
|
|
||
| def add_hook( |
There was a problem hiding this comment.
This repurposes hook to mean "hook callback"; I think that makes sense, but call it out in the PR description as I want the release notes to reflect this new direction/terminology
| @overload | ||
| def add_callback(self, event_type: type[TEvent], callback: HookCallback[TEvent]) -> None: ... | ||
|
|
||
| def add_callback( |
There was a problem hiding this comment.
Can we just leave these apis alone and sort of deprecate the usage of it directly? That sets us up better I think long term to reduce confusion - e.g. don't use agent.hooks directly is the guidance
There was a problem hiding this comment.
Are you saying move the typehint checking to the agent class, or remove the method overloads I added above?
There was a problem hiding this comment.
Remove the method overloads you added here.
Not a blocker, but a possible way to simplify
|
/strands continue |
Motivation
Currently, registering a hook requires accessing the internal hooks registry:
This exposes implementation details and is less discoverable for users. Plugin authors and users who want to add hooks directly need a cleaner, more intuitive API.
Resolves #1686
Public API Changes
The Agent class now has an
add_hookmethod that provides a cleaner API for registering hook callbacks:The
add_callbackmethod onHookRegistryalso supports type inference:When
event_typeis not provided, it's inferred from the callback's first parameter type hint. AValueErroris raised with a helpful message if inference fails.Use Cases
hooksregistryinit_pluginimplementations can use this cleaner API