# PostHog Node AI TypeScript SDK for LLM observability with PostHog. [SEE FULL DOCS](https://posthog.com/docs/ai-engineering/observability) ## Installation ```bash npm install @posthog/ai ``` ## Direct Provider Usage ```typescript import { OpenAI } from '@posthog/ai' import { PostHog } from 'posthog-node' const phClient = new PostHog('', { host: 'https://us.i.posthog.com' }) const client = new OpenAI({ apiKey: '', posthog: phClient, }) const completion = await client.chat.completions.create({ model: 'gpt-5-mini', messages: [{ role: 'user', content: 'Tell me a fun fact about hedgehogs' }], posthogDistinctId: 'user_123', // optional posthogTraceId: 'trace_123', // optional posthogProperties: { conversation_id: 'abc123', paid: true }, //optional posthogGroups: { company: 'company_id_in_your_db' }, // optional posthogPrivacyMode: false, // optional }) console.log(completion.choices[0].message.content) // YOU HAVE TO HAVE THIS OR THE CLIENT MAY NOT SEND EVENTS await phClient.shutdown() ``` ## Custom and unsupported providers For LLM calls that don't go through one of the wrapped clients — direct Cloudflare Workers AI bindings, TanStack AI adapters, custom HTTP clients — use `captureAiGeneration` to emit the same `$ai_generation` events the wrappers produce. ```typescript import { captureAiGeneration } from '@posthog/ai' import { PostHog } from 'posthog-node' const phClient = new PostHog('', { host: 'https://us.i.posthog.com' }) const start = Date.now() const result = await env.AI.run('@cf/zai-org/glm-4.7-flash', { messages, reasoning_effort: 'high' }) await captureAiGeneration(phClient, { distinctId: 'user_123', traceId: 'trace_abc', provider: 'cloudflare-workers-ai', model: '@cf/zai-org/glm-4.7-flash', input: messages, output: result.response, modelParameters: { reasoning_effort: 'high' }, usage: { inputTokens: result.usage?.prompt_tokens, outputTokens: result.usage?.completion_tokens }, latency: (Date.now() - start) / 1000, properties: { feature: 'transcript-toc' }, }) await phClient.shutdown() ``` `captureAiGeneration` is the same primitive that every other `@posthog/ai` wrapper funnels through, so the resulting events are indistinguishable from those produced by `withTracing`, `OpenAI`, `Anthropic`, etc. ## OpenTelemetry `@posthog/ai/otel` provides two ways to send AI traces to PostHog via OpenTelemetry. Both automatically filter to AI-related spans only (`gen_ai.*`, `llm.*`, `ai.*`, `traceloop.*`) and PostHog converts them into `$ai_generation` events server-side. This works with any LLM provider SDK that supports OpenTelemetry. ```bash npm install @posthog/ai @opentelemetry/sdk-node @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-http ``` ### PostHogSpanProcessor (recommended) A self-contained `SpanProcessor` that handles batching and export internally. Use this when your setup accepts a span processor. ```typescript import { NodeSDK } from '@opentelemetry/sdk-node' import { PostHogSpanProcessor } from '@posthog/ai/otel' import { generateText } from 'ai' import { openai } from '@ai-sdk/openai' const sdk = new NodeSDK({ spanProcessors: [ new PostHogSpanProcessor({ apiKey: '', host: 'https://us.i.posthog.com', // optional, defaults to https://us.i.posthog.com }), ], }) sdk.start() const result = await generateText({ model: openai('gpt-5-mini'), prompt: 'Write a short haiku about debugging', experimental_telemetry: { isEnabled: true, functionId: 'my-awesome-function', metadata: { posthog_distinct_id: 'user_123', conversation_id: 'abc123', }, }, }) await sdk.shutdown() ``` ### PostHogTraceExporter A `TraceExporter` for APIs that only accept an exporter, such as Vercel's `registerOTel`. ```typescript import { PostHogTraceExporter } from '@posthog/ai/otel' import { registerOTel } from '@vercel/otel' registerOTel({ serviceName: 'my-app', traceExporter: new PostHogTraceExporter({ apiKey: '', host: 'https://us.i.posthog.com', // optional, defaults to https://us.i.posthog.com }), }) ``` LLM Observability [docs](https://posthog.com/docs/ai-engineering/observability) Please see the main [PostHog docs](https://www.posthog.com/docs). ## Questions? ### [Check out our community page.](https://posthog.com/posts)