From 75ea1fa9c83f22921648602bdb107300b54c9d61 Mon Sep 17 00:00:00 2001 From: Marco Gancitano Date: Wed, 5 Aug 2026 13:52:30 -0400 Subject: [PATCH 1/3] docs(ai-observability): openai-agents identity goes per run, not on instrument() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit instrument() registers one process-global tracing processor, so the distinct_id and per-conversation properties the example passed there stamp every run in the process — wrong for any server. Show identity and session per run via RunConfig (group_id -> $ai_session_id, trace_metadata posthog_distinct_id / posthog_properties) and scope instrument() to process-constant config. Requires PostHog/posthog-python#833. Co-Authored-By: Claude Fable 5 --- .../ai-observability/openai-agents.tsx | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/onboarding/ai-observability/openai-agents.tsx b/docs/onboarding/ai-observability/openai-agents.tsx index 1c55fa84a899..989e95932ad0 100644 --- a/docs/onboarding/ai-observability/openai-agents.tsx +++ b/docs/onboarding/ai-observability/openai-agents.tsx @@ -78,18 +78,27 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi instrument( client=posthog, - distinct_id="user_123", # optional privacy_mode=False, # optional groups={"company": "company_id_in_your_db"}, # optional - properties={"conversation_id": "abc123"}, # optional ) `} /> + + + {dedent` + \`instrument()\` registers one tracing processor for the whole process, so anything + you pass here applies to **every** run in the process. Pass the user and + conversation **per run** instead — see the next step. A static \`distinct_id\` + here is only appropriate when one process serves one user, like a CLI or worker. + `} + + +
- **Note:** If you want to capture LLM events anonymously, **do not** pass a distinct ID to - `instrument()`. See our docs on [anonymous vs identified + **Note:** If you want to capture LLM events anonymously, **do not** pass a distinct ID — + here or per run. See our docs on [anonymous vs identified events](https://posthog.com/docs/data/anonymous-vs-identified-events) to learn more.
@@ -105,7 +114,14 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi {dedent` Run your OpenAI agents as normal. PostHog automatically captures \`$ai_generation\` events for LLM calls and \`$ai_span\` events for agent execution, tool calls, and - handoffs. The example below defines a tool and lets the agent call it. + handoffs. Pass the user and conversation on the run's \`RunConfig\`: + + - \`group_id\` groups the run's traces into a conversation — it becomes \`$ai_session_id\`. + - \`trace_metadata["posthog_distinct_id"]\` attributes the run's events to a user, taking + precedence over any \`instrument()\`-level default. + - \`trace_metadata["posthog_properties"]\` adds custom properties to every event in the run. + + The example below defines a tool and lets the agent call it. `} @@ -128,7 +144,13 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi result = Runner.run_sync( agent, "What's the weather in Paris?", - run_config=RunConfig(group_id="conversation-abc"), + run_config=RunConfig( + group_id="conversation_abc", # becomes $ai_session_id + trace_metadata={ + "posthog_distinct_id": "user_123", + "posthog_properties": {"plan": "scale"}, + }, + ), ) print(result.final_output) `} From 61e1000a8252c85951c9762f5db2e7c08347eea2 Mon Sep 17 00:00:00 2001 From: Marco Gancitano Date: Wed, 5 Aug 2026 13:56:58 -0400 Subject: [PATCH 2/3] docs: use the existing callable distinct_id resolver, no SDK change needed Per review: keep posthog-python as-is. The released SDK already resolves a callable distinct_id per trace, so wire it once to read posthog_distinct_id from each run's RunConfig trace_metadata. All per-run values still travel with the call. Co-Authored-By: Claude Fable 5 --- .../ai-observability/openai-agents.tsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/onboarding/ai-observability/openai-agents.tsx b/docs/onboarding/ai-observability/openai-agents.tsx index 989e95932ad0..c65ce4d48ac1 100644 --- a/docs/onboarding/ai-observability/openai-agents.tsx +++ b/docs/onboarding/ai-observability/openai-agents.tsx @@ -78,6 +78,8 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi instrument( client=posthog, + # Resolves the user per run from RunConfig trace_metadata — see the next step + distinct_id=lambda trace: (trace.metadata or {}).get("posthog_distinct_id"), privacy_mode=False, # optional groups={"company": "company_id_in_your_db"}, # optional ) @@ -88,9 +90,10 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi {dedent` \`instrument()\` registers one tracing processor for the whole process, so anything - you pass here applies to **every** run in the process. Pass the user and - conversation **per run** instead — see the next step. A static \`distinct_id\` - here is only appropriate when one process serves one user, like a CLI or worker. + static you pass here applies to **every** run in the process. The lambda above is + the per-run escape hatch: it reads the user from each run's \`trace_metadata\` + (next step). A static \`distinct_id\` string is only appropriate when one process + serves one user, like a CLI or worker. `} @@ -117,9 +120,9 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi handoffs. Pass the user and conversation on the run's \`RunConfig\`: - \`group_id\` groups the run's traces into a conversation — it becomes \`$ai_session_id\`. - - \`trace_metadata["posthog_distinct_id"]\` attributes the run's events to a user, taking - precedence over any \`instrument()\`-level default. - - \`trace_metadata["posthog_properties"]\` adds custom properties to every event in the run. + - \`trace_metadata["posthog_distinct_id"]\` attributes the run's events to a user — the + \`distinct_id\` lambda from the previous step reads it off each trace. Any other + \`trace_metadata\` keys land on the trace as \`$ai_trace_metadata\`. The example below defines a tool and lets the agent call it. `} @@ -146,10 +149,7 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi "What's the weather in Paris?", run_config=RunConfig( group_id="conversation_abc", # becomes $ai_session_id - trace_metadata={ - "posthog_distinct_id": "user_123", - "posthog_properties": {"plan": "scale"}, - }, + trace_metadata={"posthog_distinct_id": "user_123"}, ), ) print(result.final_output) From 476e478ac7b344fa47ed33285fa6705b4ea218e8 Mon Sep 17 00:00:00 2001 From: Marco Gancitano Date: Wed, 5 Aug 2026 14:03:23 -0400 Subject: [PATCH 3/3] docs: drop inline comments and identity-scope callout Co-Authored-By: Claude Fable 5 --- .../onboarding/ai-observability/openai-agents.tsx | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/docs/onboarding/ai-observability/openai-agents.tsx b/docs/onboarding/ai-observability/openai-agents.tsx index c65ce4d48ac1..db0e90dc8f48 100644 --- a/docs/onboarding/ai-observability/openai-agents.tsx +++ b/docs/onboarding/ai-observability/openai-agents.tsx @@ -78,7 +78,6 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi instrument( client=posthog, - # Resolves the user per run from RunConfig trace_metadata — see the next step distinct_id=lambda trace: (trace.metadata or {}).get("posthog_distinct_id"), privacy_mode=False, # optional groups={"company": "company_id_in_your_db"}, # optional @@ -86,18 +85,6 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi `} /> - - - {dedent` - \`instrument()\` registers one tracing processor for the whole process, so anything - static you pass here applies to **every** run in the process. The lambda above is - the per-run escape hatch: it reads the user from each run's \`trace_metadata\` - (next step). A static \`distinct_id\` string is only appropriate when one process - serves one user, like a CLI or worker. - `} - - -
**Note:** If you want to capture LLM events anonymously, **do not** pass a distinct ID — @@ -148,7 +135,7 @@ export const getOpenAIAgentsSteps = (ctx: OnboardingComponentsContext): StepDefi agent, "What's the weather in Paris?", run_config=RunConfig( - group_id="conversation_abc", # becomes $ai_session_id + group_id="conversation_abc", trace_metadata={"posthog_distinct_id": "user_123"}, ), )