Execution boundary
ADK already gives community plugins a precise pre-dispatch boundary: PluginManager.run_before_tool_callback() runs before functions.py calls the tool, and a non-None callback result short-circuits that dispatch. ToolContext.function_call_id also supplies the original call identity.
I built a bounded integration patch against 396da17a9597d8d5f96e7e1aa8c1c396c738d146 that maps this boundary to the experimental dhms-agentfuse==3.7.3 package:
AgentFuseGovernancePlugin evaluates a configured RuntimeGuard in before_tool_callback;
allow returns None, leaving approval, dispatch, execution outcome, retries, and completion owned by ADK;
block returns a terminal policy_denied / not_executed response before the tool body starts;
- the immutable decision is retained by the original
function_call_id;
- the dependency is an opt-in
agentfuse extra, not a default dependency.
Working proof
The patch includes two real LlmAgent + InMemoryRunner tests using ADK's actual plugin and tool-dispatch path:
- allow: protected handler count = 1;
- block: protected handler count = 0;
- both terminal
FunctionResponse objects preserve the original call ID;
- all plugin tests:
27 passed on Python 3.12, Google ADK 2.7.1, and AgentFuse 3.7.3.
The implementation is four files: one plugin, one focused test module, one export, and one optional dependency entry. It does not change ADK core or claim that a policy decision is approval or execution success.
If this integration shape fits the community repo, I can push the tested branch and open a Draft PR with the exact patch and test plan.
Execution boundary
ADK already gives community plugins a precise pre-dispatch boundary:
PluginManager.run_before_tool_callback()runs beforefunctions.pycalls the tool, and a non-Nonecallback result short-circuits that dispatch.ToolContext.function_call_idalso supplies the original call identity.I built a bounded integration patch against
396da17a9597d8d5f96e7e1aa8c1c396c738d146that maps this boundary to the experimentaldhms-agentfuse==3.7.3package:AgentFuseGovernancePluginevaluates a configuredRuntimeGuardinbefore_tool_callback;allowreturnsNone, leaving approval, dispatch, execution outcome, retries, and completion owned by ADK;blockreturns a terminalpolicy_denied/not_executedresponse before the tool body starts;function_call_id;agentfuseextra, not a default dependency.Working proof
The patch includes two real
LlmAgent+InMemoryRunnertests using ADK's actual plugin and tool-dispatch path:FunctionResponseobjects preserve the original call ID;27 passedon Python 3.12, Google ADK 2.7.1, and AgentFuse 3.7.3.The implementation is four files: one plugin, one focused test module, one export, and one optional dependency entry. It does not change ADK core or claim that a policy decision is approval or execution success.
If this integration shape fits the community repo, I can push the tested branch and open a Draft PR with the exact patch and test plan.