Feature Request
Problem
In the Python SDK, agent lifecycle callback parameters (before_agent_callback, after_agent_callback, before_model_callback, etc.) accept only a single callable. When multiple concerns need to run at the same hook point (e.g., logging + data injection before an agent starts), developers are forced to write a manual composite wrapper:
async def before_portfolio_analyzer(callback_context: CallbackContext) -> None:
log_agent_start(callback_context)
await inject_portfolio_data(callback_context)
portfolio_analyzer = LlmAgent(
before_agent_callback=before_portfolio_analyzer, # manual composition
)
This adds boilerplate and breaks the "1 callback = 1 responsibility" principle.
Existing precedent in Go SDK
The Go SDK already supports lists of callbacks:
llmCfg := llmagent.Config{
BeforeAgentCallbacks: []agent.BeforeAgentCallback{onBeforeAgent},
AfterAgentCallbacks: []agent.AfterAgentCallback{onAfterAgent},
BeforeModelCallbacks: []llmagent.BeforeModelCallback{onBeforeModel},
BeforeToolCallbacks: []llmagent.BeforeToolCallback{onBeforeTool},
}
Proposed solution
Accept either a single callable or a list of callables for all callback parameters in Python:
portfolio_analyzer = LlmAgent(
before_agent_callback=[log_agent_start, inject_portfolio_data],
before_model_callback=log_before_model, # single callable still works
)
Callbacks in the list would execute sequentially. If any callback returns a non-None value (e.g., Content to skip the agent), subsequent callbacks in the list should be skipped (short-circuit).
Benefits
- Parity with Go SDK — consistent behavior across SDKs
- Composability — mix and match reusable callback functions without manual wrappers
- Single Responsibility — each callback function stays focused on one concern
Environment
- Python SDK
- Affects:
BaseAgent (before_agent_callback, after_agent_callback) and LlmAgent (before_model_callback, after_model_callback, before_tool_callback, after_tool_callback)
Feature Request
Problem
In the Python SDK, agent lifecycle callback parameters (
before_agent_callback,after_agent_callback,before_model_callback, etc.) accept only a single callable. When multiple concerns need to run at the same hook point (e.g., logging + data injection before an agent starts), developers are forced to write a manual composite wrapper:This adds boilerplate and breaks the "1 callback = 1 responsibility" principle.
Existing precedent in Go SDK
The Go SDK already supports lists of callbacks:
Proposed solution
Accept either a single callable or a list of callables for all callback parameters in Python:
Callbacks in the list would execute sequentially. If any callback returns a non-
Nonevalue (e.g.,Contentto skip the agent), subsequent callbacks in the list should be skipped (short-circuit).Benefits
Environment
BaseAgent(before_agent_callback,after_agent_callback) andLlmAgent(before_model_callback,after_model_callback,before_tool_callback,after_tool_callback)