Types of Callbacks¶
The framework provides different types of callbacks that trigger at various stages of an agent's execution. Understanding when each callback fires and what context it receives is key to using them effectively.
Agent Lifecycle Callbacks¶
These callbacks are available on any agent that inherits from BaseAgent
(including LlmAgent
, SequentialAgent
, ParallelAgent
, LoopAgent
, etc).
Before Agent Callback¶
When: Called immediately before the agent's _run_async_impl
(or _run_live_impl
) method is executed. It runs after the agent's InvocationContext
is created but before its core logic begins.
Purpose: Ideal for setting up resources or state needed only for this specific agent's run, performing validation checks on the session state (callback_context.state) before execution starts, logging the entry point of the agent's activity, or potentially modifying the invocation context before the core logic uses it.
Note on the before_agent_callback
Example:
- What it Shows: This example demonstrates the
before_agent_callback
. This callback runs right before the agent's main processing logic starts for a given request. - How it Works: The callback function (
check_if_agent_should_run
) looks at a flag (skip_llm_agent
) in the session's state.- If the flag is
True
, the callback returns atypes.Content
object. This tells the ADK framework to skip the agent's main execution entirely and use the callback's returned content as the final response. - If the flag is
False
(or not set), the callback returnsNone
. This tells the ADK framework to proceed with the agent's normal execution (calling the LLM in this case).
- If the flag is
- Expected Outcome: You'll see two scenarios:
- In the session with the
skip_llm_agent: True
state, the agent's LLM call is bypassed, and the output comes directly from the callback ("Agent... skipped..."). - In the session without that state flag, the callback allows the agent to run, and you see the actual response from the LLM (e.g., "Hello!").
- In the session with the
- Understanding Callbacks: This highlights how
before_
callbacks act as gatekeepers, allowing you to intercept execution before a major step and potentially prevent it based on checks (like state, input validation, permissions).
After Agent Callback¶
When: Called immediately after the agent's _run_async_impl
(or _run_live_impl
) method successfully completes. It does not run if the agent was skipped due to before_agent_callback
returning content or if end_invocation
was set during the agent's run.
Purpose: Useful for cleanup tasks, post-execution validation, logging the completion of an agent's activity, modifying final state, or augmenting/replacing the agent's final output.
Note on the after_agent_callback
Example:
- What it Shows: This example demonstrates the
after_agent_callback
. This callback runs right after the agent's main processing logic has finished and produced its result, but before that result is finalized and returned. - How it Works: The callback function (
modify_output_after_agent
) checks a flag (add_concluding_note
) in the session's state.- If the flag is
True
, the callback returns a newtypes.Content
object. This tells the ADK framework to replace the agent's original output with the content returned by the callback. - If the flag is
False
(or not set), the callback returnsNone
. This tells the ADK framework to use the original output generated by the agent.
- If the flag is
- Expected Outcome: You'll see two scenarios:
- In the session without the
add_concluding_note: True
state, the callback allows the agent's original output ("Processing complete!") to be used. - In the session with that state flag, the callback intercepts the agent's original output and replaces it with its own message ("Concluding note added...").
- In the session without the
- Understanding Callbacks: This highlights how
after_
callbacks allow post-processing or modification. You can inspect the result of a step (the agent's run) and decide whether to let it pass through, change it, or completely replace it based on your logic.
LLM Interaction Callbacks¶
These callbacks are specific to LlmAgent
and provide hooks around the interaction with the Large Language Model.
Before Model Callback¶
When: Called just before the generate_content_async
(or equivalent) request is sent to the LLM within an LlmAgent
's flow.
Purpose: Allows inspection and modification of the request going to the LLM. Use cases include adding dynamic instructions, injecting few-shot examples based on state, modifying model config, implementing guardrails (like profanity filters), or implementing request-level caching.
Return Value Effect:
If the callback returns None
, the LLM continues its normal workflow. If the callback returns an LlmResponse
object, then the call to the LLM is skipped. The returned LlmResponse
is used directly as if it came from the model. This is powerful for implementing guardrails or caching.
After Model Callback¶
When: Called just after a response (LlmResponse
) is received from the LLM, before it's processed further by the invoking agent.
Purpose: Allows inspection or modification of the raw LLM response. Use cases include
- logging model outputs,
- reformatting responses,
- censoring sensitive information generated by the model,
- parsing structured data from the LLM response and storing it in
callback_context.state
- or handling specific error codes.
Tool Execution Callbacks¶
These callbacks are also specific to LlmAgent
and trigger around the execution of tools (including FunctionTool
, AgentTool
, etc.) that the LLM might request.
Before Tool Callback¶
When: Called just before a specific tool's run_async
method is invoked, after the LLM has generated a function call for it.
Purpose: Allows inspection and modification of tool arguments, performing authorization checks before execution, logging tool usage attempts, or implementing tool-level caching.
Return Value Effect:
- If the callback returns
None
, the tool'srun_async
method is executed with the (potentially modified)args
. - If a dictionary is returned, the tool's
run_async
method is skipped. The returned dictionary is used directly as the result of the tool call. This is useful for caching or overriding tool behavior.
After Tool Callback¶
When: Called just after the tool's run_async
method completes successfully.
Purpose: Allows inspection and modification of the tool's result before it's sent back to the LLM (potentially after summarization). Useful for logging tool results, post-processing or formatting results, or saving specific parts of the result to the session state.
Return Value Effect:
- If the callback returns
None
, the originaltool_response
is used. - If a new dictionary is returned, it replaces the original
tool_response
. This allows modifying or filtering the result seen by the LLM.