From 3e9ce1529ab67896edb331bbc62993430310edc1 Mon Sep 17 00:00:00 2001 From: "Timothy W. Cook" Date: Mon, 23 Mar 2026 08:47:23 -0500 Subject: [PATCH 1/6] Add SDC Agents community toolsets module Thin re-export wrapper over the sdc-agents PyPI package, providing eight BaseToolset implementations (32 tools) for semantic data governance through the google.adk_community namespace. Includes: - Re-export module at google.adk_community.sdc_agents - Optional dependency: pip install google-adk-community[sdc-agents] - Import verification tests - Sample agent demo (CatalogToolset + IntrospectToolset) --- .../samples/sdc_agents_demo/README.md | 58 +++++++++++++ contributing/samples/sdc_agents_demo/agent.py | 68 +++++++++++++++ pyproject.toml | 3 + src/google/adk_community/__init__.py | 5 ++ src/google/adk_community/sdc_agents/README.md | 87 +++++++++++++++++++ .../adk_community/sdc_agents/__init__.py | 47 ++++++++++ tests/unittests/test_sdc_agents_imports.py | 78 +++++++++++++++++ 7 files changed, 346 insertions(+) create mode 100644 contributing/samples/sdc_agents_demo/README.md create mode 100644 contributing/samples/sdc_agents_demo/agent.py create mode 100644 src/google/adk_community/sdc_agents/README.md create mode 100644 src/google/adk_community/sdc_agents/__init__.py create mode 100644 tests/unittests/test_sdc_agents_imports.py diff --git a/contributing/samples/sdc_agents_demo/README.md b/contributing/samples/sdc_agents_demo/README.md new file mode 100644 index 00000000..a8b6374d --- /dev/null +++ b/contributing/samples/sdc_agents_demo/README.md @@ -0,0 +1,58 @@ +# SDC Agents Demo + +A minimal example composing SDC Agents toolsets with an ADK `LlmAgent`. + +## Prerequisites + +- Python 3.11+ +- An SDCStudio API key (set as `SDC_API_KEY` environment variable) + +## Setup + +```bash +pip install google-adk-community[sdc-agents] + +export SDC_API_KEY="your-sdcstudio-api-key" +export GOOGLE_API_KEY="your-google-api-key" +``` + +## Usage + +```bash +# Run with the ADK CLI +adk run . + +# Or use the ADK web UI +adk web . +``` + +## What This Demo Does + +The agent composes two SDC Agents toolsets: + +- **CatalogToolset**: Search published SDC4 schemas, download artifacts + (XSD, RDF, JSON-LD), and check wallet balance. +- **IntrospectToolset**: Analyze a datasource to infer column types, + constraints, and statistics. + +## Sample Queries + +``` +> Search the catalog for schemas related to lab results +> Introspect the sample datasource +> What published schemas match the columns in my datasource? +``` + +## Structure + +``` +sdc_agents_demo/ +├── agent.py # Agent definition with SDC toolsets +└── README.md # This file +``` + +## Resources + +- [SDC Agents Documentation](https://github.com/SemanticDataCharter/SDC_Agents) +- [SDC Agents on PyPI](https://pypi.org/project/sdc-agents/) +- [ADK Integration Guide](https://github.com/SemanticDataCharter/SDC_Agents/blob/main/docs/integrations/ADK_INTEGRATION.md) diff --git a/contributing/samples/sdc_agents_demo/agent.py b/contributing/samples/sdc_agents_demo/agent.py new file mode 100644 index 00000000..6cd2cd86 --- /dev/null +++ b/contributing/samples/sdc_agents_demo/agent.py @@ -0,0 +1,68 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Minimal SDC Agents demo -- catalog search + data introspection. + +Composes CatalogToolset and IntrospectToolset into a single LlmAgent +that can discover published SDC4 schemas and introspect datasource +structure. + +Prerequisites: + pip install google-adk-community[sdc-agents] + export SDC_API_KEY="your-sdcstudio-api-key" + +Usage: + adk run . +""" + +from google.adk.agents import LlmAgent + +from google.adk_community.sdc_agents import ( + CatalogToolset, + IntrospectToolset, + SDCAgentsConfig, +) + +config = SDCAgentsConfig( + sdcstudio={ + "base_url": "https://sdcstudio.com", + "api_key": "${SDC_API_KEY}", + }, + datasources={ + "sample": { + "type": "csv", + "path": "./data/sample.csv", + }, + }, + cache={"root": ".sdc-cache"}, + audit={"path": ".sdc-cache/audit.jsonl"}, +) + +root_agent = LlmAgent( + name="sdc_demo_agent", + model="gemini-2.0-flash", + description=( + "Discovers SDC4 schemas and introspects datasource structure." + ), + instruction=( + "You help data engineers govern their data.\n" + "1. Use catalog tools to search for published SDC4 schemas\n" + "2. Use introspect tools to analyze datasource columns and types\n" + "3. Summarize findings clearly" + ), + tools=[ + CatalogToolset(config=config), + IntrospectToolset(config=config), + ], +) diff --git a/pyproject.toml b/pyproject.toml index 71fbb78d..cbfa717f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,6 +45,9 @@ test = [ "pytest>=8.4.2", "pytest-asyncio>=1.2.0", ] +sdc-agents = [ + "sdc-agents>=4.2.0", +] spraay = ["web3>=6.0.0"] diff --git a/src/google/adk_community/__init__.py b/src/google/adk_community/__init__.py index 9a1dc35f..fb0b7d69 100644 --- a/src/google/adk_community/__init__.py +++ b/src/google/adk_community/__init__.py @@ -15,4 +15,9 @@ from . import memory from . import sessions from . import version + +try: + from . import sdc_agents +except ImportError: + pass # Optional: pip install google-adk-community[sdc-agents] __version__ = version.__version__ diff --git a/src/google/adk_community/sdc_agents/README.md b/src/google/adk_community/sdc_agents/README.md new file mode 100644 index 00000000..47b023ca --- /dev/null +++ b/src/google/adk_community/sdc_agents/README.md @@ -0,0 +1,87 @@ +# SDC Agents -- Semantic Data Governance for ADK + +Thin re-export wrapper over the +[`sdc-agents`](https://pypi.org/project/sdc-agents/) PyPI package. The +canonical source lives at +[SemanticDataCharter/SDC_Agents](https://github.com/SemanticDataCharter/SDC_Agents); +this module provides importability through the `google.adk_community` +namespace. + +## Installation + +```bash +pip install google-adk-community[sdc-agents] +``` + +## Usage + +```python +from google.adk.agents import LlmAgent +from google.adk_community.sdc_agents import ( + load_config, + CatalogToolset, + IntrospectToolset, + MappingToolset, +) + +config = load_config("sdc-agents.yaml") + +agent = LlmAgent( + name="data_governance_agent", + model="gemini-2.0-flash", + description="Introspects data sources and maps them to SDC4 schemas.", + instruction=( + "You help data engineers govern their data. When given a datasource:\n" + "1. Introspect the structure to discover columns and types\n" + "2. Search the SDC4 catalog for matching published schemas\n" + "3. Map columns to schema components by type and name similarity\n" + "4. Report the mapping with confidence scores" + ), + tools=[ + IntrospectToolset(config=config), + CatalogToolset(config=config), + MappingToolset(config=config), + ], +) +``` + +## Exported Toolsets + +| Toolset | Description | +|---------|-------------| +| **CatalogToolset** | Discover published SDC4 schemas, download artifacts (XSD, RDF, JSON-LD), check wallet balance | +| **IntrospectToolset** | Analyze datasource structure -- infer column types and constraints from SQL, CSV, JSON, MongoDB | +| **MappingToolset** | Match datasource columns to schema components by type compatibility and name similarity | +| **AssemblyToolset** | Compose data models from catalog components -- reuse existing or mint new, with wallet billing | +| **GeneratorToolset** | Generate validated XML instances, batch processing, and preview | +| **ValidationToolset** | Validate XML instances against schemas, digitally sign via VaaS API | +| **DistributionToolset** | Deliver RDF triples to Fuseki, Neo4j, GraphDB, or REST endpoints | +| **KnowledgeToolset** | Index domain documentation (JSON, CSV, TTL, Markdown, PDF, DOCX) for semantic search | + +## Configuration + +SDC Agents uses a YAML config file with environment variable substitution: + +```yaml +sdcstudio: + base_url: "https://sdcstudio.com" + api_key: "${SDC_API_KEY}" + +datasources: + warehouse: + type: csv + path: "./data/sample.csv" + +cache: + root: ".sdc-cache" + +audit: + path: ".sdc-cache/audit.jsonl" +``` + +## Resources + +- [SDC Agents on PyPI](https://pypi.org/project/sdc-agents/) +- [SDC Agents GitHub](https://github.com/SemanticDataCharter/SDC_Agents) +- [ADK Integration Guide](https://github.com/SemanticDataCharter/SDC_Agents/blob/main/docs/integrations/ADK_INTEGRATION.md) +- [SDCStudio](https://sdcstudio.com) diff --git a/src/google/adk_community/sdc_agents/__init__.py b/src/google/adk_community/sdc_agents/__init__.py new file mode 100644 index 00000000..70a0022e --- /dev/null +++ b/src/google/adk_community/sdc_agents/__init__.py @@ -0,0 +1,47 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""SDC Agents -- Purpose-scoped semantic data governance toolsets for ADK. + +Eight BaseToolset implementations (32 tools) that transform SQL, CSV, JSON, +and MongoDB data into validated, self-describing SDC4 artifacts with +structured audit trails and enforced agent isolation boundaries. + +Install: pip install google-adk-community[sdc-agents] +Docs: https://github.com/SemanticDataCharter/SDC_Agents +""" + +from sdc_agents.common.config import load_config +from sdc_agents.common.config import SDCAgentsConfig +from sdc_agents.toolsets.assembly import AssemblyToolset +from sdc_agents.toolsets.catalog import CatalogToolset +from sdc_agents.toolsets.distribution import DistributionToolset +from sdc_agents.toolsets.generator import GeneratorToolset +from sdc_agents.toolsets.introspect import IntrospectToolset +from sdc_agents.toolsets.knowledge import KnowledgeToolset +from sdc_agents.toolsets.mapping import MappingToolset +from sdc_agents.toolsets.validation import ValidationToolset + +__all__ = [ + "load_config", + "SDCAgentsConfig", + "AssemblyToolset", + "CatalogToolset", + "DistributionToolset", + "GeneratorToolset", + "IntrospectToolset", + "KnowledgeToolset", + "MappingToolset", + "ValidationToolset", +] diff --git a/tests/unittests/test_sdc_agents_imports.py b/tests/unittests/test_sdc_agents_imports.py new file mode 100644 index 00000000..f9a1bb0e --- /dev/null +++ b/tests/unittests/test_sdc_agents_imports.py @@ -0,0 +1,78 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Verify that all SDC Agents re-exports resolve correctly.""" + +import importlib + +import pytest + + +@pytest.fixture(autouse=True) +def _skip_if_not_installed(): + """Skip every test in this module when sdc-agents is not installed.""" + pytest.importorskip("sdc_agents") + + +class TestSDCAgentsImports: + """Validate that the community re-export module exposes all toolsets.""" + + def test_module_importable(self): + mod = importlib.import_module("google.adk_community.sdc_agents") + assert mod is not None + + def test_load_config_exported(self): + from google.adk_community.sdc_agents import load_config + + assert callable(load_config) + + def test_sdc_agents_config_exported(self): + from google.adk_community.sdc_agents import SDCAgentsConfig + + assert SDCAgentsConfig is not None + + @pytest.mark.parametrize( + "name", + [ + "AssemblyToolset", + "CatalogToolset", + "DistributionToolset", + "GeneratorToolset", + "IntrospectToolset", + "KnowledgeToolset", + "MappingToolset", + "ValidationToolset", + ], + ) + def test_toolset_exported(self, name: str): + mod = importlib.import_module("google.adk_community.sdc_agents") + cls = getattr(mod, name, None) + assert cls is not None, f"{name} not found in sdc_agents module" + + def test_all_list_complete(self): + from google.adk_community import sdc_agents + + expected = { + "load_config", + "SDCAgentsConfig", + "AssemblyToolset", + "CatalogToolset", + "DistributionToolset", + "GeneratorToolset", + "IntrospectToolset", + "KnowledgeToolset", + "MappingToolset", + "ValidationToolset", + } + assert set(sdc_agents.__all__) == expected From 48a265e37d29eb0b7a4d4ab29ac634ef3d375d52 Mon Sep 17 00:00:00 2001 From: twcook Date: Fri, 27 Mar 2026 09:36:42 -0500 Subject: [PATCH 2/6] chore: Update SDC Agents integration to v4.3.3 - Bump sdc-agents dependency from >=4.2.0 to >=4.3.3 - Update toolset descriptions for 4.3.x improvements (catalog-first discovery, structured unmatched columns, mapping context persistence, sidecar metadata support) - Enhance demo agent to show full pipeline (5 toolsets) instead of minimal 2-toolset example --- contributing/samples/sdc_agents_demo/agent.py | 31 +++++++++++++------ pyproject.toml | 2 +- src/google/adk_community/sdc_agents/README.md | 8 ++--- .../adk_community/sdc_agents/__init__.py | 2 ++ 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/contributing/samples/sdc_agents_demo/agent.py b/contributing/samples/sdc_agents_demo/agent.py index 6cd2cd86..3e030c52 100644 --- a/contributing/samples/sdc_agents_demo/agent.py +++ b/contributing/samples/sdc_agents_demo/agent.py @@ -12,11 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Minimal SDC Agents demo -- catalog search + data introspection. +"""SDC Agents demo -- full data governance pipeline. -Composes CatalogToolset and IntrospectToolset into a single LlmAgent -that can discover published SDC4 schemas and introspect datasource -structure. +Composes five SDC Agents toolsets into a single LlmAgent that can +introspect datasources, discover matching catalog components, map +columns to schemas, and assemble validated data models. Prerequisites: pip install google-adk-community[sdc-agents] @@ -31,6 +31,9 @@ from google.adk_community.sdc_agents import ( CatalogToolset, IntrospectToolset, + MappingToolset, + AssemblyToolset, + ValidationToolset, SDCAgentsConfig, ) @@ -53,16 +56,24 @@ name="sdc_demo_agent", model="gemini-2.0-flash", description=( - "Discovers SDC4 schemas and introspects datasource structure." + "Full data governance pipeline: introspect, discover, map," + " and assemble SDC4 data models." ), instruction=( - "You help data engineers govern their data.\n" - "1. Use catalog tools to search for published SDC4 schemas\n" - "2. Use introspect tools to analyze datasource columns and types\n" - "3. Summarize findings clearly" + "You help data engineers govern their data. Follow this workflow:\n" + "1. Introspect the datasource to discover columns and types\n" + "2. Search the SDC4 catalog for matching published schemas\n" + "3. Discover catalog components that match the datasource structure\n" + "4. Map unmatched columns to schema components by similarity\n" + "5. Propose a cluster hierarchy for the data model\n" + "6. Assemble the final data model via the Assembly API\n" + "7. Validate the generated artifacts" ), tools=[ - CatalogToolset(config=config), IntrospectToolset(config=config), + CatalogToolset(config=config), + MappingToolset(config=config), + AssemblyToolset(config=config), + ValidationToolset(config=config), ], ) diff --git a/pyproject.toml b/pyproject.toml index cbfa717f..db687035 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ test = [ "pytest-asyncio>=1.2.0", ] sdc-agents = [ - "sdc-agents>=4.2.0", + "sdc-agents>=4.3.3", ] spraay = ["web3>=6.0.0"] diff --git a/src/google/adk_community/sdc_agents/README.md b/src/google/adk_community/sdc_agents/README.md index 47b023ca..c1f67144 100644 --- a/src/google/adk_community/sdc_agents/README.md +++ b/src/google/adk_community/sdc_agents/README.md @@ -49,10 +49,10 @@ agent = LlmAgent( | Toolset | Description | |---------|-------------| -| **CatalogToolset** | Discover published SDC4 schemas, download artifacts (XSD, RDF, JSON-LD), check wallet balance | -| **IntrospectToolset** | Analyze datasource structure -- infer column types and constraints from SQL, CSV, JSON, MongoDB | -| **MappingToolset** | Match datasource columns to schema components by type compatibility and name similarity | -| **AssemblyToolset** | Compose data models from catalog components -- reuse existing or mint new, with wallet billing | +| **CatalogToolset** | Discover published SDC4 schemas, download artifacts (XSD, RDF, JSON-LD) | +| **IntrospectToolset** | Analyze datasource structure -- infer column types and constraints from SQL, CSV, JSON, MongoDB with sidecar metadata support | +| **MappingToolset** | Match datasource columns to schema components by type compatibility and name similarity, persist mapping configs with schema and datasource context | +| **AssemblyToolset** | Compose data models from catalog components -- reuse existing or mint new, with catalog-first discovery and structured unmatched column reporting | | **GeneratorToolset** | Generate validated XML instances, batch processing, and preview | | **ValidationToolset** | Validate XML instances against schemas, digitally sign via VaaS API | | **DistributionToolset** | Deliver RDF triples to Fuseki, Neo4j, GraphDB, or REST endpoints | diff --git a/src/google/adk_community/sdc_agents/__init__.py b/src/google/adk_community/sdc_agents/__init__.py index 70a0022e..a72920b7 100644 --- a/src/google/adk_community/sdc_agents/__init__.py +++ b/src/google/adk_community/sdc_agents/__init__.py @@ -20,6 +20,8 @@ Install: pip install google-adk-community[sdc-agents] Docs: https://github.com/SemanticDataCharter/SDC_Agents + +Requires sdc-agents >= 4.3.3. """ from sdc_agents.common.config import load_config From dda744747b72b4f022f096cb912cbb969507935b Mon Sep 17 00:00:00 2001 From: twcook Date: Sun, 10 May 2026 14:39:57 -0500 Subject: [PATCH 3/6] fix(sdc-agents-demo): use env vars for base_url and api_key Addresses Gemini bot review on PR #106: - base_url is now overridable via SDC_BASE_URL with default https://sdcstudio.axius-sdc.com (the production endpoint). - api_key is now read from SDC_API_KEY via os.environ.get rather than the literal "${SDC_API_KEY}" string, which was not substituted by pydantic and broke the demo as written. - Docstring prerequisites updated to mention SDC_BASE_URL. --- contributing/samples/sdc_agents_demo/agent.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contributing/samples/sdc_agents_demo/agent.py b/contributing/samples/sdc_agents_demo/agent.py index 3e030c52..0107ceac 100644 --- a/contributing/samples/sdc_agents_demo/agent.py +++ b/contributing/samples/sdc_agents_demo/agent.py @@ -21,11 +21,14 @@ Prerequisites: pip install google-adk-community[sdc-agents] export SDC_API_KEY="your-sdcstudio-api-key" + export SDC_BASE_URL="https://sdcstudio.axius-sdc.com" # optional; this is the default Usage: adk run . """ +import os + from google.adk.agents import LlmAgent from google.adk_community.sdc_agents import ( @@ -39,8 +42,8 @@ config = SDCAgentsConfig( sdcstudio={ - "base_url": "https://sdcstudio.com", - "api_key": "${SDC_API_KEY}", + "base_url": os.environ.get("SDC_BASE_URL", "https://sdcstudio.axius-sdc.com"), + "api_key": os.environ.get("SDC_API_KEY", ""), }, datasources={ "sample": { From 59e39f9146e576da23e6c0505d6124ca6cd8f413 Mon Sep 17 00:00:00 2001 From: twcook Date: Wed, 13 May 2026 11:02:12 -0500 Subject: [PATCH 4/6] fix(sdc-agents): py3.10 install guard, demo sample, explicit api key error - pyproject: gate sdc-agents extra on python_version >= '3.11' so uv sync resolves cleanly on 3.10 (sdc-agents 4.3.3 itself requires >=3.11). - tests: add module-level skipif(<3.11) to test_sdc_agents_imports. - demo: raise ValueError with setup instructions when SDC_API_KEY is missing, instead of silently defaulting to an empty string. - demo: add contributing/samples/sdc_agents_demo/data/sample.csv (12-row lab-results dataset matching the README's sample query). The tools/ folder placement question raised in the prior review is being clarified separately before any module move. --- contributing/samples/sdc_agents_demo/agent.py | 10 +++++++++- .../samples/sdc_agents_demo/data/sample.csv | 13 +++++++++++++ pyproject.toml | 2 +- tests/unittests/test_sdc_agents_imports.py | 6 ++++++ 4 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 contributing/samples/sdc_agents_demo/data/sample.csv diff --git a/contributing/samples/sdc_agents_demo/agent.py b/contributing/samples/sdc_agents_demo/agent.py index 0107ceac..3db8b585 100644 --- a/contributing/samples/sdc_agents_demo/agent.py +++ b/contributing/samples/sdc_agents_demo/agent.py @@ -40,10 +40,18 @@ SDCAgentsConfig, ) +api_key = os.environ.get("SDC_API_KEY") +if not api_key: + raise ValueError( + "SDC_API_KEY environment variable is required. " + "Get an API key from https://sdcstudio.axius-sdc.com and set it via: " + "export SDC_API_KEY=\"your-key\"" + ) + config = SDCAgentsConfig( sdcstudio={ "base_url": os.environ.get("SDC_BASE_URL", "https://sdcstudio.axius-sdc.com"), - "api_key": os.environ.get("SDC_API_KEY", ""), + "api_key": api_key, }, datasources={ "sample": { diff --git a/contributing/samples/sdc_agents_demo/data/sample.csv b/contributing/samples/sdc_agents_demo/data/sample.csv new file mode 100644 index 00000000..5d1182e0 --- /dev/null +++ b/contributing/samples/sdc_agents_demo/data/sample.csv @@ -0,0 +1,13 @@ +patient_id,test_date,test_name,result_value,result_units,reference_low,reference_high +P001,2026-01-15,Glucose,98,mg/dL,70,99 +P002,2026-01-15,HbA1c,5.4,%,4.0,5.6 +P003,2026-01-16,Total Cholesterol,182,mg/dL,0,200 +P004,2026-01-16,LDL Cholesterol,104,mg/dL,0,130 +P005,2026-01-17,HDL Cholesterol,58,mg/dL,40,60 +P006,2026-01-17,Triglycerides,142,mg/dL,0,150 +P007,2026-01-18,Creatinine,0.9,mg/dL,0.6,1.2 +P008,2026-01-18,BUN,14,mg/dL,7,20 +P009,2026-01-19,Sodium,140,mmol/L,135,145 +P010,2026-01-19,Potassium,4.1,mmol/L,3.5,5.0 +P011,2026-01-20,Hemoglobin,14.2,g/dL,13.5,17.5 +P012,2026-01-20,WBC,7.8,K/uL,4.0,11.0 diff --git a/pyproject.toml b/pyproject.toml index db687035..a92b711e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,7 +46,7 @@ test = [ "pytest-asyncio>=1.2.0", ] sdc-agents = [ - "sdc-agents>=4.3.3", + "sdc-agents>=4.3.3; python_version >= '3.11'", ] spraay = ["web3>=6.0.0"] diff --git a/tests/unittests/test_sdc_agents_imports.py b/tests/unittests/test_sdc_agents_imports.py index f9a1bb0e..148c6cea 100644 --- a/tests/unittests/test_sdc_agents_imports.py +++ b/tests/unittests/test_sdc_agents_imports.py @@ -15,9 +15,15 @@ """Verify that all SDC Agents re-exports resolve correctly.""" import importlib +import sys import pytest +pytestmark = pytest.mark.skipif( + sys.version_info < (3, 11), + reason="sdc-agents requires Python 3.11+", +) + @pytest.fixture(autouse=True) def _skip_if_not_installed(): From 638d111c0a819f7f7c0fb540dc7f73ef187fbd4a Mon Sep 17 00:00:00 2001 From: twcook Date: Thu, 14 May 2026 07:57:07 -0500 Subject: [PATCH 5/6] refactor(sdc-agents): move under tools/ to match apihub_tool convention Per Dean's review on PR #106: BaseToolset implementations belong under src/google/adk_community/tools/ alongside spraay, not at the adk_community package root. Mirrors the core adk-python convention where toolsets like apihub_tool live under src/google/adk/tools/. - Move sdc_agents/ to tools/sdc_agents/ (git mv preserves history) - Update public import path to google.adk_community.tools.sdc_agents - Update test imports, demo agent imports, and the module README usage example - Drop the optional-import try/except in adk_community/__init__.py; matches the spraay precedent where optional extras fail at the user import site rather than being eagerly imported at package init --- contributing/samples/sdc_agents_demo/agent.py | 2 +- src/google/adk_community/__init__.py | 4 ---- .../adk_community/{ => tools}/sdc_agents/README.md | 2 +- .../adk_community/{ => tools}/sdc_agents/__init__.py | 0 tests/unittests/test_sdc_agents_imports.py | 10 +++++----- 5 files changed, 7 insertions(+), 11 deletions(-) rename src/google/adk_community/{ => tools}/sdc_agents/README.md (98%) rename src/google/adk_community/{ => tools}/sdc_agents/__init__.py (100%) diff --git a/contributing/samples/sdc_agents_demo/agent.py b/contributing/samples/sdc_agents_demo/agent.py index 3db8b585..1fb1de1f 100644 --- a/contributing/samples/sdc_agents_demo/agent.py +++ b/contributing/samples/sdc_agents_demo/agent.py @@ -31,7 +31,7 @@ from google.adk.agents import LlmAgent -from google.adk_community.sdc_agents import ( +from google.adk_community.tools.sdc_agents import ( CatalogToolset, IntrospectToolset, MappingToolset, diff --git a/src/google/adk_community/__init__.py b/src/google/adk_community/__init__.py index fb0b7d69..98c0e33b 100644 --- a/src/google/adk_community/__init__.py +++ b/src/google/adk_community/__init__.py @@ -16,8 +16,4 @@ from . import sessions from . import version -try: - from . import sdc_agents -except ImportError: - pass # Optional: pip install google-adk-community[sdc-agents] __version__ = version.__version__ diff --git a/src/google/adk_community/sdc_agents/README.md b/src/google/adk_community/tools/sdc_agents/README.md similarity index 98% rename from src/google/adk_community/sdc_agents/README.md rename to src/google/adk_community/tools/sdc_agents/README.md index c1f67144..7b155585 100644 --- a/src/google/adk_community/sdc_agents/README.md +++ b/src/google/adk_community/tools/sdc_agents/README.md @@ -17,7 +17,7 @@ pip install google-adk-community[sdc-agents] ```python from google.adk.agents import LlmAgent -from google.adk_community.sdc_agents import ( +from google.adk_community.tools.sdc_agents import ( load_config, CatalogToolset, IntrospectToolset, diff --git a/src/google/adk_community/sdc_agents/__init__.py b/src/google/adk_community/tools/sdc_agents/__init__.py similarity index 100% rename from src/google/adk_community/sdc_agents/__init__.py rename to src/google/adk_community/tools/sdc_agents/__init__.py diff --git a/tests/unittests/test_sdc_agents_imports.py b/tests/unittests/test_sdc_agents_imports.py index 148c6cea..617ce605 100644 --- a/tests/unittests/test_sdc_agents_imports.py +++ b/tests/unittests/test_sdc_agents_imports.py @@ -35,16 +35,16 @@ class TestSDCAgentsImports: """Validate that the community re-export module exposes all toolsets.""" def test_module_importable(self): - mod = importlib.import_module("google.adk_community.sdc_agents") + mod = importlib.import_module("google.adk_community.tools.sdc_agents") assert mod is not None def test_load_config_exported(self): - from google.adk_community.sdc_agents import load_config + from google.adk_community.tools.sdc_agents import load_config assert callable(load_config) def test_sdc_agents_config_exported(self): - from google.adk_community.sdc_agents import SDCAgentsConfig + from google.adk_community.tools.sdc_agents import SDCAgentsConfig assert SDCAgentsConfig is not None @@ -62,12 +62,12 @@ def test_sdc_agents_config_exported(self): ], ) def test_toolset_exported(self, name: str): - mod = importlib.import_module("google.adk_community.sdc_agents") + mod = importlib.import_module("google.adk_community.tools.sdc_agents") cls = getattr(mod, name, None) assert cls is not None, f"{name} not found in sdc_agents module" def test_all_list_complete(self): - from google.adk_community import sdc_agents + from google.adk_community.tools import sdc_agents expected = { "load_config", From 6fed50c086e7071b7f5343556248c037cb2c111d Mon Sep 17 00:00:00 2001 From: twcook Date: Fri, 15 May 2026 07:52:03 -0500 Subject: [PATCH 6/6] docs(sdc-agents-demo): align datasource singular in docstring Bot review nit: docstring used plural "datasources" while the workflow description uses singular "datasource" throughout. Pick singular. --- contributing/samples/sdc_agents_demo/agent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributing/samples/sdc_agents_demo/agent.py b/contributing/samples/sdc_agents_demo/agent.py index 1fb1de1f..ca3a5fa0 100644 --- a/contributing/samples/sdc_agents_demo/agent.py +++ b/contributing/samples/sdc_agents_demo/agent.py @@ -15,7 +15,7 @@ """SDC Agents demo -- full data governance pipeline. Composes five SDC Agents toolsets into a single LlmAgent that can -introspect datasources, discover matching catalog components, map +introspect a datasource, discover matching catalog components, map columns to schemas, and assemble validated data models. Prerequisites: