feat: implement Plugin system to replace HookProvider#619
feat: implement Plugin system to replace HookProvider#619zastrowm wants to merge 2 commits intostrands-agents:mainfrom
Conversation
003ea55 to
48330ad
Compare
There was a problem hiding this comment.
Assessment: Request Changes
Excellent progress! The API has been refined significantly and addresses the previous naming feedback.
Review Summary
Improvements in this iteration:
- ✅ Renamed
initPlugin→initAgent(aligns with Python SDK'sinit_agent) - ✅ Simplified API by removing
PluginAgentinterface (plugins receiveAgentDatadirectly) - ✅ Extended
AgentDatainterface withtoolRegistryandaddHook - ✅ Added
MultiAgentPluginfor orchestrator extensibility - ✅ All 1,261 tests passing
Design improvements:
- Base
Plugin.initAgent()auto-registers tools fromgetTools()- clean pattern AgentDatainterface provides exactly what plugins need
Blocking Issue: The PR description is still missing a "Documentation PR" section. Please add either:
- A link to a documentation PR at
https://github.com/strands-agents/docs/pull/..., OR - A justification explaining why documentation updates are not required (e.g., "Documentation not required - TypeScript SDK not yet publicly released")
The implementation is solid and ready to merge once the documentation requirement is addressed!
48330ad to
3b00f89
Compare
| * | ||
| * For strands-vended plugins, names should be prefixed with `strands:`. | ||
| */ | ||
| abstract get name(): string |
There was a problem hiding this comment.
Any reason why this is a function and not a variable?
There was a problem hiding this comment.
It's the only way to make it abstract; because this is a class, that's the only way to enforce that it's required
| /** | ||
| * The tool registry for registering tools with the agent. | ||
| */ | ||
| readonly toolRegistry: ToolRegistry |
There was a problem hiding this comment.
Generally curious about what belongs on AgentData? Does system prompt or model belong here too?
There was a problem hiding this comment.
Anything that is our "generic" agent; in my mind that's anything that would be common between Agent and BiDiAgent;
model would not be included for that reason
There was a problem hiding this comment.
Up until now I've been conservative and only adding things to AgentData when we're using it - so that if/when we get BiDi agent we don't have any breaking changes
# Conflicts: # src/index.ts # src/session/__tests__/session-manager.test.ts # src/session/session-manager.ts
Motivation
The Python SDK recently implemented Plugins as a replacement for HookProvider. Given that TypeScript hasn't shipped yet, we can implement Plugins without backward compatibility concerns around HookProvider.
Plugins provide a more structured approach to extending agent functionality with a required unique name for identification, logging, and duplicate prevention. The
initAgent(agent)method is where plugins callagent.addHook()to register callbacks, andgetTools()enables auto-registering tools with the agent.Resolves #42
Public API Changes
AgentConfignow acceptsplugins: Plugin[]instead ofhooks: HookProvider[]:Creating plugins follows a class-based pattern matching the Python SDK:
Runtime hook registration is now done via
agent.addHook(), which returns a cleanup function:Plugins can provide tools via
getTools(), which are auto-registered during plugin initialization:The same pattern applies to multi-agent orchestrators via
MultiAgentPlugin.SwarmOptionsnow acceptsplugins: MultiAgentPlugin[]instead ofhooks: HookProvider[], and plugins register callbacks viainitMultiAgent(orchestrator):HookProvideris no longer exported.agent.hooksandswarm.hooksare now private — useagent.addHook()/swarm.addHook()for runtime hook registration.PluginRegistryandMultiAgentPluginRegistryare internal. Strands-vended plugin names are prefixed withstrands:(e.g.,strands:sliding-window-conversation-manager).Documentation PR
Will update after we get some iterations/review here