Skip to content

feat: add pluggable policy & taxonomy#5898

Closed
ViktorVeselov wants to merge 4 commits into
google:mainfrom
ViktorVeselov:feature/taxonomy-plugin
Closed

feat: add pluggable policy & taxonomy#5898
ViktorVeselov wants to merge 4 commits into
google:mainfrom
ViktorVeselov:feature/taxonomy-plugin

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

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

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). Currently, the SDK lacks an extensible, out-of-the-box plugin architecture that intercepts skill listings and execution checks to apply context-aware taxonomy validation. Additionally, taxonomy can be used and/or executed as a more deterministic task handler without taking away LLM's decision-making. This taxonomy can be used to empower existing systems, and, for example, can be applied to AntigravityCLI if needed.

Solution:
The initial design referred to embedding the design/taxonomy directly into the core SDK; instead of that, it pivoted to plugins. As a result, the following is true: Implemented a fully pluggable, opt-in Taxonomy & Policy Security Engine (as a TaxonomyPlugin(BasePlugin)). Key design points include:

  • Frontmatter Validation: Hardened validation rules in the Frontmatter model to parse taxonomy-binds natively, reusing the SDK's existing path segment guards under the hood.
  • Pre-Compiled Safety Guard: Configured the validation regex _TAXONOMY_BIND_PATTERN as a pre-compiled module-level immutable constant for maximum speed and security.
  • Dual-Schema Taxonomy Parsing: The TaxonomyRegistry cleanly 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 user roles, entitlements, and classification rules) during runtime execution.
  • Clean Event-Driven Integration: Integrates directly with the SDK's list_skills and is_skill_allowed hooks, keeping lists in the expected dictionary-wrapped XML response structure.

Testing Plan

Unit Tests:

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

Comprehensive Test Suite Executed:
Added and verified 53 passing test cases under the native pytest framework, including:

  1. test_taxonomy_plugin.py (6 cases): Validates full parsing of Flat and SKOS JSON-LD structures, async TaxonomyPipeline chaining, DefaultSkillPolicy set-intersection filtering, and interceptive before_tool_callback listing logic.
  2. test_models.py (4 cases): Validates taxonomy-binds aliases, list item validation, rejection of invalid tags (e.g. strings containing spaces), and serialization format.
  3. test__utils.py (1 case): End-to-end load tests validating YAML frontmatter mapping within SKILL.md parser loops.
# To execute the full pytest suite:
$env:PYTHONPATH="src"
python -m pytest tests/unittests/plugins/test_taxonomy_plugin.py tests/unittests/skills/test_models.py tests/unittests/skills/test__utils.py

Note

Environmental Package Mock Details:
Due to a pre-existing dependency issue where the installed google-genai library lacks the expected AvatarConfig attribute in certain environments, I pre-emptively mocked google.genai.types.AvatarConfig (inheriting from pydantic.BaseModel) directly inside tests/unittests/conftest.py.

This ensures that the test runner bypasses system-level schema compilation issues and allows the entire unit test suite to compile cleanly in any CI/CD or local environment, while remaining focused on validating our functionalities.

Manual Tests:

To manually verify the taxonomy filter pipeline:

  1. Initialize the Registry with a SKOS JSON-LD or Flat JSON configuration:
    from google.adk.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.

Important

Request for Thorough Verification and Security Auditing:
As this engine controls dynamic skill execution visibility, it acts as a primary security container boundary. It rprefered that reviewers thoroughly review and test:

  1. Context Traversal Boundaries: Verify that context values are evaluated securely against complex hierarchical SKOS registries.
  2. Pluggability / Compatibility: Verify that without the plugin registered, the runner continues standard operations with zero side-effects.

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

  • 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.

@adk-bot adk-bot added the core [Component] This issue is related to the core interface and implementation label May 29, 2026
@adk-bot
Copy link
Copy Markdown
Collaborator

adk-bot commented May 29, 2026

Response from ADK Triaging Agent

Hello @ViktorVeselov, thank you for creating this PR!

We really appreciate your contribution implementing the pluggable Taxonomy & Policy Security Engine. To help us review and merge your changes more efficiently, could you please provide the following details from our contribution guidelines:

  1. Summary of Passed Unit Tests: Please include a summary of the passed pytest results to verify everything is working as expected.
  2. Logs or Console Output for Manual E2E Tests: While you've provided excellent manual E2E test steps, could you please also attach the console output or logs showing the results of these tests after applying your changes?

This context is very helpful for the reviewers to understand the fix and ensure high code quality. Thank you for your support!

@ViktorVeselov ViktorVeselov marked this pull request as ready for review May 29, 2026 18:37
@rohityan rohityan self-assigned this May 29, 2026
@rohityan rohityan added the community repo [Community] FRs/issues well suited for google/adk-python-community repository label May 29, 2026
@rohityan
Copy link
Copy Markdown
Collaborator

Hi @ViktorVeselov , Thank you for your contribution! We appreciate you taking the time to submit this pull request.
Closing this PR here as it belongs to adk-python-community repo.
We highly recommend releasing the feature as a standalone package that we will then share through: https://google.github.io/adk-docs/integrations/

@rohityan rohityan closed this May 29, 2026
@ViktorVeselov
Copy link
Copy Markdown
Author

Response from ADK Triaging Agent

Hello @ViktorVeselov, thank you for creating this PR!

We really appreciate your contribution implementing the pluggable Taxonomy & Policy Security Engine. To help us review and merge your changes more efficiently, could you please provide the following details from our contribution guidelines:

  1. Summary of Passed Unit Tests: Please include a summary of the passed pytest results to verify everything is working as expected.
  2. Logs or Console Output for Manual E2E Tests: While you've provided excellent manual E2E test steps, could you please also attach the console output or logs showing the results of these tests after applying your changes?

This context is very helpful for the reviewers to understand the fix and ensure high code quality. Thank you for your support!


Below is the requested testing context, including the complete summary of the passed unit tests under pytest and the console logs from the manual E2E validation script demonstrating successful dual-schema taxonomy parsing and frontmatter validation.


1. Pytest Unit Test Summary

Added comprehensive coverage under pytest to fully validate parsing configurations, pipeline resolvers, set-intersection policy filters, and directory-traversal guards.
All 53 unit tests passed successfully:

============================= test session starts =============================
platform win32 -- Python 3.12.3, pytest-8.4.1, pluggy-1.6.0
rootdir: /google-sdk
configfile: pyproject.toml
plugins: anyio-4.12.1, asyncio-1.3.0
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collected 53 items
tests\unittests\plugins\test_taxonomy_plugin.py ......                   [ 11%]
tests\unittests\skills\test_models.py .............................      [ 66%]
tests\unittests\skills\test__utils.py ..................                 [100%]
======================= 53 passed, 5 warnings in 7.71s ========================
image

2. Manual E2E Validation Logs

Executed a dedicated end-to-end integration script to verify:

  • Flat Key-Value JSON parsing and hierarchical parent path resolution in TaxonomyRegistry.
  • Standard semantic SKOS JSON-LD parsing using concepts and broader relationship mappings.
  • Hardened Frontmatter Validation, successfully matching clean taxonomy binds and raising precise validation errors for disallowed elements (like spaces or special characters).

Here is the clean console output from the E2E verification run:

SUCCESS: Core modules imported correctly!

--- Testing Flat JSON Parsing ---
Registry loaded 2 terms.
Path to root for '101': Machine Learning -> Artificial Intelligence
Flat JSON parsing passed!

--- Testing JSON-LD SKOS Parsing ---
Registry loaded 2 terms.
Path to root for 'ml': Machine Learning -> Artificial Intelligence
JSON-LD SKOS parsing passed!

--- Testing Frontmatter Validation ---
Frontmatter parsed successfully. Taxonomy binds: ['engineering', 'machine-learning']
Expected validation error occurred successfully: 1 validation error for Frontmatter
taxonomy-binds
  Value error, Invalid characters in taxonomy bind tag: Engineering Invalid [type=value_error, input_value=['Engineering Invalid'], input_type=list]
    For further information visit https://errors.pydantic.dev/2.12/v/value_error
Frontmatter validation passed!
image

3. All Tests in tests/unittests

The following was executed for pre-testing and ensuring env. compatibility with SDK dependencies.

python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -e .[test]
$env:PYTHONPATH="src"
python -m pytest tests/unittests

With 6794 tests passing and 1 error related to the bash tool due to incompatible OS (Windows, while expected Linux/macOS):

============================================================================================= ERRORS =============================================================================================
____________________________________________________________________ ERROR collecting tests/unittests/tools/test_bash_tool.py ____________________________________________________________________ 
sdk\tests\unittests\tools\test_bash_tool.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
C:\Python312\Lib\importlib\__init__.py:90: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
tests\unittests\tools\test_bash_tool.py:16: in <module>
    import resource
E   ModuleNotFoundError: No module named 'resource'
======================================================================================== warnings summary ======================================================================================== 
image image image

@ViktorVeselov
Copy link
Copy Markdown
Author

Hi @ViktorVeselov , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Closing this PR here as it belongs to adk-python-community repo. We highly recommend releasing the feature as a standalone package that we will then share through: https://google.github.io/adk-docs/integrations/

Gotcha, I will see what we can do there then. I'd assume that I got positive feedback from you tho?

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

Labels

community repo [Community] FRs/issues well suited for google/adk-python-community repository 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: Modular Domain Taxonomy

3 participants