The plugin system provides a modular, extensible architecture for intercepting and modifying agent execution behavior. Plugins enable developers to implement cross-cutting concerns such as logging, monitoring, request filtering, response transformation, and custom business logic without modifying agent code directly.
For detailed information about specific callback methods and their signatures, see Callbacks and Hooks. This page focuses on the plugin architecture, lifecycle, and registration mechanisms.
The ADK plugin system is built around three core components: BasePlugin, PluginManager, and the Runner integration layer.
Sources: src/google/adk/runners.py57-58 src/google/adk/runners.py127-128 src/google/adk/runners.py720-850
Plugins are registered when constructing a Runner instance, either directly via the deprecated plugins parameter or through the App object:
Sources: src/google/adk/runners.py140-209 src/google/adk/runners.py239-269
Plugins participate in the complete agent execution lifecycle through a series of callback hooks. The Runner._exec_with_plugin() method orchestrates this lifecycle:
| Phase | Callback Method | Purpose | Can Modify |
|---|---|---|---|
| 1. User Message | on_user_message_callback | Transform or intercept user input before processing | User message content |
| 2. Before Run | before_run_callback | Inspect context, perform setup, optionally short-circuit execution | Can return early exit response |
| 3. Event Stream | on_event_callback | Transform or filter each event as it's yielded | Individual events |
| 4. After Run | after_run_callback | Cleanup, finalization, metrics collection | None (side effects only) |
Sources: src/google/adk/runners.py720-850
When multiple plugins are registered, the PluginManager chains their callbacks in registration order:
on_user_message_callback: First plugin to return non-None short-circuits the chainbefore_run_callback: All plugins execute in sequence; first to return types.Content triggers early exiton_event_callback: Each plugin receives the result from the previous plugin in the chainafter_run_callback: All plugins execute in sequence for cleanupSources: tests/unittests/test_runners.py136-189
Sources: tests/unittests/test_runners.py875-886
Sources: src/google/adk/runners.py172-173 src/google/adk/runners.py239-244
The plugin_close_timeout parameter controls how long the runner waits for plugins to close gracefully:
Sources: src/google/adk/runners.py151 tests/unittests/test_runners.py844-854
All plugins must inherit from BasePlugin and implement the callback methods they need:
Sources: src/google/adk/runners.py57 tests/unittests/test_runners.py136-189
This example from the test suite demonstrates a plugin that intercepts and modifies user messages:
Sources: tests/unittests/test_runners.py136-161
Sources: tests/unittests/test_runners.py172-188
Plugins receive an InvocationContext object that provides access to:
| Context Property | Type | Description |
|---|---|---|
invocation_id | str | Unique identifier for this invocation |
agent | BaseAgent | The agent being executed |
user_content | Optional[types.Content] | The user's message content |
run_config | RunConfig | Configuration for this run |
plugin_manager | PluginManager | Reference to the plugin manager |
session_service | BaseSessionService | Session persistence service |
artifact_service | Optional[BaseArtifactService] | Artifact storage service |
memory_service | Optional[BaseMemoryService] | Memory service |
credential_service | Optional[BaseCredentialService] | Credential service |
Sources: tests/unittests/test_runners.py150 tests/unittests/test_runners.py164-170
The PluginManager coordinates all plugin callbacks and handles the chain-of-responsibility pattern:
Sources: src/google/adk/runners.py199-201 src/google/adk/runners.py739-850
Plugins should implement the close() method to release resources:
The Runner.close() method delegates to PluginManager.close() to ensure all plugins are cleaned up:
Sources: tests/unittests/test_runners.py833-841
The Runner class integrates plugins at initialization and throughout the execution lifecycle:
Sources: src/google/adk/runners.py186-201
The _exec_with_plugin() method wraps the entire agent execution:
| Step | Line Reference | Action |
|---|---|---|
| 1 | runners.py741-759 | Run before_run_callback, handle early exit |
| 2 | runners.py778-831 | Execute agent, stream events, buffer transcriptions in live mode |
| 3 | runners.py833-843 | Run on_event_callback for each event, yield modified events |
| 4 | runners.py847-850 | Run after_run_callback for cleanup |
Sources: src/google/adk/runners.py720-850
Plugins can track execution metrics without modifying agent code:
Plugins can validate or transform user input:
Sources: tests/unittests/test_runners.py802-820
Plugins can modify agent responses before they reach the user:
Sources: tests/unittests/test_runners.py822-831
Plugins work with RunConfig.custom_metadata to propagate request-level metadata through the execution:
The _apply_run_config_custom_metadata() function merges run-level metadata into events, with event-level metadata taking precedence:
Sources: src/google/adk/runners.py89-99 tests/unittests/test_runners.py729-761
Plugins should handle errors gracefully to avoid breaking agent execution. The PluginManager provides isolation between plugins, ensuring that one plugin's failure doesn't affect others. However, plugin authors should implement appropriate error handling:
In live streaming mode (runner.run_live()), event buffering occurs to maintain proper ordering of transcriptions and function calls. Plugins receive events in the correct order after buffering:
| Event Type | Buffering Behavior |
|---|---|
| Partial transcriptions | Not appended to session, not buffered |
| Complete transcriptions | Appended to session after completion |
| Function calls | Buffered if transcription in progress |
| Function responses | Buffered if transcription in progress |
| Audio events | Handled specially (inline data not saved) |
Sources: src/google/adk/runners.py766-826
Direct plugin registration via the Runner constructor's plugins parameter is deprecated. Use the App object instead:
Sources: src/google/adk/runners.py239-244
Refresh this wiki
This wiki was recently refreshed. Please wait 6 days to refresh again.