Skip to content

fix(ai): document that lifecycle insights exclude anonymous users - #71883

Merged
darkopia merged 5 commits into
masterfrom
posthog-code/lifecycle-ai-anonymous-users
Jul 17, 2026
Merged

fix(ai): document that lifecycle insights exclude anonymous users#71883
darkopia merged 5 commits into
masterfrom
posthog-code/lifecycle-ai-anonymous-users

Conversation

@darkopia

Copy link
Copy Markdown
Contributor

Problem

Lifecycle insights exclude anonymous (personless) users by design: the query runner filters out every event with $process_person_profile: false, which is what anonymous visitors send under posthog-js's default person_profiles: 'identified_only'. Trends unique-user counts include those visitors. So in projects with mostly anonymous traffic, lifecycle totals are expected to be a small fraction of the unique-user trend for the same event.

Our AI surfaces didn't know this. In a recent support conversation, a user asked why their lifecycle insight showed a tiny fraction of the users their unique-user trend showed, and the AI speculated about bugs and data issues instead of giving the real answer. The knowledge exists only as an uncommented filter in the query runner, so nothing that reads lifecycle results for the AI can explain the gap.

Changes

  • ee/hogai/context/insight/prompts.py: LIFECYCLE_EXAMPLE_PROMPT (the prompt Max receives whenever it reads lifecycle query results) now explains the anonymous-user exclusion, states that lower-than-trends counts are by design, and says how to compare like-for-like (filter trends to $process_person_profile != false). Also removed a stale duplicate definition of the same constant lower in the file. Python keeps the last definition, so the stale one (old lowercase headers, no multi-series format) was shadowing the maintained one that matches the actual formatter output in ee/hogai/context/insight/format/lifecycle.py.
  • services/mcp/definitions/prompts/query-lifecycle.md: new "Anonymous users are excluded" section plus a reminder bullet, so every MCP agent planning a query-lifecycle call gets the same knowledge.
  • posthog/hogql_queries/insights/lifecycle/lifecycle_query_runner.py: a short why-comment on the previously unexplained $process_person_profile filter.

Note

The MCP description is baked into services/mcp/schema/generated-tool-definitions.json. I couldn't regenerate it locally (codegen needs a database to export the OpenAPI schema), so the check-openapi-types CI job will auto-commit the regenerated definitions onto this branch.

How did you test this code?

  • ruff check and ruff format --check pass on the changed Python files.
  • Exec'd ee/hogai/context/insight/prompts.py and asserted the module parses with exactly one LIFECYCLE_EXAMPLE_PROMPT containing the new exclusion text and the multi-series table format.
  • The only test touching this constant (ee/hogai/context/insight/test/test_query_executor.py) asserts get_example_prompt(LifecycleQuery(...)) returns the imported constant, so it is unaffected.
  • I (Claude) did not run the DB-bound pytest suite or the MCP codegen in this sandbox; the changes are prompt strings, a markdown tool description, and a code comment, with no runtime logic touched.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Docs update

No docs/ page in this repo covers lifecycle insights, and the public website docs already explain anonymous vs identified events. This PR only teaches the AI surfaces and annotates the code.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Authored in a PostHog Code (Claude) session investigating a support conversation about a lifecycle-vs-trends unique users gap. I (Claude) verified the exclusion in lifecycle_query_runner.py, traced which prompt Max actually receives via query_executor.get_example_prompt, and found the duplicate LIFECYCLE_EXAMPLE_PROMPT shadowing the maintained definition along the way. Skill invoked: /implementing-mcp-tools (for the description_file and codegen workflow). Decision: place the knowledge at both points where an AI reasons about lifecycle, when reading results (Max) and when planning queries (MCP), rather than only one of them.


Created with PostHog Code

Lifecycle queries filter out events with $process_person_profile set to false, so lifecycle user counts are expected to be far lower than unique-user trends in projects with anonymous traffic. Teach Max's lifecycle results prompt and the MCP query-lifecycle tool description about this, remove a stale duplicate LIFECYCLE_EXAMPLE_PROMPT definition that shadowed the current one, and add a why-comment on the filter in the query runner.

Generated-By: PostHog Code
Task-Id: ce969ba9-98ef-43ab-88d8-7e92760ead2a
@darkopia darkopia self-assigned this Jul 17, 2026
@trunk-io

trunk-io Bot commented Jul 17, 2026

Copy link
Copy Markdown

Static BadgeStatic BadgeStatic BadgeStatic Badge

View Full Report ↗︎Docs

@darkopia
darkopia marked this pull request as ready for review July 17, 2026 11:49
@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested a review from a team July 17, 2026 11:50
@pr-assigner-resolver-posthog

Copy link
Copy Markdown

👀 Auto-assigned reviewers

These soft owners were skipped because they only have minor changes here. Nothing blocks merge, so self-assign if you'd like a look:

  • @PostHog/team-product-analytics (posthog/hogql_queries/owners.yaml)

Soft owners come from each directory's owners.yaml and each product's product.yaml (resolved nearest-file-wins). The locator after each owner is the file that decided it. Generated files and lockfiles are ignored when deciding ownership.

Scope the person-profile exclusion note to event and action series (data warehouse lifecycle series skip the filter), replace the categorical "by design, not a bug" phrasing with guidance to verify the gap via a trends-query filter before dismissing it, correct the "new" status definition to person-profile-creation semantics, and add the anonymous-user exclusion caveat to the query-lifecycle-actors tool description so actor drill-downs are covered too.

Generated-By: PostHog Code
Task-Id: ce969ba9-98ef-43ab-88d8-7e92760ead2a
@github-actions

Copy link
Copy Markdown
Contributor

🤖 CI report

Playwright — all passed

All tests passed.

View test results →

darkopia added 2 commits July 17, 2026 14:14
Generated-By: PostHog Code
Task-Id: 648e45e9-5a88-44e8-8e78-aaafaad080cd
@darkopia
darkopia merged commit 4832155 into master Jul 17, 2026
247 checks passed
@darkopia
darkopia deleted the posthog-code/lifecycle-ai-anonymous-users branch July 17, 2026 13:01
@deployment-status-posthog

deployment-status-posthog Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-07-17 13:27 UTC Run
prod-us ✅ Deployed 2026-07-17 13:46 UTC Run
prod-eu ✅ Deployed 2026-07-17 13:45 UTC Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants