Pre-flight Checklist
Describe the Bug
Summary
When a StrandsAgent is constructed from a template Agent that has plugins (e.g. AgentSkills), those plugins are silently dropped from every per-thread StrandsAgentCore instance. The per-thread agents behave as if no plugins were configured.
Root cause
StrandsAgent.__init__ (in src/ag_ui_strands/agent.py) copies the template agent's configuration using _extract_agent_kwargs, which introspects Agent.__init__'s constructor signature and reads matching attributes off the agent instance. The problem is that Strands does not retain the plugins list as an attribute after Agent.__init__ completes — plugins are consumed during initialisation (hooks registered into HookRegistry, tools registered into ToolRegistry) and the original list is discarded. As a result, _extract_agent_kwargs finds nothing to copy, and the per-thread agents are created without any plugins.
The existing hooks= parameter on StrandsAgent was added to work around exactly this problem for hook callbacks — but it is an undiscoverable escape hatch that requires callers to reach into plugin internals, and it only works for plugins that register hooks. Plugins that only register tools have no workaround at all.
Steps to Reproduce
Steps to reproduce
from strands import Agent, AgentSkills
from ag_ui_strands import StrandsAgent
plugin = AgentSkills(skills=["./skills"])
agent = Agent(model=model, tools=[...], plugins=[plugin])
# Plugin is registered on the template agent correctly.
agui_agent = StrandsAgent(agent=agent, name="my-agent")
# Per-thread StrandsAgentCore instances have no AgentSkills plugin.
# The <available_skills> XML is never injected into the system prompt.
# The `skills` tool is absent.
# No warning or error is raised.
### Expected Behavior
Plugins attached to the template agent are reproduced faithfully in every per-thread StrandsAgentCore. The behaviour of a per-thread agent matches the template agent.
### Actual behaviour
Plugins are silently dropped. When using AgentSkills, the <available_skills> XML is never injected into the system prompt and the skills tool is not registered. No warning or error is raised.
### Environment
```text
ag_ui_strands-0.1.9
strands-agents-1.42.0
Screenshots
No response
Logs & Errors
Additional Context
Current workaround
Pass the plugin's internal hook callbacks via StrandsAgent(hooks=[...]) and explicitly include the plugin's tools in the template agent's tools list:
plugin = AgentSkills(skills=["./skills"])
agent = Agent(model=model, tools=[*my_tools, *plugin.tools], plugins=[plugin])
agui_agent = StrandsAgent(
agent=agent,
name="my-agent",
hooks=plugin.hooks, # must reach into plugin internals
)
This is undiscoverable, requires knowledge of plugin internals, and only works for plugins that register hooks.
Suggested fix
Add a plugins parameter to StrandsAgent.init (alongside the existing hooks parameter). When provided, call agent._plugin_registry.add_and_init(plugin) on each per-thread StrandsAgentCore immediately after it is created in run().
In src/ag_ui_strands/agent.py:
__init__ — accept and store plugins:
def __init__(
self,
agent: StrandsAgentCore,
name: str,
description: str = "",
config: "StrandsAgentConfig | None" = None,
hooks: "list | None" = None,
plugins: "list | None" = None, # <-- add this
):
...
self._hooks = list(hooks) if hooks else []
self._plugins = list(plugins) if plugins else [] # <-- add this
run() — initialise plugins on each new per-thread agent (after the existing StrandsAgentCore(...) call, around line 406):
self._agents_by_thread[thread_id] = StrandsAgentCore(
model=self._model,
system_prompt=self._system_prompt,
tools=self._tools,
session_manager=session_manager,
**core_kwargs,
)
# Initialise plugins on the fresh per-thread agent so their hooks
# and tools are registered exactly as they would be on the template.
for plugin in self._plugins:
self._agents_by_thread[thread_id]._plugin_registry.add_and_init(plugin)
This mirrors what Agent.__init__ does internally and requires no changes to Strands itself.
Pre-flight Checklist
Describe the Bug
Summary
When a
StrandsAgentis constructed from a templateAgentthat has plugins (e.g.AgentSkills), those plugins are silently dropped from every per-threadStrandsAgentCoreinstance. The per-thread agents behave as if no plugins were configured.Root cause
StrandsAgent.__init__(insrc/ag_ui_strands/agent.py) copies the template agent's configuration using_extract_agent_kwargs, which introspectsAgent.__init__'s constructor signature and reads matching attributes off the agent instance. The problem is that Strands does not retain thepluginslist as an attribute afterAgent.__init__completes — plugins are consumed during initialisation (hooks registered intoHookRegistry, tools registered intoToolRegistry) and the original list is discarded. As a result,_extract_agent_kwargsfinds nothing to copy, and the per-thread agents are created without any plugins.The existing
hooks=parameter onStrandsAgentwas added to work around exactly this problem for hook callbacks — but it is an undiscoverable escape hatch that requires callers to reach into plugin internals, and it only works for plugins that register hooks. Plugins that only register tools have no workaround at all.Steps to Reproduce
Steps to reproduce
Screenshots
No response
Logs & Errors
Additional Context
Current workaround
Pass the plugin's internal hook callbacks via StrandsAgent(hooks=[...]) and explicitly include the plugin's tools in the template agent's tools list:
This is undiscoverable, requires knowledge of plugin internals, and only works for plugins that register hooks.
Suggested fix
Add a plugins parameter to StrandsAgent.init (alongside the existing hooks parameter). When provided, call agent._plugin_registry.add_and_init(plugin) on each per-thread StrandsAgentCore immediately after it is created in run().
In src/ag_ui_strands/agent.py:
__init__— accept and store plugins:run()— initialise plugins on each new per-thread agent (after the existing StrandsAgentCore(...) call, around line 406):This mirrors what
Agent.__init__does internally and requires no changes to Strands itself.