diff --git a/docs/onboarding/ai-observability/google-adk.tsx b/docs/onboarding/ai-observability/google-adk.tsx
new file mode 100644
index 000000000000..2156660daa98
--- /dev/null
+++ b/docs/onboarding/ai-observability/google-adk.tsx
@@ -0,0 +1,171 @@
+import { OnboardingComponentsContext, createInstallation } from 'scenes/onboarding/shared/OnboardingDocsContentWrapper'
+
+import { StepDefinition } from '../steps'
+
+export const getGoogleADKSteps = (ctx: OnboardingComponentsContext): StepDefinition[] => {
+ const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx
+ const NotableGenerationProperties = snippets?.NotableGenerationProperties
+
+ return [
+ {
+ title: 'Install dependencies',
+ badge: 'required',
+ content: (
+ <>
+
+
+ See the complete [Node.js
+ example](https://github.com/PostHog/posthog-js/tree/main/examples/example-ai-adk) on GitHub.
+
+
+
+
+ Install the PostHog SDK alongside the [Google Agent Development Kit for
+ TypeScript](https://github.com/google/adk-js) (`@google/adk`). For the Python and Go ADKs, use
+ the [OpenTelemetry
+ integration](https://posthog.com/docs/ai-observability/installation/opentelemetry) instead: they
+ emit `gen_ai.*` spans that PostHog captures automatically. ADK Go sends message content as log
+ records, so its generations arrive without prompts and responses.
+
+
+
+ >
+ ),
+ },
+ {
+ title: 'Add the PostHog plugin',
+ badge: 'required',
+ content: (
+ <>
+
+ Create a PostHog client and register `PostHogADKPlugin` on your ADK `Runner`. The plugin hooks
+ the run, agent, tool, and model callbacks and captures the full hierarchy: an `$ai_trace` per
+ invocation, `$ai_span` events for agent runs and tool calls, and one `$ai_generation` per model
+ call. It **does not** proxy your calls.
+
+
+ ', { host: '' })
+
+ const getWeather = new FunctionTool({
+ name: 'get_weather',
+ description: 'Get the current weather for a city.',
+ parameters: z.object({ city: z.string() }),
+ execute: ({ city }) => \`The weather in \${city} is sunny, 72F\`,
+ })
+
+ const agent = new LlmAgent({
+ name: 'assistant',
+ model: 'gemini-3.6-flash',
+ instruction: 'You are a helpful assistant.',
+ tools: [getWeather],
+ })
+
+ const sessionService = new InMemorySessionService()
+ const runner = new Runner({
+ appName: 'my-app',
+ agent,
+ sessionService,
+ plugins: [new PostHogADKPlugin({ client: posthog })],
+ })
+ `}
+ />
+ >
+ ),
+ },
+ {
+ title: 'Run your agent',
+ badge: 'required',
+ content: (
+ <>
+
+ {dedent`
+ Run your agent as normal. Each invocation becomes a trace, the ADK session ID becomes
+ \`$ai_session_id\`, and the run's \`userId\` becomes the events' distinct ID. Pass
+ \`distinctId\` to the plugin to attribute events to a different PostHog person.
+ `}
+
+
+
+
+
+ {dedent`
+ The question above makes the agent call the tool, so this run captures:
+
+ - a trace for the invocation
+ - a span for the \`assistant\` agent run
+ - a span for the \`get_weather\` tool call
+ - a generation for each of the two model calls (the tool request, then the answer)
+ `}
+
+
+
+ Call `await posthog.shutdown()` before your process exits so batched events are flushed.
+
+
+
+ {dedent`
+ You can expect captured \`$ai_generation\` events to have the following properties:
+ `}
+
+
+ {NotableGenerationProperties && }
+ >
+ ),
+ },
+ {
+ title: 'Plugin options',
+ badge: 'optional',
+ content: (
+
+ {dedent`
+ \`PostHogADKPlugin\` accepts these options besides \`client\`:
+
+ - \`distinctId\`: a string, or a resolver \`(context) => string\` called per model call. Defaults to the ADK \`userId\`.
+ - \`provider\`: the \`$ai_provider\` label. Defaults to \`gemini\`. Set it when routing ADK to another provider so costs are derived from the right model catalog.
+ - \`privacyMode\`: redacts captured input and output content.
+ - \`groups\`: [group analytics](https://posthog.com/docs/product-analytics/group-analytics) attached to every event.
+ - \`properties\`: extra properties merged into every event.
+ - \`captureImmediate\`: awaits delivery per event instead of batching. Useful in serverless environments.
+ - \`onError\`: called when capturing an event fails. Capture errors never throw into the model flow.
+ `}
+
+ ),
+ },
+ ]
+}
+
+export const GoogleADKInstallation = createInstallation(getGoogleADKSteps)
diff --git a/frontend/src/scenes/onboarding/legacy/sdks/ai-observability/AIObservabilitySDKInstructions.tsx b/frontend/src/scenes/onboarding/legacy/sdks/ai-observability/AIObservabilitySDKInstructions.tsx
index 74c8cc90179a..ff3a479acec5 100644
--- a/frontend/src/scenes/onboarding/legacy/sdks/ai-observability/AIObservabilitySDKInstructions.tsx
+++ b/frontend/src/scenes/onboarding/legacy/sdks/ai-observability/AIObservabilitySDKInstructions.tsx
@@ -18,6 +18,7 @@ import { DSPyInstallation } from '@posthog/shared-onboarding/ai-observability/ds
import { EveInstallation } from '@posthog/shared-onboarding/ai-observability/eve'
import { FireworksAIInstallation } from '@posthog/shared-onboarding/ai-observability/fireworks-ai'
import { GoogleInstallation } from '@posthog/shared-onboarding/ai-observability/google'
+import { GoogleADKInstallation } from '@posthog/shared-onboarding/ai-observability/google-adk'
import { GroqInstallation } from '@posthog/shared-onboarding/ai-observability/groq'
import { HeliconeInstallation } from '@posthog/shared-onboarding/ai-observability/helicone'
import { HuggingFaceInstallation } from '@posthog/shared-onboarding/ai-observability/hugging-face'
@@ -80,6 +81,10 @@ const LLMGoogleInstructionsWrapper = withOnboardingDocsWrapper({
Installation: GoogleInstallation,
snippets: PROVIDER_SNIPPETS,
})
+const LLMGoogleADKInstructionsWrapper = withOnboardingDocsWrapper({
+ Installation: GoogleADKInstallation,
+ snippets: PROVIDER_SNIPPETS,
+})
const LLMOpenRouterInstructionsWrapper = withOnboardingDocsWrapper({
Installation: OpenRouterInstallation,
snippets: PROVIDER_SNIPPETS,
@@ -238,6 +243,7 @@ export const AIObservabilitySDKInstructions: SDKInstructionsMap = {
[SDKKey.ANTHROPIC]: LLMAnthropicInstructionsWrapper,
[SDKKey.AWS_BEDROCK]: LLMAWSBedrockInstructionsWrapper,
[SDKKey.GOOGLE_GEMINI]: LLMGoogleInstructionsWrapper,
+ [SDKKey.GOOGLE_ADK]: LLMGoogleADKInstructionsWrapper,
[SDKKey.VERCEL_AI]: LLMVercelAIInstructionsWrapper,
[SDKKey.EVE]: LLMEveInstructionsWrapper,
[SDKKey.VERCEL_AI_GATEWAY]: LLMVercelAIGatewayInstructionsWrapper,
diff --git a/frontend/src/scenes/onboarding/legacy/sdks/allSDKs.tsx b/frontend/src/scenes/onboarding/legacy/sdks/allSDKs.tsx
index 40ac3d62a0d3..e4e19c6e1605 100644
--- a/frontend/src/scenes/onboarding/legacy/sdks/allSDKs.tsx
+++ b/frontend/src/scenes/onboarding/legacy/sdks/allSDKs.tsx
@@ -218,6 +218,13 @@ export const ALL_SDKS: SDK[] = [
image: geminiImage,
docsLink: 'https://posthog.com/docs/ai-observability/installation/google',
},
+ {
+ name: 'Google ADK',
+ key: SDKKey.GOOGLE_ADK,
+ tags: [SDKTag.FRAMEWORK],
+ image: geminiImage,
+ docsLink: 'https://posthog.com/docs/ai-observability/installation/google-adk',
+ },
{
name: 'Vercel AI SDK',
key: SDKKey.VERCEL_AI,
diff --git a/frontend/src/types.ts b/frontend/src/types.ts
index b61ab1dc4267..847420d41513 100644
--- a/frontend/src/types.ts
+++ b/frontend/src/types.ts
@@ -7125,6 +7125,7 @@ export enum SDKKey {
FLUTTER = 'flutter',
GATSBY = 'gatsby',
GO = 'go',
+ GOOGLE_ADK = 'google_adk',
GOOGLE_GEMINI = 'google_gemini',
GOOGLE_TAG_MANAGER = 'google_tag_manager',
GROQ = 'groq',