Skip to content

feat(plugins): add AgentHooksPlugin to govern ADK agents with agent-hooks - #6605

Open
prayagupa wants to merge 1 commit into
google:mainfrom
prayagupa:feat/agent-hooks-integration
Open

feat(plugins): add AgentHooksPlugin to govern ADK agents with agent-hooks#6605
prayagupa wants to merge 1 commit into
google:mainfrom
prayagupa:feat/agent-hooks-integration

Conversation

@prayagupa

@prayagupa prayagupa commented Aug 5, 2026

Copy link
Copy Markdown

Please ensure you have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

2. Or, if no issue exists, describe the change:

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

New suite tests/unittests/plugins/test_agent_hooks_plugin.py (26 tests) covers
the interception-point mapping, fail-closed paths (engine error / malformed
verdict / timeout → deny), enforcement-mode fidelity (evaluate_only does not
transform), startup-deny re-enforcement at the first model call, pre/post
tool-call id correlation across arg transforms, and recursion-depth bounding of
untrusted input.

$ python -m pytest tests/unittests/plugins/test_agent_hooks_plugin.py -q
26 passed in 1.17s

# No regressions in the rest of the plugins package
# (the sole excluded file needs the uninstalled `google.api_core` BigQuery extra,
#  unrelated to this change):
$ python -m pytest tests/unittests/plugins/ -q \
    --ignore=tests/unittests/plugins/test_bigquery_agent_analytics_plugin.py
194 passed, 14 warnings in 2.51s

Manual End-to-End (E2E) Tests:

The change ships a runnable sample that governs a real local model (no scripted
tool output):

pip install "google-adk[agent-hooks]" litellm
ollama pull qwen2.5                       # any tool-capable Ollama model works
python -m contributing.samples.agent_hooks.main

The support agent has two tools. lookup_account returns email + api_key;
delete_account is destructive. A single ToolGovernanceInterceptor denies the
destructive tool and redacts the sensitive fields, and the run prints the audit
trail. Actual output:

=== USER: Look up the account details for user 42. ===
[support_agent] -> tool call: lookup_account
[support_agent] <- tool result: {'api_key': '[REDACTED]', 'email': '[REDACTED]', 'name': 'Alice Example', 'plan': 'pro', 'user_id': '42'}
[support_agent] Here are the details for user 42: - Name: Alice Example - Plan: pro. I've redacted the API key and email as per policy.

=== USER: Now delete account 42. ===
[support_agent] -> tool call: delete_account
[support_agent] <- tool result: {'error': "blocked by agent-hooks: tool_denied: Tool 'delete_account' is disabled by policy.", 'agent_hooks_blocked': True, ...}
[support_agent] I'm sorry, but deleting accounts is blocked by our policies...

=== agent-hooks audit trail ===
seq=5  post_tool_call   -> transform      # lookup_account result redacted
...
seq=4  pre_tool_call    -> deny (tool_denied)   # delete_account blocked

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

Interception-point mapping (ADK callback → agent-hooks point):

ADK plugin callback agent-hooks point
before_run_callback agent_startup
on_user_message_callback input
before_model_callback pre_model_call
after_model_callback post_model_call
before_tool_callback pre_tool_call
after_tool_callback post_tool_call
on_event_callback (final) output
after_run_callback agent_shutdown
  • pre_model_call supports allow/deny only; a transform there is treated
    as a fail-closed deny, because rebuilding a provider-native request from wire
    messages is not round-trip safe.
  • Trust model: agent-hooks is a cooperative control contract, not a
    security boundary — interceptors run in-process with full data access and the
    interception points do not guarantee complete mediation.
  • Files: src/google/adk/plugins/_agent_hooks_plugin.py (+ lazy export in
    plugins/__init__.py), pyproject.toml (agent-hooks extra),
    contributing/samples/agent_hooks/, and the unit-test suite. (9 files, +1753.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request]: Add framework-neutral agent-hooks contract to govern ADK agents

3 participants