genkitx-posthog
v0.1.2
Published
PostHog LLM analytics integration for Firebase Genkit
Maintainers
Readme

genkitx-posthog is the PostHog LLM analytics plugin for Firebase Genkit, originally developed and battle-tested at Orchestra.
It automatically captures AI/LLM telemetry data from your Genkit applications and sends it to PostHog for analysis.
Installation
Install the plugin in your project with your favorite package manager:
npm install genkitx-posthogpnpm add genkitx-posthogyarn add genkitx-posthogVersion Compatibility
| Plugin Version | Genkit Version | | -------------- | -------------- | | >= 0.1.0 | >= 1.0.0 |
Configuration
To use the plugin, you need to configure it with your PostHog API key:
import { genkit } from 'genkit';
import { googleAI } from '@genkit-ai/googleai';
import { enableTelemetry } from 'genkit/tracing';
import { getPostHogProcessor } from 'genkitx-posthog';
// 1. Initialize Genkit
const ai = genkit({
plugins: [googleAI()],
});
// 2. Create the PostHog span processor
const posthogProcessor = getPostHogProcessor({
apiKey: process.env.POSTHOG_API_KEY!,
host: 'https://us.i.posthog.com', // or 'https://eu.i.posthog.com'
genkitInstance: ai,
});
// 3. Add it to telemetry
enableTelemetry({
spanProcessors: [posthogProcessor],
});The plugin accepts the following configuration options:
| Option | Type | Default | Description |
| ---------------- | ----------------------- | ---------------------------- | -------------------------------------------------- |
| apiKey | string | required | PostHog project API key |
| host | string | 'https://us.i.posthog.com' | PostHog API host URL |
| debug | boolean | false | Enable debug logging |
| getContext | ContextResolver | undefined | Custom function to resolve user context from spans |
| genkitInstance | GenkitInstanceMinimal | undefined | Genkit instance for currentContext() fallback |
| logger | Logger | Console logger | Custom logger implementation |
| flushAt | number | 1 | Batch size before automatic flush |
| privacyMode | boolean | false | Redact input/output content from events |
Usage
Basic Generation
Once configured, the plugin automatically captures all Genkit operations:
// Events are captured automatically
const response = await ai.generate({
model: 'googleai/gemini-2.0-flash',
prompt: 'Tell me a joke',
});With User Context
To attribute events to specific users, pass context through Genkit or use a custom context resolver:
// Option 1: Pass context via Genkit's context option
await ai.generate({
model: 'googleai/gemini-2.0-flash',
prompt: 'Hello',
context: {
auth: { uid: 'user-123' },
sessionId: 'session-789',
},
});
// Option 2: Use a custom context resolver
const processor = getPostHogProcessor({
apiKey: process.env.POSTHOG_API_KEY!,
getContext: ({ traceId, spanAttributes, currentContext }) => {
return {
distinctId: currentContext?.userId as string || 'anonymous',
groupType: 'company',
groupId: currentContext?.organizationId as string,
sessionId: currentContext?.sessionId as string,
};
},
});Within a Genkit Flow
import { defineFlow } from 'genkit';
const myFlow = ai.defineFlow(
{ name: 'myFlow', inputSchema: z.string(), outputSchema: z.string() },
async (input) => {
const response = await ai.generate({
model: 'googleai/gemini-2.0-flash',
prompt: input,
});
return response.text;
}
);
// Flow execution is automatically traced
const result = await myFlow('What is AI?');Serverless Environments
In serverless environments (AWS Lambda, Cloud Functions), flush events before termination:
import { flushPostHog, shutdownPostHog } from 'genkitx-posthog';
export async function handler(event) {
// ... your Genkit operations
await flushPostHog(); // Ensure events are sent
return response;
}
// For graceful shutdown
process.on('SIGTERM', async () => {
await shutdownPostHog();
process.exit(0);
});Features
Captured Events
The plugin captures these PostHog AI event types:
| Event | Description | Key Properties |
| ----------------- | --------------------------------- | ----------------------------------------------------------------------- |
| $ai_generation | Model/LLM calls | $ai_model, $ai_provider, $ai_input_tokens, $ai_output_tokens |
| $ai_embedding | Embedder calls | $ai_model, $ai_provider, $ai_input |
| $ai_trace | Flows and root operations | $ai_trace_id, $ai_span_name, $ai_latency |
| $ai_span | Tools and nested operations | $ai_span_name, $ai_input_state, $ai_output_state |
All events include: $ai_framework ('genkit'), $ai_lib_version, $ai_trace_id, $ai_span_id, $ai_latency, $ai_is_error
Privacy Mode
Enable privacy mode to redact sensitive data:
const processor = getPostHogProcessor({
apiKey: process.env.POSTHOG_API_KEY!,
privacyMode: true, // Redacts input/output content
});When enabled, $ai_input, $ai_output_choices, $ai_input_state, and $ai_output_state are replaced with '[REDACTED]'. Metadata like token counts and latency are still captured.
PostHog Groups
To use PostHog Groups for organization-level analytics:
const processor = getPostHogProcessor({
apiKey: process.env.POSTHOG_API_KEY!,
getContext: ({ currentContext }) => ({
distinctId: currentContext?.userId as string,
groupType: 'company', // Your PostHog group type
groupId: currentContext?.organizationId as string,
}),
});API Reference
| Export | Type | Description |
| --------------------- | ----------------------------- | ------------------------------------------------ |
| getPostHogProcessor | (options) => SpanProcessor | Creates a span processor for PostHog integration |
| posthog | (options) => GenkitPlugin | Genkit plugin (marker only) |
| flushPostHog | () => Promise<void> | Flush pending events to PostHog |
| shutdownPostHog | () => Promise<void> | Gracefully shutdown the exporter |
Troubleshooting
Events not appearing in PostHog
- Verify
POSTHOG_API_KEYis set correctly - Enable
debug: trueto see detailed logs - Call
flushPostHog()explicitly to force send events - Ensure correct host (
us.i.posthog.comvseu.i.posthog.com)
Missing user attribution
- Implement a custom
getContextresolver - Pass context via Genkit's
contextoption - Provide
genkitInstancefor automatic context extraction
Built & Maintained By
This plugin was originally built for internal use at Orchestra — the AI-Native productivity platform.
We couldn't find a ready-made way to track our Genkit workflows in PostHog, so we built and open-sourced it to help the Genkit community get better visibility into their AI apps.
Maintained by Miro K and the Orchestra Team.
Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
License
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
