Skip to content

feat: add AuthorityRoutingPlugin for ADVISE/EXECUTE/DEFER/STOP tool authority - #173

Closed
Palo-Alto-AI-Research-Lab wants to merge 2 commits into
google:mainfrom
Palo-Alto-AI-Research-Lab:anton-dzyatkovsky/authority-routing-plugin
Closed

feat: add AuthorityRoutingPlugin for ADVISE/EXECUTE/DEFER/STOP tool authority#173
Palo-Alto-AI-Research-Lab wants to merge 2 commits into
google:mainfrom
Palo-Alto-AI-Research-Lab:anton-dzyatkovsky/authority-routing-plugin

Conversation

@Palo-Alto-AI-Research-Lab

Copy link
Copy Markdown

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:

  1. A pluggable model router (PostureRouter ABC) 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.
  2. A deterministic guard (plain keyword code a model can't be argued past) raises an irreversibility / pending-approval floor (delete, deploy, send, pending approval, …) that the router verdict is composed against.

Only EXECUTE authorizes side effects; ADVISE / DEFER / STOP short-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 under ADVISE/DEFER.

This follows the merged AgentGovernancePlugin pattern — BasePlugin subclass, async before_tool_callback, None (allow) / dict (short-circuit) return semantics, fail-closed default, bounded audit log. It's complementary, not overlapping: AgentGovernancePlugin evaluates policy-as-code and DelegationAuthPlugin (#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 exports
  • tests/plugins/test_authority_routing_plugin.py — 18 tests
  • contributing/samples/authority_routing/ — runnable example (no API key needed) + README

Testing 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, CallableRouter wrapping a sync callable, and the audit log. The model router is stubbed, so the suite runs with no live key.

$ python -m pytest tests/plugins/test_authority_routing_plugin.py -q
18 passed

$ python contributing/samples/authority_routing/main.py
[ADVISE ] DENIED  edit_file  <- Review the retry settings in config.yaml.
[EXECUTE] ALLOWED edit_file  <- Rename foo to bar in utils.py.
[DEFER  ] DENIED  shell      <- Deploy the release to production.

Disclosure

Design and validation mine; implementation drafted with Claude, manually reviewed and tested.

@google-cla

google-cla Bot commented Jul 23, 2026

Copy link
Copy Markdown

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.
@Palo-Alto-AI-Research-Lab
Palo-Alto-AI-Research-Lab force-pushed the anton-dzyatkovsky/authority-routing-plugin branch from 5d03686 to d1502d6 Compare July 27, 2026 06:14
@Palo-Alto-AI-Research-Lab

Copy link
Copy Markdown
Author

@googlebot I signed it!

@Palo-Alto-AI-Research-Lab

Copy link
Copy Markdown
Author

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.

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