feat(google-adk): add ADK instrumentation and e2e coverage - #1765

Merged
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation
Apr 14, 2026
Merged

feat(google-adk): add ADK instrumentation and e2e coverage#1765
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation

Conversation

@AbhiPrasad

@AbhiPrasadAbhijeet Prasad (AbhiPrasad) commented Apr 9, 2026

Copy link
Copy Markdown
Member

resolves#1477

Add Braintrust instrumentation for @google/adk with auto-instrumentation support by default when users run with Braintrust's loader hook.

This adds tracing for:

  • Runner.runAsync
  • BaseAgent.runAsync and subclasses
  • FunctionTool.runAsync

It also adds Google ADK e2e coverage for both hook-driven and wrapped execution.

Because ADK uses @google/genai under the hood, underlying LLM spans continue to come from the existing Google GenAI instrumentation.

Recommended usage: auto-instrumentation

The primary way users should adopt this is via Braintrust auto-instrumentation:

node --import braintrust/hook.mjs app.mjs

Then they can use @google/adk normally and Braintrust will trace supported ADK operations automatically.

Example:

import*asadkfrom"@google/adk";import{initLogger}from"braintrust";initLogger({projectName: "my-google-adk-app"});constagent=newadk.LlmAgent({name: "weather_agent",model: "gemini-2.5-flash-lite",instruction: "Answer weather questions",});construnner=newadk.InMemoryRunner({ agent,appName: "weather-app"});awaitrunner.sessionService.createSession({appName: runner.appName,userId: "user-1",sessionId: "session-1",});forawait(consteventofrunner.runAsync({userId: "user-1",sessionId: "session-1",newMessage: {role: "user",parts: [{text: "What's the weather in Paris?"}],},})){console.log(event);}

If needed, it can be disabled with:

BRAINTRUST_DISABLE_INSTRUMENTATION=google-adk node --import braintrust/hook.mjs app.mjs

Manual usage

Manual wrapping is also available for cases where users want explicit control:

import*asadkfrom"@google/adk";import{wrapGoogleADK}from"braintrust";constwrapped=wrapGoogleADK(adk);

Screenshot

image

@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

wait this need some more work. I realized the parent child relationships are wrong 😢

Comment threadjs/src/auto-instrumentations/configs/google-adk.test.ts Outdated
Comment threade2e/scenarios/google-adk-instrumentation/assertions.ts
@lforst

Copy link
Copy Markdown
Member

wait this need some more work. I realized the parent child relationships are wrong 😢

I honestly don't know why this is so painful in this SDK. Tracing channels make it harder because they are event based. It should honestly just be a simple wrapping call imo.

@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the feat/google-adk-instrumentation branch 2 times, most recently from 45ea59e to 19c40c1CompareApril 13, 2026 14:11
Add manual and load-time instrumentation for `@google/adk` across runner,
agent, and tool execution. This introduces the wrapper entrypoint,
tracing-channel plugin, vendored SDK types, exports, and loader config needed
to emit Braintrust spans for Google ADK workflows.
Add a dedicated Google ADK e2e scenario with a committed lockfile and stable
snapshots for both wrapped and hook-driven execution.
Stabilize the scenario by pre-creating ADK sessions, letting the loader hook
respect `BRAINTRUST_DISABLE_INSTRUMENTATION`, and normalizing volatile outputs
in the assertions so the coverage stays repeatable.
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) marked this pull request as ready for review April 13, 2026 14:11
@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

Okay fixed the parent-child relationships! This is good to review now.

@socket-security

socket-securityBot commented Apr 13, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

DiffPackageSupply Chain
Security
VulnerabilityQualityMaintenanceLicense
Updatednext@​15.5.15 ⏵ 14.2.3482+2070-3095+450-4670
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 1.3.2471-110085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.5371-110085-398100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.200.07310010094100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.205.07310010094100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 2.6.17410083-493100
Addedopenai@​5.23.274100100100100
Added@​vercel/​otel@​0.1.01001007599100
Addedcohere-ai@​7.21.07510010093100
Addedcohere-ai@​8.0.07510010095100
Added@​types/​react-dom@​18.3.71001007686100
Added@​braintrust/​otel@​0.1.27710010088100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 2.0.078+110010093100
Addedcohere-ai@​7.20.08210010088100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 0.0.62100+2810083-597-1100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.205.0100+110084-194100
Updatedreact@​19.2.5 ⏵ 18.3.110010084+197100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.35.0100+11008591-3100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.57100+2810085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 3.0.799+2710086-298100
Updated@​opentelemetry/​otlp-transformer@​0.53.0 ⏵ 0.35.0100+110087-391-3100
Added@​vercel/​otel@​2.1.0991009787100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 1.9.0100+2710088+188-5100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 1.9.0100+2210010088-5100
Addedzod@​4.1.1110010010088100
Updatedai@​6.0.159 ⏵ 5.0.7689-1010010099100
Addedtypescript@​5.4.4100100909990
Updatedbraintrust@​2.2.2 ⏵ 2.2.1-rc.090+11009097100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.35.099+2610010091-3100
Updatedreact-dom@​19.2.5 ⏵ 18.3.192-71009298100
Updatedai@​6.0.159 ⏵ 6.0.192-810010099100
Addedcohere-ai@​7.14.09710010093100
See 15 more rows in the dashboard

View full report

@lforst
Luca Forstner (lforst)force-pushed the feat/google-adk-instrumentation branch from 4739528 to 3ae014bCompareApril 13, 2026 19:39
@lforst

Copy link
Copy Markdown
Member

The wrapper is still not perfect. It's not capturing llm spans. I am still gonna merge because the package has too little downloads to justify putting more work in.

@lforst
Luca Forstner (lforst) merged commit df3434d into mainApr 14, 2026
45 of 49 checks passed
@lforst
Luca Forstner (lforst) deleted the feat/google-adk-instrumentation branch April 14, 2026 09:47
Sign up for freeto 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.

Integration for Google Agent Development Kit (ADK) for TypeScript

2 participants

@AbhiPrasad@lforst
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(google-adk): add ADK instrumentation and e2e coverage - #1765

Merged
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation
Apr 14, 2026
Merged

feat(google-adk): add ADK instrumentation and e2e coverage#1765
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation

Conversation

@AbhiPrasad

@AbhiPrasadAbhijeet Prasad (AbhiPrasad) commented Apr 9, 2026

Copy link
Copy Markdown
Member

resolves#1477

Add Braintrust instrumentation for @google/adk with auto-instrumentation support by default when users run with Braintrust's loader hook.

This adds tracing for:

  • Runner.runAsync
  • BaseAgent.runAsync and subclasses
  • FunctionTool.runAsync

It also adds Google ADK e2e coverage for both hook-driven and wrapped execution.

Because ADK uses @google/genai under the hood, underlying LLM spans continue to come from the existing Google GenAI instrumentation.

Recommended usage: auto-instrumentation

The primary way users should adopt this is via Braintrust auto-instrumentation:

node --import braintrust/hook.mjs app.mjs

Then they can use @google/adk normally and Braintrust will trace supported ADK operations automatically.

Example:

import*asadkfrom"@google/adk";import{initLogger}from"braintrust";initLogger({projectName: "my-google-adk-app"});constagent=newadk.LlmAgent({name: "weather_agent",model: "gemini-2.5-flash-lite",instruction: "Answer weather questions",});construnner=newadk.InMemoryRunner({ agent,appName: "weather-app"});awaitrunner.sessionService.createSession({appName: runner.appName,userId: "user-1",sessionId: "session-1",});forawait(consteventofrunner.runAsync({userId: "user-1",sessionId: "session-1",newMessage: {role: "user",parts: [{text: "What's the weather in Paris?"}],},})){console.log(event);}

If needed, it can be disabled with:

BRAINTRUST_DISABLE_INSTRUMENTATION=google-adk node --import braintrust/hook.mjs app.mjs

Manual usage

Manual wrapping is also available for cases where users want explicit control:

import*asadkfrom"@google/adk";import{wrapGoogleADK}from"braintrust";constwrapped=wrapGoogleADK(adk);

Screenshot

image

@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

wait this need some more work. I realized the parent child relationships are wrong 😢

Comment threadjs/src/auto-instrumentations/configs/google-adk.test.ts Outdated
Comment threade2e/scenarios/google-adk-instrumentation/assertions.ts
@lforst

Copy link
Copy Markdown
Member

wait this need some more work. I realized the parent child relationships are wrong 😢

I honestly don't know why this is so painful in this SDK. Tracing channels make it harder because they are event based. It should honestly just be a simple wrapping call imo.

@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the feat/google-adk-instrumentation branch 2 times, most recently from 45ea59e to 19c40c1CompareApril 13, 2026 14:11
Add manual and load-time instrumentation for `@google/adk` across runner,
agent, and tool execution. This introduces the wrapper entrypoint,
tracing-channel plugin, vendored SDK types, exports, and loader config needed
to emit Braintrust spans for Google ADK workflows.
Add a dedicated Google ADK e2e scenario with a committed lockfile and stable
snapshots for both wrapped and hook-driven execution.
Stabilize the scenario by pre-creating ADK sessions, letting the loader hook
respect `BRAINTRUST_DISABLE_INSTRUMENTATION`, and normalizing volatile outputs
in the assertions so the coverage stays repeatable.
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) marked this pull request as ready for review April 13, 2026 14:11
@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

Okay fixed the parent-child relationships! This is good to review now.

@socket-security

socket-securityBot commented Apr 13, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

DiffPackageSupply Chain
Security
VulnerabilityQualityMaintenanceLicense
Updatednext@​15.5.15 ⏵ 14.2.3482+2070-3095+450-4670
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 1.3.2471-110085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.5371-110085-398100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.200.07310010094100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.205.07310010094100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 2.6.17410083-493100
Addedopenai@​5.23.274100100100100
Added@​vercel/​otel@​0.1.01001007599100
Addedcohere-ai@​7.21.07510010093100
Addedcohere-ai@​8.0.07510010095100
Added@​types/​react-dom@​18.3.71001007686100
Added@​braintrust/​otel@​0.1.27710010088100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 2.0.078+110010093100
Addedcohere-ai@​7.20.08210010088100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 0.0.62100+2810083-597-1100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.205.0100+110084-194100
Updatedreact@​19.2.5 ⏵ 18.3.110010084+197100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.35.0100+11008591-3100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.57100+2810085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 3.0.799+2710086-298100
Updated@​opentelemetry/​otlp-transformer@​0.53.0 ⏵ 0.35.0100+110087-391-3100
Added@​vercel/​otel@​2.1.0991009787100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 1.9.0100+2710088+188-5100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 1.9.0100+2210010088-5100
Addedzod@​4.1.1110010010088100
Updatedai@​6.0.159 ⏵ 5.0.7689-1010010099100
Addedtypescript@​5.4.4100100909990
Updatedbraintrust@​2.2.2 ⏵ 2.2.1-rc.090+11009097100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.35.099+2610010091-3100
Updatedreact-dom@​19.2.5 ⏵ 18.3.192-71009298100
Updatedai@​6.0.159 ⏵ 6.0.192-810010099100
Addedcohere-ai@​7.14.09710010093100
See 15 more rows in the dashboard

View full report

@lforst
Luca Forstner (lforst)force-pushed the feat/google-adk-instrumentation branch from 4739528 to 3ae014bCompareApril 13, 2026 19:39
@lforst

Copy link
Copy Markdown
Member

The wrapper is still not perfect. It's not capturing llm spans. I am still gonna merge because the package has too little downloads to justify putting more work in.

@lforst
Luca Forstner (lforst) merged commit df3434d into mainApr 14, 2026
45 of 49 checks passed
@lforst
Luca Forstner (lforst) deleted the feat/google-adk-instrumentation branch April 14, 2026 09:47
Sign up for freeto 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.

Integration for Google Agent Development Kit (ADK) for TypeScript

2 participants

@AbhiPrasad@lforst
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(google-adk): add ADK instrumentation and e2e coverage - #1765

Merged
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation
Apr 14, 2026
Merged

feat(google-adk): add ADK instrumentation and e2e coverage#1765
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation

Conversation

@AbhiPrasad

@AbhiPrasadAbhijeet Prasad (AbhiPrasad) commented Apr 9, 2026

Copy link
Copy Markdown
Member

resolves#1477

Add Braintrust instrumentation for @google/adk with auto-instrumentation support by default when users run with Braintrust's loader hook.

This adds tracing for:

  • Runner.runAsync
  • BaseAgent.runAsync and subclasses
  • FunctionTool.runAsync

It also adds Google ADK e2e coverage for both hook-driven and wrapped execution.

Because ADK uses @google/genai under the hood, underlying LLM spans continue to come from the existing Google GenAI instrumentation.

Recommended usage: auto-instrumentation

The primary way users should adopt this is via Braintrust auto-instrumentation:

node --import braintrust/hook.mjs app.mjs

Then they can use @google/adk normally and Braintrust will trace supported ADK operations automatically.

Example:

import*asadkfrom"@google/adk";import{initLogger}from"braintrust";initLogger({projectName: "my-google-adk-app"});constagent=newadk.LlmAgent({name: "weather_agent",model: "gemini-2.5-flash-lite",instruction: "Answer weather questions",});construnner=newadk.InMemoryRunner({ agent,appName: "weather-app"});awaitrunner.sessionService.createSession({appName: runner.appName,userId: "user-1",sessionId: "session-1",});forawait(consteventofrunner.runAsync({userId: "user-1",sessionId: "session-1",newMessage: {role: "user",parts: [{text: "What's the weather in Paris?"}],},})){console.log(event);}

If needed, it can be disabled with:

BRAINTRUST_DISABLE_INSTRUMENTATION=google-adk node --import braintrust/hook.mjs app.mjs

Manual usage

Manual wrapping is also available for cases where users want explicit control:

import*asadkfrom"@google/adk";import{wrapGoogleADK}from"braintrust";constwrapped=wrapGoogleADK(adk);

Screenshot

image

@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

wait this need some more work. I realized the parent child relationships are wrong 😢

Comment threadjs/src/auto-instrumentations/configs/google-adk.test.ts Outdated
Comment threade2e/scenarios/google-adk-instrumentation/assertions.ts
@lforst

Copy link
Copy Markdown
Member

wait this need some more work. I realized the parent child relationships are wrong 😢

I honestly don't know why this is so painful in this SDK. Tracing channels make it harder because they are event based. It should honestly just be a simple wrapping call imo.

@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the feat/google-adk-instrumentation branch 2 times, most recently from 45ea59e to 19c40c1CompareApril 13, 2026 14:11
Add manual and load-time instrumentation for `@google/adk` across runner,
agent, and tool execution. This introduces the wrapper entrypoint,
tracing-channel plugin, vendored SDK types, exports, and loader config needed
to emit Braintrust spans for Google ADK workflows.
Add a dedicated Google ADK e2e scenario with a committed lockfile and stable
snapshots for both wrapped and hook-driven execution.
Stabilize the scenario by pre-creating ADK sessions, letting the loader hook
respect `BRAINTRUST_DISABLE_INSTRUMENTATION`, and normalizing volatile outputs
in the assertions so the coverage stays repeatable.
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) marked this pull request as ready for review April 13, 2026 14:11
@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

Okay fixed the parent-child relationships! This is good to review now.

@socket-security

socket-securityBot commented Apr 13, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

DiffPackageSupply Chain
Security
VulnerabilityQualityMaintenanceLicense
Updatednext@​15.5.15 ⏵ 14.2.3482+2070-3095+450-4670
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 1.3.2471-110085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.5371-110085-398100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.200.07310010094100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.205.07310010094100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 2.6.17410083-493100
Addedopenai@​5.23.274100100100100
Added@​vercel/​otel@​0.1.01001007599100
Addedcohere-ai@​7.21.07510010093100
Addedcohere-ai@​8.0.07510010095100
Added@​types/​react-dom@​18.3.71001007686100
Added@​braintrust/​otel@​0.1.27710010088100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 2.0.078+110010093100
Addedcohere-ai@​7.20.08210010088100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 0.0.62100+2810083-597-1100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.205.0100+110084-194100
Updatedreact@​19.2.5 ⏵ 18.3.110010084+197100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.35.0100+11008591-3100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.57100+2810085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 3.0.799+2710086-298100
Updated@​opentelemetry/​otlp-transformer@​0.53.0 ⏵ 0.35.0100+110087-391-3100
Added@​vercel/​otel@​2.1.0991009787100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 1.9.0100+2710088+188-5100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 1.9.0100+2210010088-5100
Addedzod@​4.1.1110010010088100
Updatedai@​6.0.159 ⏵ 5.0.7689-1010010099100
Addedtypescript@​5.4.4100100909990
Updatedbraintrust@​2.2.2 ⏵ 2.2.1-rc.090+11009097100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.35.099+2610010091-3100
Updatedreact-dom@​19.2.5 ⏵ 18.3.192-71009298100
Updatedai@​6.0.159 ⏵ 6.0.192-810010099100
Addedcohere-ai@​7.14.09710010093100
See 15 more rows in the dashboard

View full report

@lforst
Luca Forstner (lforst)force-pushed the feat/google-adk-instrumentation branch from 4739528 to 3ae014bCompareApril 13, 2026 19:39
@lforst

Copy link
Copy Markdown
Member

The wrapper is still not perfect. It's not capturing llm spans. I am still gonna merge because the package has too little downloads to justify putting more work in.

@lforst
Luca Forstner (lforst) merged commit df3434d into mainApr 14, 2026
45 of 49 checks passed
@lforst
Luca Forstner (lforst) deleted the feat/google-adk-instrumentation branch April 14, 2026 09:47
Sign up for freeto 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.

Integration for Google Agent Development Kit (ADK) for TypeScript

2 participants

@AbhiPrasad@lforst
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(google-adk): add ADK instrumentation and e2e coverage - #1765

Merged
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation
Apr 14, 2026
Merged

feat(google-adk): add ADK instrumentation and e2e coverage#1765
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation

Conversation

@AbhiPrasad

@AbhiPrasadAbhijeet Prasad (AbhiPrasad) commented Apr 9, 2026

Copy link
Copy Markdown
Member

resolves#1477

Add Braintrust instrumentation for @google/adk with auto-instrumentation support by default when users run with Braintrust's loader hook.

This adds tracing for:

  • Runner.runAsync
  • BaseAgent.runAsync and subclasses
  • FunctionTool.runAsync

It also adds Google ADK e2e coverage for both hook-driven and wrapped execution.

Because ADK uses @google/genai under the hood, underlying LLM spans continue to come from the existing Google GenAI instrumentation.

Recommended usage: auto-instrumentation

The primary way users should adopt this is via Braintrust auto-instrumentation:

node --import braintrust/hook.mjs app.mjs

Then they can use @google/adk normally and Braintrust will trace supported ADK operations automatically.

Example:

import*asadkfrom"@google/adk";import{initLogger}from"braintrust";initLogger({projectName: "my-google-adk-app"});constagent=newadk.LlmAgent({name: "weather_agent",model: "gemini-2.5-flash-lite",instruction: "Answer weather questions",});construnner=newadk.InMemoryRunner({ agent,appName: "weather-app"});awaitrunner.sessionService.createSession({appName: runner.appName,userId: "user-1",sessionId: "session-1",});forawait(consteventofrunner.runAsync({userId: "user-1",sessionId: "session-1",newMessage: {role: "user",parts: [{text: "What's the weather in Paris?"}],},})){console.log(event);}

If needed, it can be disabled with:

BRAINTRUST_DISABLE_INSTRUMENTATION=google-adk node --import braintrust/hook.mjs app.mjs

Manual usage

Manual wrapping is also available for cases where users want explicit control:

import*asadkfrom"@google/adk";import{wrapGoogleADK}from"braintrust";constwrapped=wrapGoogleADK(adk);

Screenshot

image

@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

wait this need some more work. I realized the parent child relationships are wrong 😢

Comment threadjs/src/auto-instrumentations/configs/google-adk.test.ts Outdated
Comment threade2e/scenarios/google-adk-instrumentation/assertions.ts
@lforst

Copy link
Copy Markdown
Member

wait this need some more work. I realized the parent child relationships are wrong 😢

I honestly don't know why this is so painful in this SDK. Tracing channels make it harder because they are event based. It should honestly just be a simple wrapping call imo.

@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the feat/google-adk-instrumentation branch 2 times, most recently from 45ea59e to 19c40c1CompareApril 13, 2026 14:11
Add manual and load-time instrumentation for `@google/adk` across runner,
agent, and tool execution. This introduces the wrapper entrypoint,
tracing-channel plugin, vendored SDK types, exports, and loader config needed
to emit Braintrust spans for Google ADK workflows.
Add a dedicated Google ADK e2e scenario with a committed lockfile and stable
snapshots for both wrapped and hook-driven execution.
Stabilize the scenario by pre-creating ADK sessions, letting the loader hook
respect `BRAINTRUST_DISABLE_INSTRUMENTATION`, and normalizing volatile outputs
in the assertions so the coverage stays repeatable.
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) marked this pull request as ready for review April 13, 2026 14:11
@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

Okay fixed the parent-child relationships! This is good to review now.

@socket-security

socket-securityBot commented Apr 13, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

DiffPackageSupply Chain
Security
VulnerabilityQualityMaintenanceLicense
Updatednext@​15.5.15 ⏵ 14.2.3482+2070-3095+450-4670
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 1.3.2471-110085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.5371-110085-398100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.200.07310010094100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.205.07310010094100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 2.6.17410083-493100
Addedopenai@​5.23.274100100100100
Added@​vercel/​otel@​0.1.01001007599100
Addedcohere-ai@​7.21.07510010093100
Addedcohere-ai@​8.0.07510010095100
Added@​types/​react-dom@​18.3.71001007686100
Added@​braintrust/​otel@​0.1.27710010088100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 2.0.078+110010093100
Addedcohere-ai@​7.20.08210010088100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 0.0.62100+2810083-597-1100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.205.0100+110084-194100
Updatedreact@​19.2.5 ⏵ 18.3.110010084+197100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.35.0100+11008591-3100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.57100+2810085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 3.0.799+2710086-298100
Updated@​opentelemetry/​otlp-transformer@​0.53.0 ⏵ 0.35.0100+110087-391-3100
Added@​vercel/​otel@​2.1.0991009787100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 1.9.0100+2710088+188-5100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 1.9.0100+2210010088-5100
Addedzod@​4.1.1110010010088100
Updatedai@​6.0.159 ⏵ 5.0.7689-1010010099100
Addedtypescript@​5.4.4100100909990
Updatedbraintrust@​2.2.2 ⏵ 2.2.1-rc.090+11009097100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.35.099+2610010091-3100
Updatedreact-dom@​19.2.5 ⏵ 18.3.192-71009298100
Updatedai@​6.0.159 ⏵ 6.0.192-810010099100
Addedcohere-ai@​7.14.09710010093100
See 15 more rows in the dashboard

View full report

@lforst
Luca Forstner (lforst)force-pushed the feat/google-adk-instrumentation branch from 4739528 to 3ae014bCompareApril 13, 2026 19:39
@lforst

Copy link
Copy Markdown
Member

The wrapper is still not perfect. It's not capturing llm spans. I am still gonna merge because the package has too little downloads to justify putting more work in.

@lforst
Luca Forstner (lforst) merged commit df3434d into mainApr 14, 2026
45 of 49 checks passed
@lforst
Luca Forstner (lforst) deleted the feat/google-adk-instrumentation branch April 14, 2026 09:47
Sign up for freeto 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.

Integration for Google Agent Development Kit (ADK) for TypeScript

2 participants

@AbhiPrasad@lforst
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(google-adk): add ADK instrumentation and e2e coverage - #1765

Merged
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation
Apr 14, 2026
Merged

feat(google-adk): add ADK instrumentation and e2e coverage#1765
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation

Conversation

@AbhiPrasad

@AbhiPrasadAbhijeet Prasad (AbhiPrasad) commented Apr 9, 2026

Copy link
Copy Markdown
Member

resolves#1477

Add Braintrust instrumentation for @google/adk with auto-instrumentation support by default when users run with Braintrust's loader hook.

This adds tracing for:

  • Runner.runAsync
  • BaseAgent.runAsync and subclasses
  • FunctionTool.runAsync

It also adds Google ADK e2e coverage for both hook-driven and wrapped execution.

Because ADK uses @google/genai under the hood, underlying LLM spans continue to come from the existing Google GenAI instrumentation.

Recommended usage: auto-instrumentation

The primary way users should adopt this is via Braintrust auto-instrumentation:

node --import braintrust/hook.mjs app.mjs

Then they can use @google/adk normally and Braintrust will trace supported ADK operations automatically.

Example:

import*asadkfrom"@google/adk";import{initLogger}from"braintrust";initLogger({projectName: "my-google-adk-app"});constagent=newadk.LlmAgent({name: "weather_agent",model: "gemini-2.5-flash-lite",instruction: "Answer weather questions",});construnner=newadk.InMemoryRunner({ agent,appName: "weather-app"});awaitrunner.sessionService.createSession({appName: runner.appName,userId: "user-1",sessionId: "session-1",});forawait(consteventofrunner.runAsync({userId: "user-1",sessionId: "session-1",newMessage: {role: "user",parts: [{text: "What's the weather in Paris?"}],},})){console.log(event);}

If needed, it can be disabled with:

BRAINTRUST_DISABLE_INSTRUMENTATION=google-adk node --import braintrust/hook.mjs app.mjs

Manual usage

Manual wrapping is also available for cases where users want explicit control:

import*asadkfrom"@google/adk";import{wrapGoogleADK}from"braintrust";constwrapped=wrapGoogleADK(adk);

Screenshot

image

@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

wait this need some more work. I realized the parent child relationships are wrong 😢

Comment threadjs/src/auto-instrumentations/configs/google-adk.test.ts Outdated
Comment threade2e/scenarios/google-adk-instrumentation/assertions.ts
@lforst

Copy link
Copy Markdown
Member

wait this need some more work. I realized the parent child relationships are wrong 😢

I honestly don't know why this is so painful in this SDK. Tracing channels make it harder because they are event based. It should honestly just be a simple wrapping call imo.

@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the feat/google-adk-instrumentation branch 2 times, most recently from 45ea59e to 19c40c1CompareApril 13, 2026 14:11
Add manual and load-time instrumentation for `@google/adk` across runner,
agent, and tool execution. This introduces the wrapper entrypoint,
tracing-channel plugin, vendored SDK types, exports, and loader config needed
to emit Braintrust spans for Google ADK workflows.
Add a dedicated Google ADK e2e scenario with a committed lockfile and stable
snapshots for both wrapped and hook-driven execution.
Stabilize the scenario by pre-creating ADK sessions, letting the loader hook
respect `BRAINTRUST_DISABLE_INSTRUMENTATION`, and normalizing volatile outputs
in the assertions so the coverage stays repeatable.
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) marked this pull request as ready for review April 13, 2026 14:11
@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

Okay fixed the parent-child relationships! This is good to review now.

@socket-security

socket-securityBot commented Apr 13, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

DiffPackageSupply Chain
Security
VulnerabilityQualityMaintenanceLicense
Updatednext@​15.5.15 ⏵ 14.2.3482+2070-3095+450-4670
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 1.3.2471-110085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.5371-110085-398100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.200.07310010094100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.205.07310010094100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 2.6.17410083-493100
Addedopenai@​5.23.274100100100100
Added@​vercel/​otel@​0.1.01001007599100
Addedcohere-ai@​7.21.07510010093100
Addedcohere-ai@​8.0.07510010095100
Added@​types/​react-dom@​18.3.71001007686100
Added@​braintrust/​otel@​0.1.27710010088100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 2.0.078+110010093100
Addedcohere-ai@​7.20.08210010088100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 0.0.62100+2810083-597-1100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.205.0100+110084-194100
Updatedreact@​19.2.5 ⏵ 18.3.110010084+197100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.35.0100+11008591-3100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.57100+2810085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 3.0.799+2710086-298100
Updated@​opentelemetry/​otlp-transformer@​0.53.0 ⏵ 0.35.0100+110087-391-3100
Added@​vercel/​otel@​2.1.0991009787100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 1.9.0100+2710088+188-5100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 1.9.0100+2210010088-5100
Addedzod@​4.1.1110010010088100
Updatedai@​6.0.159 ⏵ 5.0.7689-1010010099100
Addedtypescript@​5.4.4100100909990
Updatedbraintrust@​2.2.2 ⏵ 2.2.1-rc.090+11009097100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.35.099+2610010091-3100
Updatedreact-dom@​19.2.5 ⏵ 18.3.192-71009298100
Updatedai@​6.0.159 ⏵ 6.0.192-810010099100
Addedcohere-ai@​7.14.09710010093100
See 15 more rows in the dashboard

View full report

@lforst
Luca Forstner (lforst)force-pushed the feat/google-adk-instrumentation branch from 4739528 to 3ae014bCompareApril 13, 2026 19:39
@lforst

Copy link
Copy Markdown
Member

The wrapper is still not perfect. It's not capturing llm spans. I am still gonna merge because the package has too little downloads to justify putting more work in.

@lforst
Luca Forstner (lforst) merged commit df3434d into mainApr 14, 2026
45 of 49 checks passed
@lforst
Luca Forstner (lforst) deleted the feat/google-adk-instrumentation branch April 14, 2026 09:47
Sign up for freeto 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.

Integration for Google Agent Development Kit (ADK) for TypeScript

2 participants

@AbhiPrasad@lforst
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(google-adk): add ADK instrumentation and e2e coverage - #1765

Merged
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation
Apr 14, 2026
Merged

feat(google-adk): add ADK instrumentation and e2e coverage#1765
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation

Conversation

@AbhiPrasad

@AbhiPrasadAbhijeet Prasad (AbhiPrasad) commented Apr 9, 2026

Copy link
Copy Markdown
Member

resolves#1477

Add Braintrust instrumentation for @google/adk with auto-instrumentation support by default when users run with Braintrust's loader hook.

This adds tracing for:

  • Runner.runAsync
  • BaseAgent.runAsync and subclasses
  • FunctionTool.runAsync

It also adds Google ADK e2e coverage for both hook-driven and wrapped execution.

Because ADK uses @google/genai under the hood, underlying LLM spans continue to come from the existing Google GenAI instrumentation.

Recommended usage: auto-instrumentation

The primary way users should adopt this is via Braintrust auto-instrumentation:

node --import braintrust/hook.mjs app.mjs

Then they can use @google/adk normally and Braintrust will trace supported ADK operations automatically.

Example:

import*asadkfrom"@google/adk";import{initLogger}from"braintrust";initLogger({projectName: "my-google-adk-app"});constagent=newadk.LlmAgent({name: "weather_agent",model: "gemini-2.5-flash-lite",instruction: "Answer weather questions",});construnner=newadk.InMemoryRunner({ agent,appName: "weather-app"});awaitrunner.sessionService.createSession({appName: runner.appName,userId: "user-1",sessionId: "session-1",});forawait(consteventofrunner.runAsync({userId: "user-1",sessionId: "session-1",newMessage: {role: "user",parts: [{text: "What's the weather in Paris?"}],},})){console.log(event);}

If needed, it can be disabled with:

BRAINTRUST_DISABLE_INSTRUMENTATION=google-adk node --import braintrust/hook.mjs app.mjs

Manual usage

Manual wrapping is also available for cases where users want explicit control:

import*asadkfrom"@google/adk";import{wrapGoogleADK}from"braintrust";constwrapped=wrapGoogleADK(adk);

Screenshot

image

@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

wait this need some more work. I realized the parent child relationships are wrong 😢

Comment threadjs/src/auto-instrumentations/configs/google-adk.test.ts Outdated
Comment threade2e/scenarios/google-adk-instrumentation/assertions.ts
@lforst

Copy link
Copy Markdown
Member

wait this need some more work. I realized the parent child relationships are wrong 😢

I honestly don't know why this is so painful in this SDK. Tracing channels make it harder because they are event based. It should honestly just be a simple wrapping call imo.

@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the feat/google-adk-instrumentation branch 2 times, most recently from 45ea59e to 19c40c1CompareApril 13, 2026 14:11
Add manual and load-time instrumentation for `@google/adk` across runner,
agent, and tool execution. This introduces the wrapper entrypoint,
tracing-channel plugin, vendored SDK types, exports, and loader config needed
to emit Braintrust spans for Google ADK workflows.
Add a dedicated Google ADK e2e scenario with a committed lockfile and stable
snapshots for both wrapped and hook-driven execution.
Stabilize the scenario by pre-creating ADK sessions, letting the loader hook
respect `BRAINTRUST_DISABLE_INSTRUMENTATION`, and normalizing volatile outputs
in the assertions so the coverage stays repeatable.
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) marked this pull request as ready for review April 13, 2026 14:11
@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

Okay fixed the parent-child relationships! This is good to review now.

@socket-security

socket-securityBot commented Apr 13, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

DiffPackageSupply Chain
Security
VulnerabilityQualityMaintenanceLicense
Updatednext@​15.5.15 ⏵ 14.2.3482+2070-3095+450-4670
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 1.3.2471-110085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.5371-110085-398100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.200.07310010094100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.205.07310010094100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 2.6.17410083-493100
Addedopenai@​5.23.274100100100100
Added@​vercel/​otel@​0.1.01001007599100
Addedcohere-ai@​7.21.07510010093100
Addedcohere-ai@​8.0.07510010095100
Added@​types/​react-dom@​18.3.71001007686100
Added@​braintrust/​otel@​0.1.27710010088100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 2.0.078+110010093100
Addedcohere-ai@​7.20.08210010088100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 0.0.62100+2810083-597-1100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.205.0100+110084-194100
Updatedreact@​19.2.5 ⏵ 18.3.110010084+197100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.35.0100+11008591-3100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.57100+2810085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 3.0.799+2710086-298100
Updated@​opentelemetry/​otlp-transformer@​0.53.0 ⏵ 0.35.0100+110087-391-3100
Added@​vercel/​otel@​2.1.0991009787100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 1.9.0100+2710088+188-5100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 1.9.0100+2210010088-5100
Addedzod@​4.1.1110010010088100
Updatedai@​6.0.159 ⏵ 5.0.7689-1010010099100
Addedtypescript@​5.4.4100100909990
Updatedbraintrust@​2.2.2 ⏵ 2.2.1-rc.090+11009097100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.35.099+2610010091-3100
Updatedreact-dom@​19.2.5 ⏵ 18.3.192-71009298100
Updatedai@​6.0.159 ⏵ 6.0.192-810010099100
Addedcohere-ai@​7.14.09710010093100
See 15 more rows in the dashboard

View full report

@lforst
Luca Forstner (lforst)force-pushed the feat/google-adk-instrumentation branch from 4739528 to 3ae014bCompareApril 13, 2026 19:39
@lforst

Copy link
Copy Markdown
Member

The wrapper is still not perfect. It's not capturing llm spans. I am still gonna merge because the package has too little downloads to justify putting more work in.

@lforst
Luca Forstner (lforst) merged commit df3434d into mainApr 14, 2026
45 of 49 checks passed
@lforst
Luca Forstner (lforst) deleted the feat/google-adk-instrumentation branch April 14, 2026 09:47
Sign up for freeto 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.

Integration for Google Agent Development Kit (ADK) for TypeScript

2 participants

@AbhiPrasad@lforst
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(google-adk): add ADK instrumentation and e2e coverage - #1765

Merged
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation
Apr 14, 2026
Merged

feat(google-adk): add ADK instrumentation and e2e coverage#1765
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation

Conversation

@AbhiPrasad

@AbhiPrasadAbhijeet Prasad (AbhiPrasad) commented Apr 9, 2026

Copy link
Copy Markdown
Member

resolves#1477

Add Braintrust instrumentation for @google/adk with auto-instrumentation support by default when users run with Braintrust's loader hook.

This adds tracing for:

  • Runner.runAsync
  • BaseAgent.runAsync and subclasses
  • FunctionTool.runAsync

It also adds Google ADK e2e coverage for both hook-driven and wrapped execution.

Because ADK uses @google/genai under the hood, underlying LLM spans continue to come from the existing Google GenAI instrumentation.

Recommended usage: auto-instrumentation

The primary way users should adopt this is via Braintrust auto-instrumentation:

node --import braintrust/hook.mjs app.mjs

Then they can use @google/adk normally and Braintrust will trace supported ADK operations automatically.

Example:

import*asadkfrom"@google/adk";import{initLogger}from"braintrust";initLogger({projectName: "my-google-adk-app"});constagent=newadk.LlmAgent({name: "weather_agent",model: "gemini-2.5-flash-lite",instruction: "Answer weather questions",});construnner=newadk.InMemoryRunner({ agent,appName: "weather-app"});awaitrunner.sessionService.createSession({appName: runner.appName,userId: "user-1",sessionId: "session-1",});forawait(consteventofrunner.runAsync({userId: "user-1",sessionId: "session-1",newMessage: {role: "user",parts: [{text: "What's the weather in Paris?"}],},})){console.log(event);}

If needed, it can be disabled with:

BRAINTRUST_DISABLE_INSTRUMENTATION=google-adk node --import braintrust/hook.mjs app.mjs

Manual usage

Manual wrapping is also available for cases where users want explicit control:

import*asadkfrom"@google/adk";import{wrapGoogleADK}from"braintrust";constwrapped=wrapGoogleADK(adk);

Screenshot

image

@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

wait this need some more work. I realized the parent child relationships are wrong 😢

Comment threadjs/src/auto-instrumentations/configs/google-adk.test.ts Outdated
Comment threade2e/scenarios/google-adk-instrumentation/assertions.ts
@lforst

Copy link
Copy Markdown
Member

wait this need some more work. I realized the parent child relationships are wrong 😢

I honestly don't know why this is so painful in this SDK. Tracing channels make it harder because they are event based. It should honestly just be a simple wrapping call imo.

@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the feat/google-adk-instrumentation branch 2 times, most recently from 45ea59e to 19c40c1CompareApril 13, 2026 14:11
Add manual and load-time instrumentation for `@google/adk` across runner,
agent, and tool execution. This introduces the wrapper entrypoint,
tracing-channel plugin, vendored SDK types, exports, and loader config needed
to emit Braintrust spans for Google ADK workflows.
Add a dedicated Google ADK e2e scenario with a committed lockfile and stable
snapshots for both wrapped and hook-driven execution.
Stabilize the scenario by pre-creating ADK sessions, letting the loader hook
respect `BRAINTRUST_DISABLE_INSTRUMENTATION`, and normalizing volatile outputs
in the assertions so the coverage stays repeatable.
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) marked this pull request as ready for review April 13, 2026 14:11
@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

Okay fixed the parent-child relationships! This is good to review now.

@socket-security

socket-securityBot commented Apr 13, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

DiffPackageSupply Chain
Security
VulnerabilityQualityMaintenanceLicense
Updatednext@​15.5.15 ⏵ 14.2.3482+2070-3095+450-4670
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 1.3.2471-110085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.5371-110085-398100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.200.07310010094100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.205.07310010094100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 2.6.17410083-493100
Addedopenai@​5.23.274100100100100
Added@​vercel/​otel@​0.1.01001007599100
Addedcohere-ai@​7.21.07510010093100
Addedcohere-ai@​8.0.07510010095100
Added@​types/​react-dom@​18.3.71001007686100
Added@​braintrust/​otel@​0.1.27710010088100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 2.0.078+110010093100
Addedcohere-ai@​7.20.08210010088100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 0.0.62100+2810083-597-1100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.205.0100+110084-194100
Updatedreact@​19.2.5 ⏵ 18.3.110010084+197100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.35.0100+11008591-3100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.57100+2810085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 3.0.799+2710086-298100
Updated@​opentelemetry/​otlp-transformer@​0.53.0 ⏵ 0.35.0100+110087-391-3100
Added@​vercel/​otel@​2.1.0991009787100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 1.9.0100+2710088+188-5100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 1.9.0100+2210010088-5100
Addedzod@​4.1.1110010010088100
Updatedai@​6.0.159 ⏵ 5.0.7689-1010010099100
Addedtypescript@​5.4.4100100909990
Updatedbraintrust@​2.2.2 ⏵ 2.2.1-rc.090+11009097100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.35.099+2610010091-3100
Updatedreact-dom@​19.2.5 ⏵ 18.3.192-71009298100
Updatedai@​6.0.159 ⏵ 6.0.192-810010099100
Addedcohere-ai@​7.14.09710010093100
See 15 more rows in the dashboard

View full report

@lforst
Luca Forstner (lforst)force-pushed the feat/google-adk-instrumentation branch from 4739528 to 3ae014bCompareApril 13, 2026 19:39
@lforst

Copy link
Copy Markdown
Member

The wrapper is still not perfect. It's not capturing llm spans. I am still gonna merge because the package has too little downloads to justify putting more work in.

@lforst
Luca Forstner (lforst) merged commit df3434d into mainApr 14, 2026
45 of 49 checks passed
@lforst
Luca Forstner (lforst) deleted the feat/google-adk-instrumentation branch April 14, 2026 09:47
Sign up for freeto 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.

Integration for Google Agent Development Kit (ADK) for TypeScript

2 participants

@AbhiPrasad@lforst
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(google-adk): add ADK instrumentation and e2e coverage - #1765

Merged
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation
Apr 14, 2026
Merged

feat(google-adk): add ADK instrumentation and e2e coverage#1765
Luca Forstner (lforst) merged 6 commits into
mainfrom
feat/google-adk-instrumentation

Conversation

@AbhiPrasad

@AbhiPrasadAbhijeet Prasad (AbhiPrasad) commented Apr 9, 2026

Copy link
Copy Markdown
Member

resolves#1477

Add Braintrust instrumentation for @google/adk with auto-instrumentation support by default when users run with Braintrust's loader hook.

This adds tracing for:

  • Runner.runAsync
  • BaseAgent.runAsync and subclasses
  • FunctionTool.runAsync

It also adds Google ADK e2e coverage for both hook-driven and wrapped execution.

Because ADK uses @google/genai under the hood, underlying LLM spans continue to come from the existing Google GenAI instrumentation.

Recommended usage: auto-instrumentation

The primary way users should adopt this is via Braintrust auto-instrumentation:

node --import braintrust/hook.mjs app.mjs

Then they can use @google/adk normally and Braintrust will trace supported ADK operations automatically.

Example:

import*asadkfrom"@google/adk";import{initLogger}from"braintrust";initLogger({projectName: "my-google-adk-app"});constagent=newadk.LlmAgent({name: "weather_agent",model: "gemini-2.5-flash-lite",instruction: "Answer weather questions",});construnner=newadk.InMemoryRunner({ agent,appName: "weather-app"});awaitrunner.sessionService.createSession({appName: runner.appName,userId: "user-1",sessionId: "session-1",});forawait(consteventofrunner.runAsync({userId: "user-1",sessionId: "session-1",newMessage: {role: "user",parts: [{text: "What's the weather in Paris?"}],},})){console.log(event);}

If needed, it can be disabled with:

BRAINTRUST_DISABLE_INSTRUMENTATION=google-adk node --import braintrust/hook.mjs app.mjs

Manual usage

Manual wrapping is also available for cases where users want explicit control:

import*asadkfrom"@google/adk";import{wrapGoogleADK}from"braintrust";constwrapped=wrapGoogleADK(adk);

Screenshot

image

@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

wait this need some more work. I realized the parent child relationships are wrong 😢

Comment threadjs/src/auto-instrumentations/configs/google-adk.test.ts Outdated
Comment threade2e/scenarios/google-adk-instrumentation/assertions.ts
@lforst

Copy link
Copy Markdown
Member

wait this need some more work. I realized the parent child relationships are wrong 😢

I honestly don't know why this is so painful in this SDK. Tracing channels make it harder because they are event based. It should honestly just be a simple wrapping call imo.

@AbhiPrasad
Abhijeet Prasad (AbhiPrasad)force-pushed the feat/google-adk-instrumentation branch 2 times, most recently from 45ea59e to 19c40c1CompareApril 13, 2026 14:11
Add manual and load-time instrumentation for `@google/adk` across runner,
agent, and tool execution. This introduces the wrapper entrypoint,
tracing-channel plugin, vendored SDK types, exports, and loader config needed
to emit Braintrust spans for Google ADK workflows.
Add a dedicated Google ADK e2e scenario with a committed lockfile and stable
snapshots for both wrapped and hook-driven execution.
Stabilize the scenario by pre-creating ADK sessions, letting the loader hook
respect `BRAINTRUST_DISABLE_INSTRUMENTATION`, and normalizing volatile outputs
in the assertions so the coverage stays repeatable.
@AbhiPrasad
Abhijeet Prasad (AbhiPrasad) marked this pull request as ready for review April 13, 2026 14:11
@AbhiPrasad

Copy link
Copy Markdown
MemberAuthor

Okay fixed the parent-child relationships! This is good to review now.

@socket-security

socket-securityBot commented Apr 13, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

DiffPackageSupply Chain
Security
VulnerabilityQualityMaintenanceLicense
Updatednext@​15.5.15 ⏵ 14.2.3482+2070-3095+450-4670
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 1.3.2471-110085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.5371-110085-398100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.200.07310010094100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.205.07310010094100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 2.6.17410083-493100
Addedopenai@​5.23.274100100100100
Added@​vercel/​otel@​0.1.01001007599100
Addedcohere-ai@​7.21.07510010093100
Addedcohere-ai@​8.0.07510010095100
Added@​types/​react-dom@​18.3.71001007686100
Added@​braintrust/​otel@​0.1.27710010088100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 2.0.078+110010093100
Addedcohere-ai@​7.20.08210010088100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 0.0.62100+2810083-597-1100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.205.0100+110084-194100
Updatedreact@​19.2.5 ⏵ 18.3.110010084+197100
Updated@​opentelemetry/​otlp-exporter-base@​0.53.0 ⏵ 0.35.0100+11008591-3100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 2.0.57100+2810085-398100
Updated@​ai-sdk/​openai@​3.0.52 ⏵ 3.0.799+2710086-298100
Updated@​opentelemetry/​otlp-transformer@​0.53.0 ⏵ 0.35.0100+110087-391-3100
Added@​vercel/​otel@​2.1.0991009787100
Updated@​opentelemetry/​context-async-hooks@​1.26.0 ⏵ 1.9.0100+2710088+188-5100
Updated@​opentelemetry/​sdk-trace-base@​1.26.0 ⏵ 1.9.0100+2210010088-5100
Addedzod@​4.1.1110010010088100
Updatedai@​6.0.159 ⏵ 5.0.7689-1010010099100
Addedtypescript@​5.4.4100100909990
Updatedbraintrust@​2.2.2 ⏵ 2.2.1-rc.090+11009097100
Updated@​opentelemetry/​exporter-trace-otlp-http@​0.53.0 ⏵ 0.35.099+2610010091-3100
Updatedreact-dom@​19.2.5 ⏵ 18.3.192-71009298100
Updatedai@​6.0.159 ⏵ 6.0.192-810010099100
Addedcohere-ai@​7.14.09710010093100
See 15 more rows in the dashboard

View full report

@lforst
Luca Forstner (lforst)force-pushed the feat/google-adk-instrumentation branch from 4739528 to 3ae014bCompareApril 13, 2026 19:39
@lforst

Copy link
Copy Markdown
Member

The wrapper is still not perfect. It's not capturing llm spans. I am still gonna merge because the package has too little downloads to justify putting more work in.

@lforst
Luca Forstner (lforst) merged commit df3434d into mainApr 14, 2026
45 of 49 checks passed
@lforst
Luca Forstner (lforst) deleted the feat/google-adk-instrumentation branch April 14, 2026 09:47
Sign up for freeto 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.

Integration for Google Agent Development Kit (ADK) for TypeScript

2 participants

@AbhiPrasad@lforst