Skip to content

Plugin callbacks (before_agent, after_agent, before_model, after_model, etc.) not being invoked by InMemoryRunner #4464

@sssahas

Description

@sssahas

Describe the Bug:

Plugin callbacks (before_agent, after_agent, before_model, after_model, on_user_message, before_run, after_run) are not being invoked by InMemoryRunner, despite being registered and the documentation stating they should be global and have precedence over agent callbacks. Only tool callbacks fire when passed directly to the agent.

Steps to Reproduce:

  1. Create a plugin extending BasePlugin with callback methods (before_agent, before_model, etc.)
  2. Register the plugin with InMemoryRunner(agent=root_agent, plugins=[MyPlugin()])
  3. Run the agent using adk run or runner.run_async()
  4. Observe that only tool callbacks fire, while agent and model callbacks never execute

Expected Behavior:

According to ADK documentation, plugin callbacks should be invoked automatically by the runner at various lifecycle points:

on_user_message_callback - when user sends a message
before_run_callback / after_run_callback - when runner starts/completes
before_agent_callback / after_agent_callback - when agent executes
before_model_callback / after_model_callback - when LLM is called
before_tool_callback / after_tool_callback - when tool executes
Observed Behavior: Only before_tool_callback and after_tool_callback fire (when passed directly to the agent). All other plugin callbacks registered on the runner never fire. The plugin initializes successfully but its lifecycle callbacks are never invoked.

Environment Details:

ADK Library Version (pip show google-adk): 1.25.0
Desktop OS: Linux
Python Version: 3.11/3.12
Model Information: Using Bedrock model via LiteLLM

Logs:

✅ [PLUGIN] Auditor plugin initialized
🛠️ [AUDIT] Before tool callback fired for consult_receptionist!
✅ [AUDIT] After tool callback fired for consult_receptionist!
Note: Agent and model callbacks never appear in logs despite being implemented.

Minimal Reproduction Code:

from google.adk.plugins.base_plugin import BasePlugin
from google.adk.agents.callback_context import CallbackContext
from google.adk.runners import InMemoryRunner
from google.adk.agents import LlmAgent

class AuditorPlugin(BasePlugin):
    def __init__(self):
        super().__init__(name="auditor_plugin")
        print("✅ [PLUGIN] Auditor plugin initialized")

    async def before_agent_callback(self, *, agent, callback_context: CallbackContext) -> None:
        print(f"🤖 [AUDIT] Before agent callback fired for {agent.name}!")

    async def after_agent_callback(self, *, agent, callback_context: CallbackContext) -> None:
        print(f"✅ [AUDIT] After agent callback fired for {agent.name}!")

    async def before_model_callback(self, *, callback_context: CallbackContext, llm_request) -> None:
        print("🧠 [AUDIT] Before model callback fired!")

    async def after_model_callback(self, *, callback_context: CallbackContext, llm_request) -> None:
        print("✅ [AUDIT] After model callback fired!")
    
    root_agent = LlmAgent(
        name="test_agent",
        model="gemini-2.0-flash",
        instruction="Test agent",
        tools=[],
    )
    
    runner = InMemoryRunner(
        agent=root_agent,
        plugins=[AuditorPlugin()],
    )

Run the agent - observe that only plugin init prints, but agent/model callbacks never fire

How often has this issue occurred?:
Always (100%)

Metadata

Metadata

Assignees

Labels

core[Component] This issue is related to the core interface and implementation

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions