Skip to content

feat(governance): Add GovernancePlugin for runtime agent governance#102

Open
sunilp wants to merge 2 commits intogoogle:mainfrom
sunilp:feat/governance-plugin
Open

feat(governance): Add GovernancePlugin for runtime agent governance#102
sunilp wants to merge 2 commits intogoogle:mainfrom
sunilp:feat/governance-plugin

Conversation

@sunilp
Copy link
Copy Markdown

@sunilp sunilp commented Mar 19, 2026

Summary

Adds a GovernancePlugin that provides runtime governance for ADK agents — policy-based tool filtering, delegation scope enforcement, and structured audit trails — without modifying agent logic.

Moved here from google/adk-python#4897 per maintainer guidance (community plugins belong in this repo).

What it does

  • Policy-based tool filtering — evaluate tool calls against custom policies before execution; deny with structured reasons
  • Tool argument validation — regex-based argument pattern enforcement (e.g., SQL queries must start with SELECT)
  • Delegation scope enforcement — control which agents can delegate to which other agents
  • Structured audit trail — every policy decision logged with timestamp, agent, tool, decision, and reason
  • Pluggable architecture — custom PolicyEvaluator protocol for organization-specific rules; custom AuditHandler for integration with logging/SIEM systems

Usage

from google.adk_community.governance import (
    GovernancePlugin, PolicyEvaluator, PolicyDecision, ToolPolicy,
)

class MyPolicyEvaluator(PolicyEvaluator):
    async def evaluate_tool_call(self, *, tool_name, tool_args,
                                 agent_name, context):
        if tool_name == "dangerous_tool":
            return PolicyDecision.deny("Tool not allowed by policy")
        return PolicyDecision.allow()

plugin = GovernancePlugin(
    policy_evaluator=MyPolicyEvaluator(),
    tool_policies={"sql_tool": ToolPolicy(allowed_arg_patterns={"query": r"^SELECT"})},
)
# runner = Runner(..., plugins=[plugin])

Files

  • src/google/adk_community/governance/governance_plugin.py — plugin implementation (692 lines)
  • src/google/adk_community/governance/__init__.py — public API exports
  • tests/unittests/governance/test_governance_plugin.py — unit tests (577 lines)

Testing plan

  • 577 lines of unit tests covering: policy evaluation, tool filtering, argument validation, delegation scope enforcement, audit trail generation, edge cases
  • Tests use mocks for ADK internals (BaseAgent, CallbackContext, InvocationContext)

Related

Adds policy-based tool filtering, delegation scope enforcement,
and structured audit trails for ADK agents.

Moved from google/adk-python#4897 per maintainer guidance.
aeoess pushed a commit to aeoess/agent-passport-python that referenced this pull request Mar 20, 2026
Maps sunilp's PolicyEvaluator protocol (google/adk-python-community#102)
to APS 3-signature policy chain (intent → decision → receipt).

- APSPolicyEvaluator: evaluate_tool_call + evaluate_agent_delegation
- APSPolicyDecision: duck-typed compatible with ADK's PolicyDecision
- Wildcard scope expansion (tool:* → specific tool)
- Monotonic narrowing enforcement for delegation
- Full cryptographic proof chain in metadata
- 16 tests, 3 suites, 102 total passing

102 tests, 0 failures.
@sunilp
Copy link
Copy Markdown
Author

sunilp commented Mar 27, 2026

Friendly bump — anything needed from my side to move this forward? Happy to address feedback or adjust the scope.

@DeanChensj
Copy link
Copy Markdown
Collaborator

@gemini-cli /review

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 5, 2026

🤖 Hi @DeanChensj, I've received your request, and I'm working on it now! You can track my progress in the logs for more details.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great start on the GovernancePlugin! It provides a solid foundation for runtime governance in ADK.

I've identified a few issues that should be addressed before merging:

  1. Missing Regex Argument Validation: The allowed_arg_patterns in ToolPolicy is defined but not enforced in before_tool_callback. This was mentioned as a key feature in the PR description.
  2. Memory Growth in _audit_log: The internal audit log list grows indefinitely, which could lead to memory leaks in long-running applications.
  3. Interleaved Audit Events: Since _audit_log is shared across invocations, events from different sessions will be mixed.

Please address these implementation details. Otherwise, the architecture looks sound and well-integrated with the ADK plugin system.

Attributes:
action: The type of action being audited.
agent_name: The agent that triggered the action.
tool_name: The tool involved, if applicable.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The allowed_arg_patterns attribute is defined here but doesn't seem to be used in before_tool_callback. Was the implementation missed?

agent_name=agent_name,
context=tool_context,
)
if decision.decision == Decision.DENY:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since _audit_log is shared across all invocations using this plugin instance, events from different sessions will be interleaved. If this is intended for a global audit trail, it's fine, but be aware of memory growth.

],
)

await self._emit_audit(
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing implementation for ToolPolicy.allowed_arg_patterns regex validation. The PR description and docstrings mention this feature, but the code doesn't enforce it here. It should probably be checked before or after the custom policy evaluator.

governance decision point, queryable via standard logging or
custom audit handlers.

Example:
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _audit_log list grows indefinitely as it's never cleared. This could lead to a memory leak in long-running processes. Consider adding a way to clear it or using a bounded buffer if internal logging is desired.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants