Skip to content

[FEATURE] Add plugins Parameter to Agent #1687

@github-actions

Description

@github-actions

Overview

Add a new plugins parameter to the Agent class that accepts a list of Plugin instances for extending agent functionality.

Parent Issue: #1636


Problem Statement

Currently, high-level features are added via the hooks parameter using HookProvider. A dedicated plugins parameter provides clearer semantics for composable agent extensions.

Proposed Solution

Add plugins: list[Plugin] | None = None parameter to Agent.__init__ that initializes plugins after the agent is constructed.


Implementation Requirements

Based on clarification discussion and repository analysis:

Technical Approach

  • Dependency: This issue requires [FEATURE] Plugin Protocol Definition #1689 (Plugin Protocol Definition) to be merged first
  • No Explicit Type Checking: Do not add isinstance checks for Plugin validation - let failures occur naturally when init_plugin is called
  • Async Handling: Use run_async() helper for async init_plugin methods (same pattern as existing Agent code)

Agent.init Changes

def __init__(
    self,
    # ... existing parameters ...
    plugins: list[Plugin] | None = None,
    hooks: list[HookProvider] | None = None,  # Keep for backwards compatibility
):
    # ... existing initialization ...
    
    # Register hooks (existing code)
    if hooks:
        for hook in hooks:
            self.hooks.add_hook(hook)
    
    # Initialize plugins after agent is fully constructed
    if plugins:
        for plugin in plugins:
            if inspect.iscoroutinefunction(plugin.init_plugin):
                # Handle async init_plugin
                run_async(lambda p=plugin: p.init_plugin(self))
            else:
                plugin.init_plugin(self)
    
    # Fire AgentInitializedEvent after plugins are initialized
    self.hooks.invoke_callbacks(AgentInitializedEvent(agent=self))

Plugin Initialization Order

  1. Built-in components initialized (model, tools, hooks registry)
  2. HookProviders registered (from hooks parameter - deprecated)
  3. Plugins initialized (from plugins parameter) ← New
  4. AgentInitializedEvent fired

Files to Modify

File Changes
src/strands/agent/agent.py Add plugins parameter, import Plugin, add initialization logic
tests/strands/agent/test_agent.py Add unit tests for plugins parameter

Import Requirements

  • Import Plugin from strands.hooks in agent.py (internal)
  • Add inspect import for iscoroutinefunction check

Example Usage

from strands import Agent, Plugin

class LoggingPlugin:
    name = "logging"
    
    def init_plugin(self, agent):
        agent.add_hook(lambda e: print("Model call starting"), BeforeModelCallEvent)

class SkillsPlugin:
    name = "skills"
    
    async def init_plugin(self, agent):
        # Async initialization supported
        agent.add_hook(self.inject_skills, BeforeModelCallEvent)
    
    def inject_skills(self, event):
        pass

# Clean, intuitive API
agent = Agent(
    plugins=[
        LoggingPlugin(),
        SkillsPlugin(),
    ]
)

Acceptance Criteria

  • plugins parameter added to Agent.__init__ with type list[Plugin] | None = None
  • Plugins are initialized with the agent instance after construction
  • Both sync and async init_plugin methods are handled correctly using run_async()
  • Plugin initialization happens after HookProvider registration and before AgentInitializedEvent is fired
  • Unit tests cover:
    • Plugin initialization with sync init_plugin
    • Plugin initialization with async init_plugin
    • Multiple plugins in order
    • Empty/None plugins parameter
  • Docstring for plugins parameter added to Agent.__init__
  • plugins parameter documented in Args section

Dependencies

Technical Notes

  • Follow existing patterns in Agent.__init__ for the hooks parameter
  • No runtime type validation needed - let duck typing handle invalid plugins
  • Use inspect.iscoroutinefunction() to detect async init_plugin methods
  • The run_async() helper is already imported in agent.py

Design References

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions