feat: add AuthorityRoutingPlugin for ADVISE/EXECUTE/DEFER/STOP tool authority - #173
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
…uthority Classifies the authority of each user turn (ADVISE / EXECUTE / DEFER / STOP) and enforces it on every tool call: only EXECUTE authorizes side effects. A pluggable model router is composed with a deterministic keyword guard under a most-restrictive-wins rule (the guard can only tighten the router), and the plugin fails closed on router errors or un-routed tool calls. Follows the AgentGovernancePlugin pattern (BasePlugin, async callbacks, None/dict short-circuit). Ported from a production pattern also proposed to anthropics/claude-cookbooks#787.
5d03686 to
d1502d6
Compare
|
@googlebot I signed it! |
|
Closing this in favour of #172, which carries the same AuthorityRoutingPlugin in a more complete form (fuller sample README, wider test coverage). Two of our sessions prepared this contribution in parallel and both opened a PR — that duplication is on us, apologies for the extra review surface. The CLA is signed and #172 is the one to look at. Nothing here is abandoned: everything in this branch is present in #172. |
Summary
Adds
AuthorityRoutingPlugin: an ADK plugin that classifies the authority of each user turn —ADVISE/EXECUTE/DEFER/STOP— and enforces it on every tool call. Tool schemas define what an agent can reach and permission systems define what calls are allowed, but a large class of real failures happens inside those boundaries: advice-becomes-action, one bounded edit ballooning into a dependent workflow, or proceeding when an approval was still pending. This plugin governs that layer.How it works — two layers composed under one rule, the strictest posture wins:
PostureRouterABC) classifies the turn. Provider-agnostic — back it with Gemini (google-genai) or any model. It's best-effort and can only ever be tightened by the guard, never loosened.delete,deploy,send,pending approval, …) that the router verdict is composed against.Only
EXECUTEauthorizes side effects;ADVISE/DEFER/STOPshort-circuit the tool with a denial dict (per the ADK plugin contract). The design fails closed: a router error or a tool call that runs before any turn was routed denies side effects rather than allowing them. An optional read-only allowlist keeps information-gathering tools usable underADVISE/DEFER.This follows the merged
AgentGovernancePluginpattern —BasePluginsubclass, asyncbefore_tool_callback,None(allow) /dict(short-circuit) return semantics, fail-closed default, bounded audit log. It's complementary, not overlapping:AgentGovernancePluginevaluates policy-as-code andDelegationAuthPlugin(#165) verifies credentials, whereas this governs the authority posture of the turn itself.Ported from a production authority-routing pattern, also proposed to the Anthropic cookbook (anthropics/claude-cookbooks#787).
Files
src/google/adk_community/plugins/authority_routing_plugin.py— the plugin,PostureRouter/CallableRouter,Posture,PostureVerdict,stricter()src/google/adk_community/plugins/__init__.py— public exportstests/plugins/test_authority_routing_plugin.py— 18 testscontributing/samples/authority_routing/— runnable example (no API key needed) + READMETesting plan
Unit tests cover: posture composition (most-restrictive-wins), the deterministic guard (irreversibility keyword, pending-approval marker, clean request, custom keywords), guard-only mode, ADVISE denies side-effecting tools, router-EXECUTE tightened to DEFER by the guard, clean EXECUTE allowed, fail-closed on router exception and on un-routed tool calls (plus the opt-in fail-open), read-only allowlist under ADVISE and its block under STOP,
CallableRouterwrapping a sync callable, and the audit log. The model router is stubbed, so the suite runs with no live key.Disclosure
Design and validation mine; implementation drafted with Claude, manually reviewed and tested.