Skip to content

feat(plugins): improve plugin creation devex with @hook and @tool decorators#1740

Open
Unshure wants to merge 10 commits intomainfrom
agent-tasks/1739
Open

feat(plugins): improve plugin creation devex with @hook and @tool decorators#1740
Unshure wants to merge 10 commits intomainfrom
agent-tasks/1739

Conversation

@Unshure
Copy link
Member

@Unshure Unshure commented Feb 19, 2026

Motivation

Currently, plugin authors must manually register hooks in their init_plugin() method, which is verbose and error-prone:

class MyPlugin:
    name = "my-plugin"
    
    def init_plugin(self, agent: Agent) -> None:
        agent.add_hook(self.log_call, BeforeModelCallEvent)

This PR enables declarative hook registration using a @hook decorator, making plugin development more intuitive and reducing boilerplate:

class MyPlugin(Plugin):
    name = "my-plugin"

    @hook
    def log_call(self, event: BeforeModelCallEvent):
        print(event)

    @tool
    def printer(self, log: str):
        print(log)
        return "Printed log"

Resolves: #1739

Public API Changes

New @hook decorator

The @hook decorator marks methods for automatic registration:

from strands.plugins import Plugin, hook
from strands.hooks import BeforeModelCallEvent, AfterModelCallEvent

class MyPlugin(Plugin):
    name = "my-plugin"

    # Single event type - inferred from type hint
    @hook
    def on_model_call(self, event: BeforeModelCallEvent):
        print(event)

    # Union types - registers for multiple events
    @hook
    def on_any_model_event(self, event: BeforeModelCallEvent | AfterModelCallEvent):
        print(event)
``

@codecov
Copy link

codecov bot commented Feb 19, 2026

Codecov Report

❌ Patch coverage is 95.23810% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/strands/hooks/_type_inference.py 91.42% 3 Missing ⚠️
src/strands/plugins/plugin.py 93.75% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!


__all__ = [
"Plugin",
"hook",
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: would it also make sense to export tool from here? I'm thinking the devx of:

from strands.plugins import Plugin, hook, tool

class MyPlugin(Plugin):
   ...

I don't have a strong preference here though

@Unshure Unshure enabled auto-merge (squash) February 27, 2026 20:45

# Skip 'self' parameter for methods
first_param = params[0]
if first_param.name == "self" and len(params) > 1:
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: do we have validation check else where that hanldes edge cases like cls or self only method

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.

[FEATURE] Create @hook decorator for Plugins

4 participants