MCPcopy Index your code
hub / github.com/google/adk-python / PluginManager

Class PluginManager

src/google/adk/plugins/plugin_manager.py:60–371  ·  view source on GitHub ↗

Manages the registration and execution of plugins. The PluginManager is an internal class that orchestrates the invocation of plugin callbacks at key points in the SDK's execution lifecycle. It maintains a list of registered plugins and ensures they are called in the order they were registe

Source from the content-addressed store, hash-verified

58
59
60class PluginManager:
61 """Manages the registration and execution of plugins.
62
63 The PluginManager is an internal class that orchestrates the invocation of
64 plugin callbacks at key points in the SDK's execution lifecycle. It maintains
65 a list of registered plugins and ensures they are called in the order they
66 were registered.
67
68 The core execution logic implements an "early exit" strategy: if any plugin
69 callback returns a non-`None` value, the execution of subsequent plugins for
70 that specific event is halted, and the returned value is propagated up the
71 call stack. This allows plugins to short-circuit operations like agent runs,
72 tool calls, or model requests.
73 """
74
75 def __init__(
76 self,
77 plugins: Optional[List[BasePlugin]] = None,
78 close_timeout: float = 5.0,
79 ):
80 """Initializes the plugin service.
81
82 Args:
83 plugins: An optional list of plugins to register upon initialization.
84 close_timeout: The timeout in seconds for each plugin's close method.
85 """
86 self.plugins: List[BasePlugin] = []
87 self._close_timeout = close_timeout
88 self._skip_closing_plugins = False
89 if plugins:
90 for plugin in plugins:
91 self.register_plugin(plugin)
92
93 def set_skip_closing_plugins(self, value: bool) -> None:
94 """Controls whether `close()` will tear down the registered plugins.
95
96 Set to True when the plugins are owned by another component (e.g. a parent
97 `Runner` whose plugin list this manager is sharing). When set, subsequent
98 calls to `close()` become a no-op so the shared plugins are not torn down
99 while still in use.
100
101 Args:
102 value: True to skip closing the plugins; False (default) to close them
103 normally.
104 """
105 self._skip_closing_plugins = value
106
107 def register_plugin(self, plugin: BasePlugin) -> None:
108 """Registers a new plugin.
109
110 Args:
111 plugin: The plugin instance to register.
112
113 Raises:
114 ValueError: If a plugin with the same name is already registered.
115 """
116 if any(p.name == plugin.name for p in self.plugins):
117 raise ValueError(f"Plugin with name '{plugin.name}' already registered.")

Calls

no outgoing calls