Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ jobs:
- name: Setup Python
uses: 'actions/setup-python@v6'
with:
python-version-file: "pyproject.toml"
python-version-file: "adk/pyproject.toml"
pip-install: "pre-commit"

- name: Install dependencies
run: uv sync --all-packages
run: make build

- name: Configure precommit
run: pre-commit install
28 changes: 18 additions & 10 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,19 @@ jobs:
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/agentic-layer-sdk-adk
url: ${{ matrix.pypi_url }}
permissions:
id-token: write
strategy:
max-parallel: 1
matrix:
include:
- package: adk
directory: adk
pypi_url: https://pypi.org/p/agentic-layer-sdk-adk
- package: msaf
directory: msaf
pypi_url: https://pypi.org/p/agentic-layer-sdk-msaf

steps:
- name: 'Checkout'
Expand All @@ -26,21 +36,19 @@ jobs:
- name: Setup Python
uses: 'actions/setup-python@v6'
with:
python-version-file: "pyproject.toml"

- name: Install Dependencies
working-directory: adk
run: uv sync
python-version-file: "adk/pyproject.toml"

- name: uv Version Bump
working-directory: adk
working-directory: ${{ matrix.directory }}
run: |-
VERSION=${{ github.ref_name }}
uv version "${VERSION#v}"

- name: 'Build adk package'
working-directory: adk
- name: Build package
working-directory: ${{ matrix.directory }}
run: uv build

- name: 'Publish adk package to PyPI'
- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: ${{ matrix.directory }}/dist
6 changes: 5 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,12 @@ repos:
# uv version.
rev: 0.8.4
hooks:
# Update the uv lockfile
# Update the uv lockfile for adk
- id: uv-lock
args: ["--directory", "adk"]
# Update the uv lockfile for msaf
- id: uv-lock
args: ["--directory", "msaf"]

- repo: local
hooks:
Expand Down
7 changes: 5 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ This is a Python SDK monorepo for the Agentic Layer platform that helps convert

### Package Structure
- Root package: `agentic-layer-sdk` (meta-package)
- Main SDK: `agentic-layer-sdk-adk` in `adk/agenticlayer/`
- Uses uv workspace configuration with `adk/` as a workspace member
- Shared: `agentic-layer-sdk-shared` in `shared/agenticlayer/` (namespace base, build-time only)
- ADK SDK: `agentic-layer-sdk-adk` in `adk/agenticlayer/adk/`
- MSAF SDK: `agentic-layer-sdk-msaf` in `msaf/agenticlayer/msaf/`
- Uses PEP 420 implicit namespace packages: `agenticlayer/` dirs have NO `__init__.py`
- Uses uv workspace configuration with `adk/` and `msaf/` as workspace members

## Development Commands

Expand Down
16 changes: 8 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,23 @@ all: build

.PHONY: build
build:
uv sync --all-packages
$(MAKE) -C adk build
$(MAKE) -C msaf build


.PHONY: test
test: build
uv run pytest
$(MAKE) -C adk test
$(MAKE) -C msaf test


.PHONY: check
check: build
uv run ruff check
uv run mypy .
uv run bandit -c pyproject.toml -r .
make test
$(MAKE) -C adk check
$(MAKE) -C msaf check


.PHONY: check-fix
check-fix: build
uv run ruff format
uv run ruff check --fix
$(MAKE) -C adk check-fix
$(MAKE) -C msaf check-fix
26 changes: 26 additions & 0 deletions adk/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.PHONY: all
all: build


.PHONY: build
build:
uv sync


.PHONY: test
test: build
uv run pytest


.PHONY: check
check: build
uv run ruff check
uv run mypy .
uv run bandit -c pyproject.toml -r .
make test


.PHONY: check-fix
check-fix: build
uv run ruff format
uv run ruff check --fix
5 changes: 3 additions & 2 deletions adk/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ pip install agentic-layer-sdk-adk
Basic usage example:

```python
from agenticlayer.agent_to_a2a import to_a2a
from agenticlayer.config import parse_sub_agents, parse_tools
from agenticlayer.otel import setup_otel
from google.adk.agents import LlmAgent

from agenticlayer.adk.agent_to_a2a import to_a2a
from agenticlayer.adk.otel import setup_otel

# Set up OpenTelemetry instrumentation, logging and metrics
setup_otel()

Expand Down
4 changes: 0 additions & 4 deletions adk/agenticlayer/__init__.py

This file was deleted.

1 change: 1 addition & 0 deletions adk/agenticlayer/adk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Google ADK adapter for the Agentic Layer SDK."""
5 changes: 2 additions & 3 deletions adk/agenticlayer/agent.py → adk/agenticlayer/adk/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import httpx
from a2a.client import A2ACardResolver
from a2a.utils.constants import AGENT_CARD_WELL_KNOWN_PATH
from agenticlayer.config import InteractionType, McpTool, SubAgent
from agenticlayer.constants import HTTP_HEADERS_SESSION_KEY
from google.adk.agents import BaseAgent, LlmAgent
from google.adk.agents.llm_agent import ToolUnion
from google.adk.agents.readonly_context import ReadonlyContext
Expand All @@ -17,9 +19,6 @@
from google.adk.tools.mcp_tool.mcp_toolset import McpToolset
from httpx_retries import Retry, RetryTransport

from agenticlayer.config import InteractionType, McpTool, SubAgent
from agenticlayer.constants import HTTP_HEADERS_SESSION_KEY

logger = logging.getLogger(__name__)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from a2a.server.tasks import InMemoryTaskStore
from a2a.types import AgentCapabilities, AgentCard
from a2a.utils.constants import AGENT_CARD_WELL_KNOWN_PATH
from agenticlayer.config import McpTool, SubAgent
from agenticlayer.constants import HTTP_HEADERS_SESSION_KEY
from google.adk.a2a.converters.request_converter import AgentRunRequest
from google.adk.a2a.executor.a2a_agent_executor import A2aAgentExecutor
from google.adk.agents import LlmAgent
Expand All @@ -28,11 +30,9 @@
from google.adk.sessions.session import Session
from starlette.applications import Starlette

from .agent import AgentFactory
from .callback_tracer_plugin import CallbackTracerPlugin
from .config import McpTool, SubAgent
from .constants import HTTP_HEADERS_SESSION_KEY
from .metrics_plugin import MetricsPlugin
from agenticlayer.adk.agent import AgentFactory
from agenticlayer.adk.callback_tracer_plugin import CallbackTracerPlugin
from agenticlayer.adk.metrics_plugin import MetricsPlugin

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -224,7 +224,7 @@ async def lifespan(app: Starlette) -> AsyncIterator[None]:
starlette_app = Starlette(lifespan=lifespan)

# Instrument the Starlette app with OpenTelemetry
from .otel_starlette import instrument_starlette_app
from agenticlayer.otel_starlette import instrument_starlette_app

instrument_starlette_app(starlette_app)

Expand Down
23 changes: 23 additions & 0 deletions adk/agenticlayer/adk/otel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""OpenTelemetry setup for a Google ADK Agent App."""

from agenticlayer._otel import (
_decode_body,
_is_text_content,
request_hook,
response_hook,
)
from agenticlayer._otel import (
setup_otel as _setup_otel_base,
)

__all__ = ["_decode_body", "_is_text_content", "request_hook", "response_hook", "setup_otel"]


def setup_otel() -> None:
"""Set up OpenTelemetry tracing, logging and metrics, including Google ADK instrumentation."""
_setup_otel_base()

# Instrument Google ADK using openinference instrumentation
from openinference.instrumentation.google_adk import GoogleADKInstrumentor

GoogleADKInstrumentor().instrument()
File renamed without changes.
77 changes: 72 additions & 5 deletions adk/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,88 @@
name = "agentic-layer-sdk-adk"
version = "0.1.0"
readme = "README.md"
requires-python = ">=3.12"
requires-python = ">=3.14,<3.15"
dependencies = [
"agentic-layer-sdk-shared",
"google-adk[a2a]",
"litellm",
"opentelemetry-exporter-otlp-proto-http",
"opentelemetry-exporter-otlp-proto-grpc",
"opentelemetry-instrumentation-starlette",
"openinference-instrumentation-google-adk",
"opentelemetry-instrumentation-httpx",
"httpx-retries>=0.4.5",
]

[dependency-groups]
dev = [
"mypy[reports]>=1.12.0,<2",
"ruff>=0.11.2",
"bandit[toml]>=1.7.8",
"pip-audit>=2.5,<3",
"pytest>=9.0.1,<10",
"pytest-cov>=7,<8",
"types-protobuf>=6.30.2.20250822",
"pytest-asyncio>=1.3.0",
"asgi-lifespan>=2.1.0",
"respx>=0.22.0",
"fastmcp>=3.0.0rc2",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["agenticlayer"]

[tool.uv.sources]
agentic-layer-sdk-shared = { path = "../shared" }


[tool.pytest.ini_options]
minversion = "7.0"
testpaths = "tests"
pythonpath = [".", "../shared"]
addopts = """\
--strict-config \
--cov agenticlayer/adk \
--cov-report html \
--import-mode=importlib \
--show-capture=no \
"""
filterwarnings = [
# https://github.com/boto/boto3/issues/3889
"ignore::UserWarning:google.adk.*",
"ignore::DeprecationWarning:google.*",
"ignore::DeprecationWarning:litellm.*",
"ignore::DeprecationWarning:a2a.*",
"ignore::UserWarning:agenticlayer.*",
# google-adk uses the deprecated streamablehttp_client from mcp; suppress until upstream fixes it
"ignore:Use `streamable_http_client` instead.:DeprecationWarning",
]


[tool.ruff]
# Allow lines to be as long as 120.
line-length = 120

[tool.ruff.lint]
# https://docs.astral.sh/ruff/rules/
# I001 --> enable import sorting rules
# Q --> enable flake8-quotes rules for consistent quote style
# N --> pep8-naming for proper naming conventions
# PT --> flake8-pytest-style for pytest best practices
# TID251 --> banned relative imports
# DTZ --> datetime timezone awareness
extend-select = ["Q", "N", "I001", "PT", "TID251", "DTZ"]


[tool.bandit]
exclude_dirs = [".venv"]

[tool.bandit.assert_used]
skips = ["**/tests/*"]


[tool.mypy]
strict = true
explicit_package_bases = true
mypy_path = ["."]
namespace_packages = true
5 changes: 3 additions & 2 deletions adk/tests/fixtures/app_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
from typing import Any

import pytest_asyncio
from agenticlayer.agent import AgentFactory
from agenticlayer.agent_to_a2a import to_a2a
from agenticlayer.config import McpTool, SubAgent
from asgi_lifespan import LifespanManager
from google.adk.agents import LlmAgent
from httpx_retries import Retry

from agenticlayer.adk.agent import AgentFactory
from agenticlayer.adk.agent_to_a2a import to_a2a


@pytest_asyncio.fixture
def app_factory() -> Any:
Expand Down
4 changes: 2 additions & 2 deletions adk/tests/test_agent_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import pytest
import respx
from a2a.client.errors import A2AClientHTTPError
from agenticlayer.agent import AgentFactory
from agenticlayer.agent_to_a2a import to_a2a
from agenticlayer.config import InteractionType, McpTool, SubAgent
from agenticlayer.loguru_config import setup_logging
from asgi_lifespan import LifespanManager
Expand All @@ -16,6 +14,8 @@
from pydantic import AnyHttpUrl
from starlette.testclient import TestClient

from agenticlayer.adk.agent import AgentFactory
from agenticlayer.adk.agent_to_a2a import to_a2a
from tests.fixtures.mock_llm import LLMMockController
from tests.utils.helpers import (
create_asgi_request_handler,
Expand Down
Loading