Skip to content

feat: implement pluggable taxonomy and policy security plugin#151

Open
ViktorVeselov wants to merge 6 commits into
google:mainfrom
ViktorVeselov:feature/pluggable-taxonomy-engine
Open

feat: implement pluggable taxonomy and policy security plugin#151
ViktorVeselov wants to merge 6 commits into
google:mainfrom
ViktorVeselov:feature/pluggable-taxonomy-engine

Conversation

@ViktorVeselov
Copy link
Copy Markdown

@ViktorVeselov ViktorVeselov commented May 29, 2026

Have read the contribution guide before creating a pull request.

Link to Issue or Description of Change

Link to an existing issue / related PR:

Problem:
Developers and system administrators need a robust, standardized way to enforce security policies and access controls on skills based on organizational hierarchies and taxonomies (e.g., flat department structures or rich SKOS JSON-LD classifications).

Originally, we designed this to be embedded directly into the core adk-python SDK. However, in line with keeping the core framework minimalist, light, and secure, the core reviewers pointed me here to implement this as an official community extension plugin (referencing the closed PR adk-python/pull/5898).

Solution:
Implemented the Taxonomy & Policy Security Engine as a pluggable, opt-in plugin (TaxonomyPlugin) in adk-python-community. This gives developers enterprise-grade taxonomy controls and skill-access guardrails without cluttering the core SDK. Additionally, it can be used as a tool for usage reinforcers and for dynamic prompting that helps to provide an agent with well-polished context, skills/tools executions tailored toward determined cases.

Key design points include:

  • Fallback Parsing: Uses a robust fallback _get_taxonomy_binds() pattern to read taxonomy-binds keys from Frontmatter.model_extra (natively populated because the core SDK's Frontmatter model has extra="allow"). This ensures perfect runtime compatibility with the unmodified core adk-python library.
  • Path Isolation: Inlined all path safety validations within before_tool_callback instead of importing private core helper functions, making the plugin entirely resilient against future internal changes in core SDK versions.
  • Dual-Schema Taxonomy Parsing: The TaxonomyRegistry parses both standard Flat Key-Value JSON (id/parentId/name/definition) and rich JSON-LD with SKOS (Concept, prefLabel, altLabel, definition, broader) standards to resolve organizational hierarchies.
  • Pipeline Orchestration: Introduces TaxonomyPipeline and TaxonomyResolver interfaces to dynamically chain multiple contextual policy resolvers (e.g., checking active user directories, roles, and entitlements) during runtime execution.
  • Event-Driven Integration: Hooks directly into BasePlugin lifecycle callbacks to intercept tool boundaries (list_skills, load_skill, etc.), returning filtered lists in the expected dictionary-wrapped XML response structure.
  • Full Cognitive Steering & Prompt Tailoring: Unlike simple static permission checkers, this implementation supports dynamic prompt and tool modifications:
    • Dynamic System Prompt Refinement: Through shape_system_instruction(), the plugin dynamically tailors the global agent instructions at runtime based on active user context and classifications (e.g., automatically injecting compliance instructions).
    • Skill Customization Based on Taxonomy: Through shape_description(), policies can actively rewrite tool description properties to guide the LLM's action selection dynamically (e.g., adding warning prefixes).
    • Skill Prioritization: Through prioritize_skills(), the engine reorders available tools inside the formatted prompt XML, ensuring context-relevant or preferred skills are bubbled to the top of the LLM's consideration set.

Testing Plan

1. Unit & Integration Tests (Command & Logs)

Added a complete integration test suite in tests/plugins/test_taxonomy_plugin.py to match the community plugin testing conventions (e.g., alongside the existing test_agent_governance_plugin.py).

To run the tests, set the PYTHONPATH to include the community source files and your standard core SDK source directory:

$env:PYTHONPATH = "src;<path-to-core-adk-python-src>"
python -m pytest "tests"

Verifiable Test Execution Log Output:

============================= test session starts =============================
platform win32 -- Python 3.12.3, pytest-8.4.1, pluggy-1.6.0
rootdir: c:\adk-python-community
configfile: pyproject.toml
plugins: anyio-4.12.1, asyncio-1.3.0
asyncio: mode=Mode.AUTO, debug=False
collected 75 items / 1 skipped

adk-python-community\tests\plugins\test_agent_governance_plugin.py ..............                                                                                                 [ 18%]
adk-python-community\tests\plugins\test_taxonomy_plugin.py ......                                                                                                                 [ 26%]
adk-python-community\tests\unittests\memory\test_open_memory_service.py .............                                                                                             [ 44%]
adk-python-community\tests\unittests\sessions\test_redis_session_service.py ...............                                                                                       [ 64%]
adk-python-community\tests\unittests\test_sdc_agents_imports.py ssssssssssss                                                                                                      [ 80%]
adk-python-community\tests\unittests\tools\spraay\test_spraay_tools.py ...............                                                                                            [100%]

================================ warnings summary ==============================
  DeprecationWarning: BaseAgentConfig is deprecated and will be removed in future versions.

==================== 63 passed, 13 skipped, 4 warnings in 1.63s ================
image

Note

Environmental Package Mock Details:
Due to potential environment variations where the google-genai library is either outdated (lacking the expected AvatarConfig attribute) or completely absent, we pre-emptively mock/patch google.genai.types.AvatarConfig directly inside tests/conftest.py. This ensures that the test runner bypasses environment-level import conflicts and allows the unit test suite to compile cleanly in any CI/CD or local environment.

2. Manual Verification E2E

To manually verify the taxonomy filter pipeline:

  1. Initialize the Registry with a SKOS JSON-LD or Flat JSON configuration:
    from google.adk_community.plugins.taxonomy import TaxonomyRegistry, TaxonomyPlugin, DefaultSkillPolicy
    
    registry = TaxonomyRegistry.from_flat_json([
        {"id": "engineering", "parentId": None, "name": "Engineering"},
        {"id": "machine-learning", "parentId": "engineering", "name": "Machine Learning"}
    ])
  2. Instantiate the Plugin with a custom policy or the DefaultSkillPolicy:
    policy = DefaultSkillPolicy()
    plugin = TaxonomyPlugin(policy=policy, taxonomy_registry=registry)
    # Register plugin to the ADK instance
  3. Add taxonomy-binds to your skill's frontmatter configuration:
    taxonomy-binds:
      - "engineering"
      - "machine-learning"
  4. Invoke list_skills with a dynamic context (e.g. passing a user identity or role inside tool_context) and observe that skills bound to unauthorized taxonomies are securely filtered out of the response.

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.
  • I have checked formatting matches styles (using autoformat.sh / standard formatting).

Additional context

  • Built to satisfy strict pluggability constraints: when the plugin is not loaded, the ADK continues operating exactly as normal (100% opt-in).
  • Returning filtered skill lists preserves the SDK's exact contract by returning a structured dict expected by __build_response_event.
  • For focus purposes, there are no example files, and we will add them later once we agree on implementation.

@ViktorVeselov ViktorVeselov marked this pull request as ready for review May 30, 2026 18:19
@ViktorVeselov
Copy link
Copy Markdown
Author

@zeroasterisk

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.

1 participant