## Problem
The writing style guidelines for headers in our agent modes are inconsistent with our general writing style rule of using sentence case.
## Changes
Added a specific guideline for headers to use sentence case rather than title case in the writing style section of the agent modes prompts.
## How did you test this code?
Didn't
## Problem
This PR makes it possible to use the FF tool directly on the experiments page, since we have removed navigation.
It also adds suggestion pills for FF and experiments.
## Changes
- Added suggestions for feature flags and experiments
- Added the feature flag creation tool to the experiments page so users can create flags without navigating away
## How did you test this code?
Tests + locally
## Problem
This PR introduces a new `MaxTool` to create experiments. It builds on top of the `create_feature_flag` `MaxTool` with multivariate flag support.
## Changes
- Added a new `CreateExperimentTool` that allows creating experiments via PostHog AI
## How did you test this code?
New tests + evals
## Changelog: (features only) Is this feature complete?
Yes, this feature is complete and ready to be included in the changelog.
## Problem
The feature flag `MaxTool` currently only supports simple boolean flags, but users need to create multivariate flags for A/B testing and experiments.
## Changes
- Added support for creating multivariate feature flags with multiple variants
## How did you test this code?
- Added unit tests and evals
## Changelog: (features only) Is this feature complete?
Yes, this feature is complete and ready to be included in the changelog.
## Problem
https://posthog.slack.com/archives/C03PB072FMJ/p1762902442761889?thread_ts=1762194137.014209&cid=C03PB072FMJ
we had a client who, when using the UI to filter, saw no results of session recordings. However, when going into recordsings manually, saw the filtered-for event.
turns out with a high rate of sampling or recent sessions WITHOUT recordings (it appears every session of this client's should have this event, they have ~80K sessions per day, replay was turned off 9 days ago) the 10000 LIMIT is very likely to select event sessions that do NOT have a corresponding replay, meaning when we do this join we confusingly get 0 results.
## Changes
Increase the limit.
I asked claude if this was risky for perf:
```
Real-world risk: LOW
- The query is already constrained by date range and team_id
- ClickHouse handles large IN clauses routinely
- Worst case: slightly slower query (probably milliseconds)
```
## How did you test this code?
spoofed user, ran this query directly in SQL -- with 10K limit, no results, with 1M limit, saw results (session replays returend)
<!-- Docs reminder: If this change requires updated docs, please do that! Engineers are the primary people responsible for their documentation. 🙌 -->
👉 _Stay up-to-date with [PostHog coding conventions](https://posthog.com/docs/contribute/coding-conventions) for a smoother review._
## Changelog: (features only) Is this feature complete?
<!-- Yes if this is okay to go in the changelog. No if it's still hidden behind a feature flag, or part of a feature that's not complete yet, etc. -->
<!-- Removing this section does not mean the changelog bot won't pick it up, because *some people* like to not use the template, so we can't rely on it existing. -->
## Problem
The current documentation for the `person_id_join_limitation` in HogQL AI generation is unclear and lacks comprehensive guidance on how to properly handle joins involving person_id fields. This leads to agents creating queries that result in ClickHouse errors due to forward references to override tables.
## Changes
Enhanced the `person_id_join_limitation` documentation in both `ee/hogai/graph/sql/prompts.py` and `posthog/hogql/ai.py` to:
## How did you test this code?
Hopefully it solves [https://us.posthog.com/project/2/error_tracking/0199e7eb-4ec0-73b1-8bc5-937a564aa75d?timestamp=2025-11-10T12%3A14%3A39.085000-08%3A00](error), will monitor
## Problem
The current implementation of `get_contextual_tool_class` only catches `KeyError` exceptions when looking up a tool by name, but it doesn't handle `ValueError` exceptions that can occur when an invalid tool name is passed to the `AssistantTool` constructor.
## Changes
Updated the exception handling in `get_contextual_tool_class` to catch both `KeyError` and `ValueError` exceptions, ensuring the function properly returns `None` for any invalid tool name.
## How did you test this code?
Didn't, sue me
## Problem
We have discussed ([online](https://posthog.slack.com/archives/C06NZEZ7V3Q/p1762190095126769) and offline at the offsite) that the navigation tool is currently disrupting:
- it breaks interactions on the current page by forcing the user to move to a different page
- it navigates to the SQL editor page whenever SQL is involved
- multi-tool flows need the agent to navigate between different pages (create ff/experiments)
- we want to move towards a ChatGPT/backend first agent, rather than a browser-use one
This PR removes the `navigate` tool.
## Changes
Removed any navigation tool-related code.
## How did you test this code?
Locally
## Problem
we're using offset based pagination in session replay which is not as performant as using timestamp (or ORDER BY based) pagination:
https://posthog.com/docs/api/queries#5-use-timestamp-based-pagination-instead-of-offset
## Changes
create a new paginator to paginate based on the order_by field
this uses a combination of the order_by field and session ID to tie-break (ie, if the user is sorting by clicks, there could be many many recordings with X clicks, we need to know which to start the next page on)
Fallback to offset based pagination if there is no cursor
## How did you test this code?
Wrote tests, confirmed pagination still behaved as expected in product
[field_based_paginating.mov <span class="graphite__hidden">(uploaded via Graphite)</span> <img class="graphite__hidden" src="https://app.graphite.com/user-attachments/thumbnails/cf0c99bb-3efc-4b7e-a0b2-97a59ad5a7db.mov" />](https://app.graphite.com/user-attachments/video/cf0c99bb-3efc-4b7e-a0b2-97a59ad5a7db.mov)
<!-- Docs reminder: If this change requires updated docs, please do that! Engineers are the primary people responsible for their documentation. 🙌 -->
👉 _Stay up-to-date with [PostHog coding conventions](https://posthog.com/docs/contribute/coding-conventions) for a smoother review._
## Changelog: (features only) Is this feature complete?
<!-- Optional, but helpful for our content team! -->
<!-- Yes if this is okay to go in the changelog. No if it's still hidden behind a feature flag, or part of a feature that's not complete yet, etc. -->