From 9b5da3518a3f12bdbaa386f962f300a7c8e9eded Mon Sep 17 00:00:00 2001 From: Marco Gancitano Date: Thu, 30 Jul 2026 12:40:04 -0400 Subject: [PATCH] fix(ai): map openai-agents groupId to $ai_session_id The Agents SDK groupId links traces from one conversation, which is what PostHog calls a session. It was only written to $ai_group_id, which nothing in AI observability reads, so grouped runs never appeared as sessions. $ai_group_id is still emitted so existing queries keep working. --- .changeset/openai-agents-group-id-session.md | 5 +++++ packages/ai/src/openai-agents/processor.ts | 5 +++++ packages/ai/tests/openai-agents.test.ts | 17 ++++++++++++++--- 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 .changeset/openai-agents-group-id-session.md diff --git a/.changeset/openai-agents-group-id-session.md b/.changeset/openai-agents-group-id-session.md new file mode 100644 index 0000000000..de7d1961ea --- /dev/null +++ b/.changeset/openai-agents-group-id-session.md @@ -0,0 +1,5 @@ +--- +'@posthog/ai': minor +--- + +The OpenAI Agents SDK `groupId` now also maps to `$ai_session_id` on `$ai_trace` and span events, so grouped runs show up as sessions in PostHog AI observability. `$ai_group_id` is still emitted alongside it. diff --git a/packages/ai/src/openai-agents/processor.ts b/packages/ai/src/openai-agents/processor.ts index 4406347d80..4340a85352 100644 --- a/packages/ai/src/openai-agents/processor.ts +++ b/packages/ai/src/openai-agents/processor.ts @@ -256,6 +256,7 @@ export class PostHogTracingProcessor implements TracingProcessor { ...errorProperties, } if (groupId) { + properties.$ai_session_id = groupId properties.$ai_group_id = groupId } return properties @@ -341,7 +342,11 @@ export class PostHogTracingProcessor implements TracingProcessor { properties.$ai_latency = latency } + // The Agents SDK groupId links traces from one conversation, which is exactly + // what PostHog calls a session. $ai_group_id is still emitted for anyone + // already querying it. if (groupId) { + properties.$ai_session_id = groupId properties.$ai_group_id = groupId } diff --git a/packages/ai/tests/openai-agents.test.ts b/packages/ai/tests/openai-agents.test.ts index ae2d6f0803..4580e08b13 100644 --- a/packages/ai/tests/openai-agents.test.ts +++ b/packages/ai/tests/openai-agents.test.ts @@ -118,13 +118,24 @@ describe('PostHogTracingProcessor', () => { expect(call.properties.$ai_latency).toBeDefined() }) - it('includes group_id in trace events', async () => { + it('includes group_id in trace and span events as both session and group id', async () => { const trace = createMockTrace({ groupId: 'group_abc' }) + const span = createMockSpan({ spanData: { type: 'generation', model: 'gpt-4o' } }) + await processor.onTraceStart(trace as any) + mockClient.capture.mockClear() + + await processor.onSpanStart(span as any) + await processor.onSpanEnd(span as any) + const spanCall = mockClient.capture.mock.calls[0][0] + await processor.onTraceEnd(trace as any) + const traceCall = mockClient.capture.mock.calls[1][0] - const call = mockClient.capture.mock.calls[0][0] - expect(call.properties.$ai_group_id).toBe('group_abc') + expect(spanCall.properties.$ai_session_id).toBe('group_abc') + expect(spanCall.properties.$ai_group_id).toBe('group_abc') + expect(traceCall.properties.$ai_session_id).toBe('group_abc') + expect(traceCall.properties.$ai_group_id).toBe('group_abc') }) it('includes trace metadata in trace events', async () => {