From ffc24bf026635a5d95162848eddd6563200dd887 Mon Sep 17 00:00:00 2001 From: Marco Gancitano Date: Tue, 1 Sep 2026 10:22:20 -0400 Subject: [PATCH 1/3] feat(aio): add google adk onboarding docs Co-Authored-By: Claude Fable 5 --- .../ai-observability/google-adk.tsx | 149 ++++++++++++++++++ .../AIObservabilitySDKInstructions.tsx | 6 + .../scenes/onboarding/legacy/sdks/allSDKs.tsx | 7 + frontend/src/types.ts | 1 + 4 files changed, 163 insertions(+) create mode 100644 docs/onboarding/ai-observability/google-adk.tsx diff --git a/docs/onboarding/ai-observability/google-adk.tsx b/docs/onboarding/ai-observability/google-adk.tsx new file mode 100644 index 000000000000..0e47c345bf62 --- /dev/null +++ b/docs/onboarding/ai-observability/google-adk.tsx @@ -0,0 +1,149 @@ +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. + + + + + ), + }, + { + title: 'Add the PostHog plugin', + badge: 'required', + content: ( + <> + + Create a PostHog client and register `PostHogADKPlugin` on your ADK `Runner`. The plugin hooks + the model-call lifecycle and captures one `$ai_generation` event per model call. It **does not** + proxy your calls. + + + ', { host: '' }) + + const agent = new LlmAgent({ + name: 'assistant', + model: 'gemini-2.5-flash', + instruction: 'You are a helpful assistant.', + }) + + 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. + `} + + + + + + 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', From 6a3e9d9aae8ef556cad92b7511bc845d33bd7606 Mon Sep 17 00:00:00 2001 From: Marco Gancitano Date: Tue, 1 Sep 2026 13:44:07 -0400 Subject: [PATCH 2/3] chore(aio): carry the adk go log-records caveat onto the adk page Ports the review feedback from #91989: ADK Go emits message content as OTel log records, so generations captured via the bridge arrive without prompts and responses. Co-Authored-By: Claude Fable 5 --- docs/onboarding/ai-observability/google-adk.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/onboarding/ai-observability/google-adk.tsx b/docs/onboarding/ai-observability/google-adk.tsx index 0e47c345bf62..85ad2b9e0c7e 100644 --- a/docs/onboarding/ai-observability/google-adk.tsx +++ b/docs/onboarding/ai-observability/google-adk.tsx @@ -24,7 +24,8 @@ export const getGoogleADKSteps = (ctx: OnboardingComponentsContext): StepDefinit 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. + emit `gen_ai.*` spans that PostHog captures automatically. ADK Go sends message content as log + records, so its generations arrive without prompts and responses. Date: Wed, 2 Sep 2026 14:51:01 -0400 Subject: [PATCH 3/3] fix(aio): document the merged adk plugin's trace and span capture Review feedback: the merged plugin hooks run, agent, tool, and model callbacks, so the page now describes the full hierarchy, registers a tool in the example, and lists the captured events. Model matches the linked example (gemini-3.6-flash). Co-Authored-By: Claude Fable 5 --- .../ai-observability/google-adk.tsx | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/docs/onboarding/ai-observability/google-adk.tsx b/docs/onboarding/ai-observability/google-adk.tsx index 85ad2b9e0c7e..2156660daa98 100644 --- a/docs/onboarding/ai-observability/google-adk.tsx +++ b/docs/onboarding/ai-observability/google-adk.tsx @@ -31,7 +31,7 @@ export const getGoogleADKSteps = (ctx: OnboardingComponentsContext): StepDefinit @@ -44,23 +44,33 @@ export const getGoogleADKSteps = (ctx: OnboardingComponentsContext): StepDefinit <> Create a PostHog client and register `PostHogADKPlugin` on your ADK `Runner`. The plugin hooks - the model-call lifecycle and captures one `$ai_generation` event per model call. It **does not** - proxy your calls. + 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-2.5-flash', + model: 'gemini-3.6-flash', instruction: 'You are a helpful assistant.', + tools: [getWeather], }) const sessionService = new InMemorySessionService() @@ -111,6 +121,17 @@ export const getGoogleADKSteps = (ctx: OnboardingComponentsContext): StepDefinit `} /> + + {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.