Skip to content

Commit 03226d0

Browse files
committed
ref(adk): migrate ADK wrapper to integrations API
Convert the Google ADK (Agent Development Kit) instrumentation from the legacy wrappers pattern to the new integrations API introduced in #118. - Extract tracing helpers into integrations/adk/tracing.py - Create ADK patchers (agent, runner, flow, mcp_tool) in patchers.py - Add AdkIntegration class with proper registration - Move tests and cassettes from wrappers/adk/ to integrations/adk/ - Move auto_instrument test script to integrations/auto_test_scripts/ - Slim down wrappers/adk/__init__.py to delegate to integrations - Update noxfile.py with ADK integration test sessions - Update integrations base and registry for ADK support
1 parent 363baa0 commit 03226d0

22 files changed

Lines changed: 1889 additions & 777 deletions

py/noxfile.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ def _pinned_python_version():
4141
SRC_DIR = "braintrust"
4242
WRAPPER_DIR = "braintrust/wrappers"
4343
INTEGRATION_DIR = "braintrust/integrations"
44-
INTEGRATION_AUTO_TEST_DIR = "braintrust/integrations/auto_test_scripts"
45-
ANTHROPIC_INTEGRATION_DIR = "braintrust/integrations/anthropic"
4644
CONTRIB_DIR = "braintrust/contrib"
4745
DEVSERVER_DIR = "braintrust/devserver"
4846

@@ -198,8 +196,8 @@ def test_google_adk(session, version):
198196
"""Test Google ADK integration."""
199197
_install_test_deps(session)
200198
_install(session, "google-adk", version)
201-
_run_tests(session, f"{WRAPPER_DIR}/adk/test_adk.py")
202-
_run_tests(session, f"{WRAPPER_DIR}/adk/test_adk_mcp_tool.py")
199+
_run_tests(session, f"{INTEGRATION_DIR}/adk/test_adk.py")
200+
_run_tests(session, f"{INTEGRATION_DIR}/adk/test_adk_mcp_tool.py")
203201
_run_core_tests(session)
204202

205203

@@ -407,7 +405,12 @@ def _run_core_tests(session):
407405
_run_tests(
408406
session,
409407
SRC_DIR,
410-
ignore_paths=[WRAPPER_DIR, INTEGRATION_AUTO_TEST_DIR, ANTHROPIC_INTEGRATION_DIR, CONTRIB_DIR, DEVSERVER_DIR],
408+
ignore_paths=[
409+
WRAPPER_DIR,
410+
INTEGRATION_DIR,
411+
CONTRIB_DIR,
412+
DEVSERVER_DIR,
413+
],
411414
)
412415

413416

py/src/braintrust/auto.py

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import logging
1010
from contextlib import contextmanager
1111

12-
from braintrust.integrations import AnthropicIntegration, IntegrationPatchConfig
12+
from braintrust.integrations import ADKIntegration, AnthropicIntegration, IntegrationPatchConfig
1313

1414

1515
__all__ = ["auto_instrument"]
@@ -39,7 +39,7 @@ def auto_instrument(
3939
agno: bool = True,
4040
claude_agent_sdk: bool = True,
4141
dspy: bool = True,
42-
adk: bool = True,
42+
adk: InstrumentOption = True,
4343
) -> dict[str, bool]:
4444
"""
4545
Auto-instrument supported AI/ML libraries for Braintrust tracing.
@@ -109,14 +109,14 @@ def auto_instrument(
109109
results = {}
110110

111111
openai_enabled = _normalize_bool_option("openai", openai)
112-
anthropic_enabled, anthropic_config = _normalize_anthropic_option(anthropic)
112+
anthropic_enabled, anthropic_config = _normalize_instrument_option("anthropic", anthropic)
113113
litellm_enabled = _normalize_bool_option("litellm", litellm)
114114
pydantic_ai_enabled = _normalize_bool_option("pydantic_ai", pydantic_ai)
115115
google_genai_enabled = _normalize_bool_option("google_genai", google_genai)
116116
agno_enabled = _normalize_bool_option("agno", agno)
117117
claude_agent_sdk_enabled = _normalize_bool_option("claude_agent_sdk", claude_agent_sdk)
118118
dspy_enabled = _normalize_bool_option("dspy", dspy)
119-
adk_enabled = _normalize_bool_option("adk", adk)
119+
adk_enabled, adk_config = _normalize_instrument_option("adk", adk)
120120

121121
if openai_enabled:
122122
results["openai"] = _instrument_openai()
@@ -135,7 +135,7 @@ def auto_instrument(
135135
if dspy_enabled:
136136
results["dspy"] = _instrument_dspy()
137137
if adk_enabled:
138-
results["adk"] = _instrument_adk()
138+
results["adk"] = _instrument_integration(ADKIntegration, patch_config=adk_config)
139139

140140
return results
141141

@@ -164,15 +164,15 @@ def _normalize_bool_option(name: str, option: bool) -> bool:
164164
raise TypeError(f"auto_instrument option {name!r} must be a bool, got {type(option).__name__}")
165165

166166

167-
def _normalize_anthropic_option(option: InstrumentOption) -> tuple[bool, IntegrationPatchConfig | None]:
167+
def _normalize_instrument_option(name: str, option: InstrumentOption) -> tuple[bool, IntegrationPatchConfig | None]:
168168
if isinstance(option, bool):
169169
return option, None
170170

171171
if isinstance(option, IntegrationPatchConfig):
172172
return True, option
173173

174174
raise TypeError(
175-
f"auto_instrument option 'anthropic' must be a bool or IntegrationPatchConfig, got {type(option).__name__}"
175+
f"auto_instrument option {name} must be a bool or IntegrationPatchConfig, got {type(option).__name__}"
176176
)
177177

178178

@@ -222,11 +222,3 @@ def _instrument_dspy() -> bool:
222222

223223
return patch_dspy()
224224
return False
225-
226-
227-
def _instrument_adk() -> bool:
228-
with _try_patch():
229-
from braintrust.wrappers.adk import setup_adk
230-
231-
return setup_adk()
232-
return False
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
from .adk import ADKIntegration
12
from .anthropic import AnthropicIntegration
23
from .base import IntegrationPatchConfig
34

45

5-
__all__ = ["AnthropicIntegration", "IntegrationPatchConfig"]
6+
__all__ = ["ADKIntegration", "AnthropicIntegration", "IntegrationPatchConfig"]
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
"""Braintrust integration for Google ADK."""
2+
3+
import logging
4+
import warnings
5+
6+
from braintrust.logger import NOOP_SPAN, current_span, init_logger
7+
8+
from .integration import ADKIntegration
9+
from .patchers import (
10+
wrap_agent,
11+
wrap_flow,
12+
wrap_mcp_tool,
13+
wrap_runner,
14+
)
15+
from .tracing import _create_thread_wrapper
16+
17+
18+
logger = logging.getLogger(__name__)
19+
20+
__all__ = [
21+
"ADKIntegration",
22+
"_create_thread_wrapper",
23+
"setup_adk",
24+
"setup_braintrust",
25+
"wrap_agent",
26+
"wrap_runner",
27+
"wrap_flow",
28+
"wrap_mcp_tool",
29+
]
30+
31+
32+
def setup_braintrust(*args, **kwargs):
33+
warnings.warn("setup_braintrust is deprecated, use setup_adk instead", DeprecationWarning, stacklevel=2)
34+
return setup_adk(*args, **kwargs)
35+
36+
37+
def setup_adk(
38+
api_key: str | None = None,
39+
project_id: str | None = None,
40+
project_name: str | None = None,
41+
SpanProcessor: type | None = None,
42+
) -> bool:
43+
"""
44+
Setup Braintrust integration with Google ADK. Will automatically patch Google ADK agents, runners, flows, and MCP tools for automatic tracing.
45+
46+
If you prefer manual patching take a look at `wrap_agent`, `wrap_runner`, `wrap_flow`, and `wrap_mcp_tool`.
47+
48+
Args:
49+
api_key (Optional[str]): Braintrust API key.
50+
project_id (Optional[str]): Braintrust project ID.
51+
project_name (Optional[str]): Braintrust project name.
52+
SpanProcessor (Optional[type]): Deprecated parameter.
53+
54+
Returns:
55+
bool: True if setup was successful, False otherwise.
56+
"""
57+
if SpanProcessor is not None:
58+
warnings.warn("SpanProcessor parameter is deprecated and will be ignored", DeprecationWarning, stacklevel=2)
59+
60+
span = current_span()
61+
if span == NOOP_SPAN:
62+
init_logger(project=project_name, api_key=api_key, project_id=project_id)
63+
64+
return ADKIntegration.setup()

0 commit comments

Comments
 (0)