Overview
Hi Claude! Could you help me develop a unique voice for an audience? If you need more information from me, ask me 1-2 key questions right away. If you think I should upload any documents that would help you do a better job, let me know. You can use the tools you have access to— like Google Drive, web search, etc.—if they’ll help you better accomplish this task. Do not use analysis tool. Please keep your responses friendly, brief and conversational. Please execute the task as soon as you can—an artifact would be great if it makes sense. If using an artifact, consider what kind of artifact (interactive, visual, checklist, etc.) might be most helpful for this specific task. Thanks for your help!
Tools
action-delete
ChatGPTaction-get
ChatGPTaction-update
ChatGPTactions-get-all
ChatGPTagent-feedback
ChatGPTcreate-feature-flag
ChatGPTdashboard-create
ChatGPTdashboard-delete
ChatGPTdashboard-get
ChatGPTfilters and variables fields in the response (preview). To execute insights with the same overrides, pass the same query params to dashboard-insights-run.dashboard-insights-run
ChatGPTdashboard-reorder-tiles
ChatGPTdashboard-update
ChatGPTdashboards-get-all
ChatGPTsearch parameter runs a fuzzy match against name and description using Postgres trigram word similarity (handles typos, transpositions, and prefix-as-you-type) and returns results ranked by relevance — use it to find a specific dashboard by name rather than paging through every dashboard. search is capped at 200 characters; longer queries return a 400 error. Optional filters by tag and pinned status are also supported. Returns name, description, pinned status, tags, and creation metadata. Tiles and insights are not included — use dashboard-get to fetch a dashboard's tiles, then dashboard-insights-run to fetch the actual data for each insight.debug-mcp-ui-apps
ChatGPTdelete-feature-flag
ChatGPTdocs-search
ChatGPTerror-tracking-assignment-rules-create
ChatGPTfilters to match incoming errors and an assignee with type (user or role) plus the matching user ID or role UUID.error-tracking-assignment-rules-list
ChatGPTlimit and offset.error-tracking-grouping-rules-create
ChatGPTfilters, and optionally set assignee and description for the issues this rule creates.error-tracking-grouping-rules-list
ChatGPTerror-tracking-issues-merge-create
ChatGPTid and the issues to merge into it as ids.error-tracking-issues-partial-update
ChatGPTerror-tracking-issues-split-create
ChatGPTid and the fingerprints to split as fingerprints, where each entry includes a required fingerprint and optional name or description.error-tracking-suppression-rules-create
ChatGPTfilters tightly to the exact exception type, message, URL, or properties you want gone. Do NOT create match-all rules (omitting filters) or broad rules — they silently swallow unrelated errors and cause data loss that is hard to detect after the fact. Prefer sampling_rate to dampen noisy issues rather than fully suppressing when uncertain. Confirm with the user before creating any rule that could match more than one distinct error.error-tracking-suppression-rules-list
ChatGPTlimit and offset.error-tracking-symbol-sets-download-retrieve
ChatGPTerror-tracking-symbol-sets-list with the exact ref first.error-tracking-symbol-sets-list
ChatGPTref or upload status (valid, invalid, or all) and sorting with order_by. Each result includes has_uploaded_file so you can tell whether the download tool will work.error-tracking-symbol-sets-retrieve
ChatGPTerror-tracking-symbol-sets-list with the exact ref first.event-definition-update
ChatGPTexecute-sql
ChatGPTposthog:execute-sql MCP tool to execute HogQL queries. HogQL is PostHog's variant of SQL that supports most of ClickHouse SQL. We use terms "HogQL" and "SQL" interchangeably. References mentioned in this file are relevant to PostHog's skill querying-posthog-data. Do not assume that data exists. Use the SQL tool proactively to find the right data. Search types Proactively use different search types depending on a task: - Grep-like (regex search) with match(), LIKE, ILIKE, position, multiMatch, etc. - Full-text search with hasToken, hasTokenCaseInsensitive, etc. Make sure you pass string constants to hasToken* functions. - Dumping results to a file and using bash commands to process potentially large outputs. Data Groups PostHog has two distinct groups of data you can query: 1. System Data (PostHog-Created Data) Data created directly in PostHog by users - metadata about PostHog setup. All system tables are prefixed with system.: Table | Description system.actions | Named event combinations for filtering system.cohorts | Groups of persons for segmentation system.dashboards | Collections of insights system.data_warehouse_sources | Connected external data sources system.data_warehouse_tables | Connected tables with their columns and formats system.error_tracking_issues | Error tracking issues (grouped exceptions) system.experiments | A/B tests and experiments system.exports | Export jobs system.feature_flags | Feature flags for controlling rollouts system.groups | Group entities system.ingestion_warnings | Data ingestion issues system.insight_variables | SQL, dashboard, and insight variables for dynamic query filtering system.insights | Visual and textual representations of aggregated data system.logs_alerts | Log alert configurations and their states system.logs_views | Saved log filter views system.notebooks | Collaborative documents with embedded insights system.surveys | Questionnaires and feedback forms system.teams | Team/project settings Example - List insights: ``sql SELECT id, name, short_id FROM system.insights WHERE NOT deleted LIMIT 10 ` **Example - Count insight variables:** `sql SELECT count() AS total FROM system.insight_variables ` **System Models Reference** Schema reference for PostHog's core system models, organized by domain: - [Actions](references/models-actions.md) - [Cohorts & Persons](references/models-cohorts.md) - [Dashboards, Tiles & Insights](references/models-dashboards-insights.md) - [Data Warehouse](references/models-data-warehouse.md) - [Error Tracking](references/models-error-tracking.md) - [Logs](references/models-logs.md) - [Flags & Experiments](references/models-flags-experiments.md) - [Notebooks](references/models-notebooks.md) - [Surveys](references/models-surveys.md) - [SQL Variables](references/models-variables.md) **Entity Relationships** From | Relation | To | Join Experiment | 1:1 | FeatureFlag | feature_flag_id Experiment | N:1 | Cohort | exposure_cohort_id Survey | N:1 | FeatureFlag | linked_flag_id, targeting_flag_id Survey | N:1 | Insight | linked_insight_id Cohort | M:N | Person | via cohortpeople Person | 1:N | PersonDistinctId | person_id All entities are scoped by a team by default. You cannot access data of another team unless you switch a team. 2. Captured Data (Analytics Data) Data collected via the PostHog SDK - used for analytics. Table | Description events | Recorded events from SDKs persons | Individuals captured by the SDK. "Person" = "user" groups | Groups of individuals (organizations, companies, etc.) sessions | Session data captured by the SDK Data warehouse tables | Connected external data sources and custom views Use posthog:read-data-warehouse-schema to retrieve the full schema of the tables above. **Key concepts:** - **Events**: Standardized events/properties start with $ (e.g., $pageview). Custom ones start with any other character. - **Properties**: Key-value metadata accessed via properties.foo.bar or properties.foo['bar'] for special characters - **Person properties**: Access via events.person.properties.foo or persons.properties.foo - **Person property modes**: person.properties.` behavior depends on the project's person-on-events setting. Check the project metadata to determine if values are event-time (value at ingestion) or query-time (current value). See [Person property modes](references/person-property-modes.md) for details. - Unique users: Use `events.person_id` for counting unique users Example - Weekly active users: ```sql SELECT toStartOfWeek(timestamp) AS week, count(DISTINCT person_id) AS users FROM events WHERE event = '$pageview' AND timestamp > now() - INTERVAL 8 WEEK GROUP BY week ORDER BY week DESC ``` 3. Document Embeddings (Semantic Search) The `document_embeddings` table stores text content with vector embeddings, partitioned by `model_name`. To discover what kinds of data are available: ```sql SELECT product, document_type, count() as cnt FROM document_embeddings WHERE model_name = 'text-embedding-3-small-1536' AND timestamp >= now() - INTERVAL 1 MONTH GROUP BY product, document_type ORDER BY cnt DESC ``` Run separately for each model. Available models: `'text-embedding-3-small-1536'`, `'text-embedding-3-large-3072'`. You MUST filter on exactly one `model_name` per query — it routes to the correct underlying ClickHouse table. `IN` clauses and cross-model queries will fail. Use `embedText(text, model_name)` and `cosineDistance()` for semantic search. See the `signals` skill for detailed query patterns around the signals product specifically, including required deduplication and metadata extraction. Querying guidelines Schema verification Before writing analytical queries, always verify that: - The required event names or actions exist. - Properties and property values of events, persons, sessions, and groups data exist. Follow this workflow: 1. Fetch the tool schema - Use `posthog:read-data-schema` to get the latest schema from the MCP. 1. Verify data exist - Use `posthog:read-data-schema` with different data types to check if the data you need is captured 1. Only then write the query - Once you've confirmed the data exists, write and execute your analytical query <example> User: how many times the tool search was used? Assistant: 1. First, verify the events exist: - Call `posthog:read-data-schema` with `kind: events` - Look for events/actions matching the request 2. If required events don't exist, inform the user immediately instead of running queries that will return empty results 3. If events exist, like "tool executed", verify the properties: - Call `posthog:read-data-schema` with `kind: event_properties` and `event_name: tool executed` - Look for properties indicating a tool 4. Check other events/actions or return if required properties don't exist 5. If events exist, like "tool_name", verify the property values: - Call `posthog:read-data-schema` with `kind: event_property_values`, `event_name: tool executed`, and `property_name: tool_name` - Follow the pattern from the sample or dig deeper into existing properties with SQL queries. 6. Only then write and execute the analytical SQL query <reasoning> Assistant should verify the data schema to write a correct SQL query, as the data schema varies over time. </reasoning> </example> <example> User: how many users have chatted with the AI assistant from the US? Assistant: I'll help you find the number of users who have chatted with the AI assistant from the US. Let me create a todo list to track this implementation. 1. Find the relevant events to "chatted with the AI assistant" 2. Find the relevant properties of the events and persons to narrow down data to users from specific country 3. Retrieve the sample property values for found properties 4. Create the insight schema by using the data retrieved in the previous steps 5. Generate the insight 6. Analyze retrieved data <reasoning> The task list helps the assistant to stay on track. </reasoning> </example> This prevents wasted API calls and gives users immediate feedback when the data they're looking for doesn't exist. Skipping index You should use the skipping index signature to write optimized analytical queries. Time ranges All analytical queries and subqueries must always have time ranges set for supported tables (events). If the user doesn't state it, assume default time range based on the data volume, like a day, week, or month. How you should use time ranges <example> User: Find events from returning browsers - browsers that appeared both yesterday and today Assistant: ```sql SELECT event FROM events WHERE timestamp >= now() - INTERVAL 1 DAY and properties['$browser'] IN (SELECT properties['$browser'] FROM events WHERE timestamp >= now() - INTERVAL 2 DAY and timestamp < now() - INTERVAL 1 DAY) ``` </example> How you should NOT write queries <example> User: List 10 events with SQL Assistant: ```sql SELECT event, timestamp, distinct_id, properties FROM events ORDER BY timestamp DESC LIMIT 10 ``` </example> JOINs General guidelines Keep in mind that the right expression is loaded in memory when joining data in ClickHouse, so the joining query or table must always fit in memory. Common strategies: - Analytical functions and combinators. - Subqueries as a source or filter. - Arrays (arrayMap, arrayJoin) and ARRAY JOIN. System data You are allowed joining system data. Insights are the most used entity, so keep it on the left. Analytical data Prefer using analytical functions and subqueries for joins. Do not use raw joins on the events table. How you should join data <example> User: Find ai traces with feedback Assistant: ```sql SELECT g.properties.$ai_trace_id as trace_id FROM events AS g WHERE timestamp >= now() - INTERVAL 1 WEEK AND g.event = '$ai_generation' AND trace_id IN (SELECT properties.$ai_trace_id FROM events WHERE event = '$ai_feedback' AND timestamp >= now() - INTERVAL 1 WEEK) ``` <reasoning>A subquery is used instead of a JOIN clause. Both queries have the timestamp filters.</reasoning> </example> How you should NOT join data <example> User: Find ai traces with feedback Assistant: ```sql SELECT g.properties.$ai_trace_id FROM events AS g INNER JOIN (SELECT properties.$ai_trace_id as trace_id FROM events WHERE event = '$ai_feedback') AS f ON g.properties.$ai_trace_id = f.trace_id WHERE g.event = '$ai_generation' ``` <reasoning>Join is not necessary here. The assistant could've used a subquery.</reasoning> </example> Other constraints - Your query results are capped at 100 rows by default. You can request up to 500 rows using a LIMIT clause. If you need more data, paginate using LIMIT and OFFSET in subsequent queries. - You should cherry-pick `properties` of events, persons, or groups, so we don't get OOMs. Never select the full `properties` object (e.g., `SELECT properties FROM events`) and dump it into the conversation output. Instead, select only the specific properties you need (e.g., `properties.$browser`, `properties.$os`). If you must inspect the full properties object, dump the query results to a file and use bash commands to explore it. - When query results contain large JSON blobs (e.g., AI trace inputs/outputs, full property objects), always dump them to a file rather than outputting them directly. Use bash commands to process the file. HogQL Differences from Standard SQL Property access ```sql -- Simple keys properties.foo.bar -- Keys with special characters properties.foo['bar-baz'] ``` Unsupported/changed functions Don't use | Use instead `toFloat64OrNull()`, `toFloat64()` | `toFloat()` `toDateOrNull(timestamp)` | `toDate(timestamp)` `LAG()`, `LEAD()` | `lagInFrame()`, `leadInFrame()` with `ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING` `count() | count() cardinality(bitmap) | bitmapCardinality(bitmap) split() | splitByChar(), splitByString() JOIN constraints Relational operators (>, <, >=, <=) are **forbidden** in JOIN clauses. Use CROSS JOIN with WHERE: `sql -- Wrong JOIN persons p ON e.person_id = p.id AND e.timestamp > p.created_at -- Correct CROSS JOIN persons p WHERE e.person_id = p.id AND e.timestamp > p.created_at ` Syntax extensions and HogQL functions Find the reference for [Sparkline, SemVer, Session replays, Actions, Translation, HTML tags and links, Text effects, and more](./references/hogql-extensions.md). Other rules - WHERE clause must come after all JOINs - No semicolons at end of queries - toStartOfWeek(timestamp, 1) for Monday start (numeric, not string) - Always handle nulls before array functions: splitByChar(',', coalesce(field, '')) - Performance: always filter events by timestamp SQL Variables Review the [reference](./references/models-variables.md) for SQL variables and dashboard filters. Available HogQL functions Verify what functions are available using [the reference list](./references/available-functions.md) with suitable bash commands. Examples **Weekly active users with activation event:** `sql SELECT week_of, countIf(weekly_event_count >= 3) FROM ( SELECT person.id AS person_id, toStartOfWeek(timestamp) AS week_of, count() AS weekly_event_count FROM events WHERE event = 'activation_event' AND properties.$current_url = 'https://example.com/foo/' AND toStartOfWeek(now()) - INTERVAL 8 WEEK <= timestamp AND timestamp < toStartOfWeek(now()) GROUP BY person.id, week_of ) GROUP BY week_of ORDER BY week_of DESC ` **Find cohorts by name:** `sql SELECT id, name, count FROM system.cohorts WHERE name ILIKE '%paying%' AND NOT deleted ` **List feature flags:** `sql SELECT key, name, rollout_percentage FROM system.feature_flags WHERE NOT deleted ORDER BY created_at DESC LIMIT 20 ` When to use execute-sql **Use query-` tools whenever the question maps to a supported insight type. These tools produce typed, saveable insights; SQL forfeits that. Reach for `execute-sql` only when no `query- tool can express the question: - **Searching or listing existing PostHog entities** — insights, dashboards, cohorts, feature flags, experiments, surveys. No query-` tool covers these; query the `system. tables. - **Multi-event joins or aggregations across event types** that don't fit a single series. - **Sophisticated queries beyond query-` schemas — custom grouping, window functions, non-trivial CTEs, data warehouse joins. - Pre-filtering or shaping a large dataset before running a `query- call. If a query-` tool fits, use it. Default to `query-; SQL is the escape hatch, not the starting point. Always consult the querying-posthog-data skill Before writing any SQL, read the PostHog querying-posthog-data skill. It is the source of truth for up-to-date HogQL patterns, system table schemas (system.insights, system.dashboards, system.cohorts, etc.), and function references. Do not rely on training data — table and column names drift. Discovery workflow (mandatory) 1. **Warehouse schema** — call read-data-warehouse-schema to verify tables, views, and columns. Do not guess names. For a specific custom warehouse table, inspect its columns with: `sql SELECT columns FROM system.data_warehouse_tables WHERE name = 'my_table' ` 2. **Event taxonomy** — call read-data-schema to verify events, properties, and property values. Do not rely on training data or PostHog defaults. 3. **Write the SQL** only after steps 1 and 2 confirm the data exists, using the verified table and column names. If the required events, properties, or tables do not exist, say so — do not run queries that will return empty results. Handling large results Large JSON values in results (notably full properties objects) are truncated by default. If you anticipate a large result set, or you are selecting the full properties object (e.g., SELECT properties FROM events), dump the results to a file and process them with bash rather than returning them inline. Alternatively, cherry-pick specific keys (properties.$browser) instead of the whole object. Large LLM trace fields are stripped from events.properties For LLM events ($ai_generation, $ai_trace, $ai_span, etc.), these specific keys with large values are stripped from events.properties: - properties.$ai_input - properties.$ai_output - properties.$ai_output_choices - properties.$ai_input_state - properties.$ai_output_state - properties.$ai_tools Prefer query-llm-trace / query-llm-traces-list whenever you need any of those six keys — they contain information on the proper read patterns to a dedicated AI events table which contains these fields. Other AI properties (token counts, costs, model, trace IDs) stay on events in all three regimes and are safe to query directly. Example: searching for existing insights <example> User: Do we have any insights tracking revenue or payments? Assistant: I'll search existing insights and dashboards via SQL. 1. Search insights by name: execute-sql with SELECT id, name, short_id, description FROM system.insights WHERE NOT deleted AND (name ILIKE '%revenue%' OR name ILIKE '%payment%') ORDER BY last_modified_at DESC LIMIT 20 2. If results are sparse, broaden to dashboards: execute-sql with SELECT id, name, description FROM system.dashboards WHERE NOT deleted AND (name ILIKE '%revenue%' OR name ILIKE '%payment%') 3. Validate promising insights with insight-retrieve. 4. Summarize with links. <reasoning> 1. SQL against system.` tables is the fastest way to discover existing entities — no `query- tool covers entity search. 2. ILIKE with multiple terms catches naming variants ("Monthly Revenue", "MRR", "Payment Events"). 3. insight-retrieve` confirms the insight's query configuration still matches intent. </reasoning> </example>experiment-archive
ChatGPTexperiment-create
ChatGPTexperiment-delete
ChatGPTexperiment-duplicate
ChatGPTexperiment-end
ChatGPTexperiment-get
ChatGPTexperiment-get-all
ChatGPTexperiment-launch
ChatGPTexperiment-list
ChatGPTexperiment-pause
ChatGPTexperiment-reset
ChatGPTexperiment-results-get
ChatGPTexperiment-resume
ChatGPTexperiment-ship-variant
ChatGPTexperiment-stats
ChatGPTexperiment-timeseries-results
ChatGPTexperiment-unarchive
ChatGPTexperiment-update
ChatGPTexternal-data-sync-logs
ChatGPTfeature-flag-get-all
ChatGPTfeature-flag-get-definition
ChatGPTfeature-flags-copy-flags-create
ChatGPTfeature-flags-dependent-flags-retrieve
ChatGPTfeature-flags-evaluation-reasons-retrieve
ChatGPTfeature-flags-status-retrieve
ChatGPTfeature-flags-test-evaluation-create
ChatGPTfeature-flags-user-blast-radius-create
ChatGPTget-llm-total-costs-for-project
ChatGPTget_more_tools
ChatGPTinsight-create
ChatGPTshort_id if you want to see the computed results.insight-delete
ChatGPTinsight-get
ChatGPTid or 8-character short_id. Returns the insight metadata and query definition, but NOT the query results. To retrieve the actual data, call the insight-query tool with the same identifier. Optionally accepts variables_override and filters_override to apply one-off overrides to the returned query definition without mutating the saved insight.insight-query
ChatGPTvariables_override and filters_override to run the insight with one-off overrides without mutating the saved definition.insight-update
ChatGPTid or short_id. Can update name, description, query, tags, favorited status, and dashboards. Returns insight metadata only — after updating the query, call the insight-query tool with the same identifier if you want to see the recomputed results.insights-list
ChatGPTshort_id or numeric id.insights-trending-retrieve
ChatGPTview_count and up to 3 recent viewers. Returns metadata only — call insight-query with the returned short_id to fetch the actual data for any of them.logs-alerts-events-list
ChatGPTkind query param narrows to a single event kind.logs-alerts-list
ChatGPTlogs-alerts-retrieve
ChatGPTlogs-alerts-simulate-create
ChatGPT-7d lookback for a healthy threshold.logs-attribute-values-list
ChatGPTlogs-attributes-list
ChatGPTlogs-count
ChatGPTquery-logs — if the count exceeds query-logs's max limit of 1000, narrow the filters before pulling rows. All parameters must be nested inside a query object. When to use - Before query-logs, to confirm the filter set returns a tractable number of rows. If the count is above query-logs's max limit of 1000, narrow the filters. - When the user asks "how many X logs are there?" and you don't need to see individual rows. - To check whether a filter combination matches anything at all before committing to a full query. To find when the volume is concentrated within the window (rather than just the total), follow up with logs-count-ranges — it returns time-bucketed counts with explicit date_from/date_to per bucket so you can drill into a sub-range without reasoning about interval width. Parameters query.dateRange Date range for the count. Defaults to the last hour (-1h). - date_from: Start of the range. Accepts ISO 8601 timestamps or relative formats: -1h, -6h, -1d, -7d. - date_to: End of the range. Same format. Omit or null for "now". query.serviceNames Filter by service names. Unlike query-logs, this tool does NOT require serviceNames — an unfiltered count is cheap and often useful for sizing up a filter before narrowing. query.severityLevels Filter by log severity: trace, debug, info, warn, error, fatal. Omit to include all levels. query.searchTerm Full-text search across log bodies. query.filterGroup Property filters to narrow results. Same format as query-logs filters. Examples Count errors in a service over the last day ``json { "query": { "serviceNames": ["api-gateway"], "severityLevels": ["error", "fatal"], "dateRange": { "date_from": "-1d" } } } ` Confirm a k8s namespace is producing logs at all `json { "query": { "dateRange": { "date_from": "-1h" }, "filterGroup": [ { "key": "k8s.namespace.name", "operator": "exact", "type": "log_resource_attribute", "value": "payments" } ] } } ``logs-count-ranges
ChatGPT{date_from, date_to, count} buckets covering the requested window. Modeled on Elasticsearch's auto_date_histogram — caller specifies a target bucket count, the engine picks the interval. Use this to find where the volume is concentrated before pulling rows. Cheaper than query-logs, more agent-friendly than logs-sparkline-query (each bucket carries explicit date_from/date_to you can feed straight back as the next call's dateRange to drill in). When to use this vs other tools - `logs-count` — total volume in a window. Scalar. - `logs-count-ranges` (this tool) — _when_ in the window the volume sits. Time-bucketed. - `query-logs` — pull individual log rows. Most expensive; only call after counts confirm the window is right-sized. Recursion pattern (the main reason this tool exists) Use the response to narrow into a sub-range without reasoning about interval width: 1. Call logs-count-ranges with the user's window (e.g. last 24h). 2. Pick the bucket(s) of interest (densest, an obvious spike, an unexpectedly empty stretch). 3. Call logs-count-ranges again with that bucket's date_from and date_to as the next dateRange. 4. Repeat up to ~3–4 levels — stop when buckets are shorter than your precision goal (e.g. 1 minute). 5. Once narrowed, call query-logs for the actual rows. This is the same pattern Elasticsearch users follow with auto_date_histogram. Keep recursion shallow — every call is cheap individually but they multiply quickly. Parameters All parameters must be nested inside a query object. query.dateRange Window to bucket. Defaults to the last hour (-1h). Same format as query-logs. query.targetBuckets Approximate bucket count. Defaults to 10, max 100. The engine picks the interval adaptively from a fixed list (1/5/10s, 1/2/5/10/15/30/60/120/240/360/720/1440m) to land near this target — actual count may differ slightly. Empty buckets are dropped, so the response can have fewer rows than targetBuckets. Pick a value based on what you're doing: - 10 (default) — overview, finding spikes, "is this concentrated or spread out?" - 20–30 — characterising a known busy window - 50+ — high-resolution drill-down, only when you know the window is small query.severityLevels, query.serviceNames, query.searchTerm, query.filterGroup Same shape as query-logs. Applied before bucketing. Response ``json { "ranges": [ { "date_from": "2026-04-26T00:00:00", "date_to": "2026-04-26T02:24:00", "count": 1024 }, { "date_from": "2026-04-26T02:24:00", "date_to": "2026-04-26T04:48:00", "count": 47 } ], "interval": "2h" } ` - ranges — buckets ordered by date_from ascending. **Empty buckets are omitted** — infer gaps by comparing each bucket's date_to to the next bucket's date_from. - interval — short-form duration of the chosen bucket width (1s / 5m / 1h / 1d). Informational only — for follow-up queries, use the per-bucket date_from/date_to. Examples Find when errors spiked over the last day `json { "query": { "dateRange": { "date_from": "-1d" }, "targetBuckets": 24, "serviceNames": ["api-gateway"], "severityLevels": ["error", "fatal"] } } ` Drill into the densest hour from a previous call After picking the densest bucket from the response above (say {date_from: "2026-04-26T15:00:00", date_to: "2026-04-26T16:00:00", count: 894}): `json { "query": { "dateRange": { "date_from": "2026-04-26T15:00:00", "date_to": "2026-04-26T16:00:00" }, "targetBuckets": 12, "serviceNames": ["api-gateway"], "severityLevels": ["error", "fatal"] } } ` Reminders - Cap recursion at ~3–4 levels. If your bucket width drops below your precision goal (e.g. 1 minute), stop and call query-logs. - Empty windows return {"ranges": [], "interval": "..."} — that's not an error, it's "I asked, nothing matched." - Always include serviceNames or a resource attribute filter, just like query-logs`. Don't bucket the entire team's log stream.logs-services-create
ChatGPTlogs-sparkline-query
ChatGPTquery object. Parameters query.dateRange Date range for the sparkline. Defaults to the last hour (-1h). - date_from: Start of the range. Accepts ISO 8601 timestamps or relative formats: -1h, -6h, -1d, -7d. - date_to: End of the range. Same format. Omit or null for "now". query.serviceNames Filter by service names. query.severityLevels Filter by log severity: trace, debug, info, warn, error, fatal. Omit to include all levels. query.searchTerm Full-text search across log bodies. query.filterGroup Property filters to narrow results. Same format as query-logs filters. query.sparklineBreakdownBy Break down the sparkline by "severity" (default) or "service". Use "service" to see which services are producing the most logs. Examples Error volume over the last day ``json { "query": { "serviceNames": ["api-gateway"], "severityLevels": ["error", "fatal"], "dateRange": { "date_from": "-1d" } } } ` Log volume by service `json { "query": { "serviceNames": ["api-gateway"], "sparklineBreakdownBy": "service", "dateRange": { "date_from": "-6h" } } } ` Log volume by severity `json { "query": { "serviceNames": ["api-gateway"], "sparklineBreakdownBy": "severity", "dateRange": { "date_from": "-1d" } } } ``organization-get
ChatGPTorganizations-list
ChatGPTproject-get
ChatGPT@current as the ID to fetch the caller's active project.projects-get
ChatGPTproxy-get
ChatGPTproxy-list
ChatGPTquery-error-tracking-issue
ChatGPTquery-error-tracking-issues-list when you have an issueId and need issue status, name/description, first/last seen timestamps, assignee, compact impact counts, top in-app frame, and latest release metadata. Defaults are intentionally useful: last 7 days, test accounts filtered out, aggregate impact included, and no sparkline unless requested. Parameters - issueId: required Error tracking issue UUID. - dateRange: time range for impact counts and latest-event metadata. Defaults to last 7 days. - includeSparkline: set true only if a trend/sparkline helps answer the user. When true, volumeResolution defaults to 12 if not provided. - volumeResolution: number of volume buckets when sparkline data is needed. Next steps Use query-error-tracking-issue-events with the same issueId when the user needs concrete event examples, stack traces, browser/OS/URL context, or $session_id values for Session replay.query-error-tracking-issue-events
ChatGPT$exception events for one Error tracking issue. Use this when the user asks for concrete examples, stack traces, affected URLs, browser/OS/library context, or Session replay links for a specific issue. Returns sampled events with plural exception fields ($exception_types, $exception_values), normalized $exception_list, $exception_fingerprint, $exception_issue_id, $session_id, $lib, browser/OS fields, and $current_url. Parameters - issueId: required Error tracking issue UUID. - dateRange: time range for sampled events. Defaults to last 7 days. - searchQuery: search exception types, values, and current URL. - filterGroup: advanced flat AND property filters applied to sampled events. - verbosity: summary (default), stack, or raw. Use raw only when exact untruncated exception payloads are needed. - onlyAppFrames: defaults to true to reduce vendor-frame noise. - limit: defaults to 1 and maxes at 20. Keep low unless the user asks for multiple examples. Session recordings When $session_id is present and the user asks what happened before the error, call query-session-recordings-list with session_ids to fetch matching recordings. Use multiple $session_id values in one call when available.query-error-tracking-issues-list
ChatGPToccurrences, users, sessions) and optional volume buckets. Use this first when the user asks which errors are happening, which errors are most common, or wants to narrow issues by status, release, library, fingerprint, URL, user, person, or properties. Defaults are intentionally useful: active issues, last 7 days, sorted by occurrences, test accounts filtered out, and compact aggregate counts. Be minimalist. Only add filters needed to answer the user’s question. Do not add "is set" filters unless the user explicitly asks for them. Common filters - status: active, resolved, suppressed, pending_release, archived, or all. Defaults to active. - searchQuery: free-text search for exception names, values, stack frames, and email text. - library: exact $lib match, for example posthog-js. - release: exact release ID, release version, or git commit ID captured in $exception_releases. This intentionally does not match project name, branch, or timestamp fragments. - fingerprint: exact $exception_fingerprint match. - url: substring match on $current_url. - personId: exact PostHog person UUID. - user: user/email text search. - filePath: stack-frame file/source text search. - filterGroup: advanced flat AND property filters. Prefer typed fields above when they fit. Use dateRange for time, not property filters. Omit date_to for now. Next steps - Use query-error-tracking-issue with issueId to inspect one issue. - Use query-error-tracking-issue-events with issueId to fetch sampled exception events, stack traces, URLs, and $session_id values. - If the user asks what people were doing before the error, use $session_id values from issue events with query-session-recordings-list and its session_ids parameter.query-funnel
ChatGPTpaidCustomer or icp_score. - Ensure that you find both the property group and name. Property groups should be one of the following: event, person, session, group. - After selecting a property, validate that the property value accurately reflects the intended criteria. - Find the suitable operator for type (e.g., contains, is set). - If the operator requires a value, use the read-data-schema tool to find the property values. - You set logical operators to combine multiple properties of a single series: AND or OR. Infer the property groups from the user's request. If your first guess doesn't yield any results, try to adjust the property group. Supported operators for the String type are: - equals (exact) - doesn't equal (is_not) - contains (icontains) - doesn't contain (not_icontains) - matches regex (regex) - doesn't match regex (not_regex) - is set - is not set Supported operators for the Numeric type are: - equals (exact) - doesn't equal (is_not) - greater than (gt) - less than (lt) - is set - is not set Supported operators for the DateTime type are: - equals (is_date_exact) - doesn't equal (is_not for existence check) - before (is_date_before) - after (is_date_after) - is set - is not set Supported operators for the Boolean type are: - equals - doesn't equal - is set - is not set All operators take a single value except for equals and doesn't equal which can take one or more values (as an array). Time period You should not filter events by time using property filters. Instead, use the dateRange field. If the question doesn't mention time, use last 30 days as a default time period. Funnel guidelines Exclusion steps Users may want to use exclusion events to filter out conversions in which a particular event occurred between specific steps. These events should not be included in the main sequence. You should include start and end indexes (0-based) for each exclusion where the minimum funnelFromStep is 0 (first step) and the maximum funnelToStep is the number of steps minus one. Exclusion events cannot be actions, only events. IMPORTANT: Exclusion steps filter out conversions where the exclusion event occurred BETWEEN the specified steps. This does NOT exclude users who completed the event before the funnel started or after it ended. For example, there is a sequence with three steps: sign up (step 0), finish onboarding (step 1), purchase (step 2). If the user wants to exclude all conversions in which users navigated away between sign up and finishing onboarding, the exclusion step will be $pageleave with funnelFromStep: 0 and funnelToStep: 1. Breakdown A breakdown is used to segment data by a single property value. They divide all defined funnel series into multiple subseries based on the values of the property. Include a breakdown only when it is essential to directly answer the user's question. You should not add a breakdown if the question can be addressed without additional segmentation. When using breakdowns, you should: - Identify the property group and name for a breakdown. - Provide the property name for a breakdown. - Validate that the property value accurately reflects the intended criteria. Examples of using a breakdown: - page views to sign up funnel by country: you need to find a property such as $geoip_country_code and set it as a breakdown. - conversion rate of users who have completed onboarding after signing up by an organization: you need to find a property such as organization name and set it as a breakdown. Combining multiple events into a single step (GroupNode) Use a `GroupNode` when the user wants a single funnel step to match any of several events — e.g. "Pageview OR Pageleave counts as one step", or "the user signed up via any of these channels". Different filters per event are fine — put them on the inner nodes. Use separate steps instead when the user wants the events to occur in sequence. Only OR is supported. Funnel math (first_time_for_user etc.), optionalInFunnel, and step-wide property filters are not supported on a grouped step — filters must live on the inner nodes, and any math / optional handling must use a regular non-grouped step. Where things live: - On the group: only name (display label). - On each inner node: event (or action id), properties, name — all respected normally; per-node properties apply only to that node. Example — funnel with a grouped step A 3-step funnel where the middle step matches either $pageview on Safari or $pageleave on Chrome: ``json { "kind": "FunnelsQuery", "series": [ { "kind": "EventsNode", "event": "sign up" }, { "kind": "GroupNode", "operator": "OR", "name": "Pageview on Safari, Pageleave on Chrome", "nodes": [ { "kind": "EventsNode", "event": "$pageview", "name": "Pageview", "properties": [{ "key": "$browser", "operator": "exact", "type": "event", "value": ["Safari"] }] }, { "kind": "EventsNode", "event": "$pageleave", "name": "Pageleave", "properties": [{ "key": "$browser", "operator": "exact", "type": "event", "value": ["Chrome"] }] } ] }, { "kind": "EventsNode", "event": "purchase" } ], "dateRange": { "date_from": "-30d" } } ` Examples Conversion from first event ingested to insight saved for organizations over 6 months `json { "kind": "FunnelsQuery", "series": [ { "kind": "EventsNode", "event": "first team event ingested" }, { "kind": "EventsNode", "event": "insight saved" } ], "dateRange": { "date_from": "-6m" }, "interval": "month", "aggregation_group_type_index": 0, "funnelsFilter": { "funnelOrderType": "ordered", "funnelVizType": "trends", "funnelWindowInterval": 14, "funnelWindowIntervalUnit": "day" }, "filterTestAccounts": true } ` Signup page CTA click rate within one hour, excluding page leaves, broken down by OS `json { "kind": "FunnelsQuery", "series": [ { "kind": "EventsNode", "event": "$pageview", "properties": [{ "key": "$current_url", "type": "event", "value": "signup", "operator": "icontains" }] }, { "kind": "EventsNode", "event": "click subscribe button", "properties": [{ "key": "$current_url", "type": "event", "value": "signup", "operator": "icontains" }] } ], "dateRange": { "date_from": "-180d" }, "interval": "week", "funnelsFilter": { "funnelWindowInterval": 1, "funnelWindowIntervalUnit": "hour", "funnelOrderType": "ordered", "exclusions": [{ "kind": "EventsNode", "event": "$pageleave", "funnelFromStep": 0, "funnelToStep": 1 }] }, "breakdownFilter": { "breakdown_type": "event", "breakdown": "$os" }, "filterTestAccounts": true } ` Credit card purchase rate from viewing a product with strict ordering (no events in between) `json { "kind": "FunnelsQuery", "series": [ { "kind": "EventsNode", "event": "view product" }, { "kind": "EventsNode", "event": "purchase", "properties": [{ "key": "paymentMethod", "type": "event", "value": "credit_card", "operator": "exact" }] } ], "dateRange": { "date_from": "-30d" }, "funnelsFilter": { "funnelOrderType": "strict", "funnelWindowInterval": 14, "funnelWindowIntervalUnit": "day" }, "filterTestAccounts": true } ` View product to buy button to purchase, using actions and events `json { "kind": "FunnelsQuery", "series": [ { "kind": "ActionsNode", "id": 8882, "name": "view product" }, { "kind": "EventsNode", "event": "click buy button" }, { "kind": "ActionsNode", "id": 573, "name": "purchase", "properties": [ { "key": "shipping_method", "value": "express_delivery", "operator": "icontains", "type": "event" } ] } ], "funnelsFilter": { "funnelVizType": "steps" }, "filterTestAccounts": true } ` Reminders - You MUST ALWAYS use AT LEAST TWO series (events or actions) in the funnel. - Ensure that any properties included are directly relevant to the context and objectives of the user's question. Avoid unnecessary or unrelated details. - Avoid overcomplicating the response with excessive property filters. Focus on the simplest solution. - The default funnel step order is ordered (events in sequence but with other events allowed in between). Use strict when events should happen consecutively with no events in between. Use unordered` when order doesn't matter. - Exclusion events in funnels only exclude conversions where the event happened between the specified steps, not before or after the funnel.query-lifecycle
ChatGPTpaidCustomer or icp_score. - Ensure that you find both the property group and name. Property groups should be one of the following: event, person, session, group. - After selecting a property, validate that the property value accurately reflects the intended criteria. - Find the suitable operator for type (e.g., contains, is set). - If the operator requires a value, use the read-data-schema tool to find the property values. - You set logical operators to combine multiple properties of a single series: AND or OR. Infer the property groups from the user's request. If your first guess doesn't yield any results, try to adjust the property group. Supported operators for the String type are: - equals (exact) - doesn't equal (is_not) - contains (icontains) - doesn't contain (not_icontains) - matches regex (regex) - doesn't match regex (not_regex) - is set - is not set Supported operators for the Numeric type are: - equals (exact) - doesn't equal (is_not) - greater than (gt) - less than (lt) - is set - is not set Supported operators for the DateTime type are: - equals (is_date_exact) - doesn't equal (is_not for existence check) - before (is_date_before) - after (is_date_after) - is set - is not set Supported operators for the Boolean type are: - equals - doesn't equal - is set - is not set All operators take a single value except for equals and doesn't equal which can take one or more values (as an array). Time period You should not filter events by time using property filters. Instead, use the dateRange field. If the question doesn't mention time, use last 30 days as a default time period. Lifecycle guidelines Lifecycle insights analyze a single event or action over time. The series array must contain exactly one item. If the user mentions multiple events, pick the most relevant one or clarify. Lifecycle statuses Each user is categorized into one of four statuses for each time period: - New – the user performed the event for the first time ever during this period. - Returning – the user was active in the previous period and is active again in the current period. - Resurrecting – the user was inactive for one or more periods and became active again. - Dormant – the user was active in the previous period but did not perform the event in the current period. Dormant counts are shown as negative values. Time interval Specify the time interval using the interval field. Available intervals are: hour, day, week, month. The default is day. Unless the user has specified otherwise, use the following default interval: - If the time period is less than two days, use the hour interval. - If the time period is less than a month, use the day interval. - If the time period is less than three months, use the week interval. - Otherwise, use the month interval. Toggled lifecycles Use toggledLifecycles in lifecycleFilter to control which lifecycle statuses are displayed. By default, all four statuses are shown. Only set this when the user wants to focus on specific statuses (e.g., only new and dormant users). Math aggregation Lifecycle insights do not support math aggregation types. Do not set math on the series node. Examples Daily lifecycle of pageviews over the last 30 days ``json { "kind": "LifecycleQuery", "series": [{ "kind": "EventsNode", "event": "$pageview" }], "dateRange": { "date_from": "-30d" }, "interval": "day" } ` Weekly lifecycle of sign ups, excluding test accounts `json { "kind": "LifecycleQuery", "series": [{ "kind": "EventsNode", "event": "user signed up" }], "dateRange": { "date_from": "-90d" }, "interval": "week", "filterTestAccounts": true } ` Monthly lifecycle of "insight created" showing only new and dormant users `json { "kind": "LifecycleQuery", "series": [{ "kind": "EventsNode", "event": "insight created" }], "dateRange": { "date_from": "-12m" }, "interval": "month", "lifecycleFilter": { "toggledLifecycles": ["new", "dormant"] }, "filterTestAccounts": true } ` Lifecycle of purchases by mobile users `json { "kind": "LifecycleQuery", "series": [{ "kind": "EventsNode", "event": "purchase completed" }], "dateRange": { "date_from": "-30d" }, "interval": "day", "properties": [{ "key": "$os", "operator": "exact", "type": "event", "value": ["iOS", "Android"] }] } ` Reminders - Lifecycle insights support only **one** series — do not add multiple events or actions. - Do not set math` on the series node — lifecycle does not support math aggregation. - Ensure that any properties included are directly relevant to the context and objectives of the user's question. Avoid unnecessary or unrelated details. - Avoid overcomplicating the response with excessive property filters. Focus on the simplest solution.query-llm-trace
ChatGPTquery-llm-traces-list to inspect the complete event tree. Use cases: - Inspect the full input/output of each generation in a trace - Debug a specific error trace found in the list - Examine the agent's decision-making flow across spans - Review tool calls and their results within a trace - Analyze token usage and costs per generation CRITICAL: This tool requires a traceId. Get the trace ID from query-llm-traces-list results first. Response shape The response contains a single trace in JSON format with: - id — the trace ID - traceName — name of the trace (if set via SDK) - createdAt — timestamp of the first event in the trace - distinctId — the person's distinct ID - aiSessionId — session ID grouping related traces (e.g., a conversation) - totalLatency — total latency in seconds - inputTokens / outputTokens — token counts across all generations - inputCost / outputCost / totalCost — costs in USD - inputState / outputState — JSON input/output state from the root $ai_trace event (e.g., conversation messages) - events — all child events in the trace at every nesting depth (not just direct children). Each event has full properties. Unlike query-llm-traces-list, this tool does NOT return errorCount, isSupportTrace, or tools — those are summary fields on the list tool only. Event types and their properties Each event in events has an event field indicating its type. Key properties vary by type: - `$ai_generation` / `$ai_embedding` — an LLM or embedding API call. Properties include $ai_input (input prompt JSON), $ai_output_choices (output message JSON), $ai_model, $ai_provider, $ai_latency, $ai_input_tokens, $ai_output_tokens, $ai_input_cost_usd, $ai_output_cost_usd, $ai_total_cost_usd, $ai_tools_called, $ai_is_error, $ai_error. - `$ai_span` — a unit of work within a trace (e.g., a retrieval step, tool execution). Properties include $ai_input_state, $ai_output_state, $ai_latency, $ai_span_name, $ai_parent_id. - `$ai_metric` — a named evaluation metric. Properties include $ai_metric_name, $ai_metric_value. - `$ai_feedback` — user-provided feedback. Properties include $ai_feedback_text. Note: $ai_trace events are NOT included in the events array — their data is surfaced via the trace-level inputState, outputState, and traceName fields. Tree structure (IDs and parent-child relationships) Events in a trace form a tree. Each event carries three IDs that define its position: - $ai_trace_id — present on every event, identifies which trace it belongs to (same as the trace's id) - $ai_span_id (or $ai_generation_id for generations) — the event's own unique identifier - $ai_parent_id — points to the parent event's $ai_span_id To reconstruct the tree: 1. Events where $ai_parent_id equals $ai_trace_id are root-level children of the trace 2. Other events are children of the event whose $ai_span_id matches their $ai_parent_id 3. Group events by $ai_parent_id and walk from root children downward Generations ($ai_generation) and embeddings ($ai_embedding) are always leaf nodes. Spans ($ai_span) can have children. Examples Fetch a trace by ID ``json { "kind": "TraceQuery", "traceId": "c9222e05-8708-41b8-98ea-d4a21849e761" } ` Fetch with a date range hint If the trace is old, provide a date range to help the query find it efficiently: `json { "kind": "TraceQuery", "traceId": "c9222e05-8708-41b8-98ea-d4a21849e761", "dateRange": { "date_from": "-30d" } } ` Reminders - Always get the traceId from query-llm-traces-list results — do not guess or fabricate trace IDs. - If no date range is provided, the default lookback window is used. For older traces, provide an explicit dateRange. - The events array contains ALL events in the trace (including deeply nested ones), making this suitable for full tree reconstruction. - Use query-llm-traces-list` first to find traces, then this tool to inspect a specific one.query-llm-traces-list
ChatGPT$ai_model, $ai_provider). Examples of use cases include: - How much are we spending on LLM tokens per day? - Which LLM generations are the slowest? - Are there any traces with errors in the last 24 hours? - What models are being used and how do their costs compare? - Show me traces for a specific user to debug their experience. - Are there any traces with unusually high token usage? CRITICAL: Be minimalist. Only include filters and settings that are essential to answer the user's specific question. Default settings are usually sufficient unless the user explicitly requests customization. Data narrowing Property filters Use property filters to narrow results. Only include property filters when they are essential to directly answer the user's question. Avoid adding them if the question can be addressed without additional segmentation and always use the minimum set of property filters needed. IMPORTANT: Do not check if a property is set unless the user explicitly asks for it. When using a property filter, you should: - Prioritize properties directly related to the context or objective of the user's query. Common AI properties include $ai_model, $ai_provider, $ai_trace_id, $ai_session_id, $ai_latency, $ai_input_tokens, $ai_output_tokens, $ai_total_cost_usd, $ai_is_error, $ai_http_status, $ai_span_name. - Note: $ai_is_error and $ai_error are valid filter properties but may not appear via read-data-schema. Use $ai_is_error with operator exact and value ["true"] to find error traces, or use $ai_error with is set to find traces with error messages. - Ensure that you find both the property group and name. Property groups should be one of the following: event, person, session, group. - After selecting a property, validate that the property value accurately reflects the intended criteria. - Find the suitable operator for type (e.g., contains, is set). - If the operator requires a value, use the read-data-schema tool to find the property values. Infer the property groups from the user's request. If your first guess doesn't yield any results, try to adjust the property group. Supported operators for the String type are: - equals (exact) - doesn't equal (is_not) - contains (icontains) - doesn't contain (not_icontains) - matches regex (regex) - doesn't match regex (not_regex) - is set - is not set Supported operators for the Numeric type are: - equals (exact) - doesn't equal (is_not) - greater than (gt) - less than (lt) - is set - is not set Supported operators for the DateTime type are: - equals (is_date_exact) - doesn't equal (is_not for existence check) - before (is_date_before) - after (is_date_after) - is set - is not set Supported operators for the Boolean type are: - equals - doesn't equal - is set - is not set All operators take a single value except for equals and doesn't equal which can take one or more values (as an array). Time period You should not filter events by time using property filters. Instead, use the dateRange field. If the question doesn't mention time, use last 7 days as a default time period. Traces guidelines This is a listing tool, not a visualization/insight tool. It returns a paginated list of LLM traces — it does NOT support series, breakdowns, math aggregations, or chart types. Response shape Each trace in the results contains: - id — unique trace ID - traceName — name of the trace (if set via SDK) - createdAt — timestamp of the first event in the trace - distinctId — the person's distinct ID - aiSessionId — session ID grouping related traces (e.g., a conversation) - totalLatency — total latency in seconds - inputTokens / outputTokens — token counts across all generations in the trace - inputCost / outputCost / totalCost — costs in USD - inputState / outputState — JSON input/output state of the trace (e.g., conversation messages), from the $ai_trace event - errorCount — number of errors in the trace - isSupportTrace — whether the trace was from a support impersonation session - tools — list of tool names called during the trace - events — list of direct child events (generations, metrics, feedback). Each event's properties contains the full event data — see "Event types and their properties" below. Event types and their properties Each event in events has an event field indicating its type. The key properties vary by type: - `$ai_generation` / `$ai_embedding` — an LLM or embedding API call. Properties include $ai_input (input prompt JSON), $ai_output_choices (output message JSON), $ai_model, $ai_provider, $ai_latency, $ai_input_tokens, $ai_output_tokens, $ai_input_cost_usd, $ai_output_cost_usd, $ai_total_cost_usd, $ai_tools_called, $ai_is_error, $ai_error. - `$ai_span` — a unit of work within a trace (e.g., a retrieval step, a tool execution). Properties include $ai_input_state, $ai_output_state, $ai_latency, $ai_span_name, $ai_parent_id. - `$ai_trace` — the root trace event. Properties include $ai_input_state (e.g., conversation messages sent), $ai_output_state (e.g., final response), $ai_span_name. - `$ai_metric` — a named evaluation metric. Properties include $ai_metric_name, $ai_metric_value. - `$ai_feedback` — user-provided feedback. Properties include $ai_feedback_text. All event types share $ai_trace_id, $ai_span_id, and $ai_parent_id for tree structure (see below). Tree structure (IDs and parent-child relationships) Events in a trace form a tree. Each event carries three IDs that define its position: - $ai_trace_id — present on every event, identifies which trace it belongs to (same as the trace's id) - $ai_span_id (or $ai_generation_id for generations) — the event's own unique identifier - $ai_parent_id — points to the parent event's $ai_span_id To reconstruct the tree: 1. Events where $ai_parent_id equals $ai_trace_id are root-level children of the trace 2. Other events are children of the event whose $ai_span_id matches their $ai_parent_id 3. Group events by $ai_parent_id and walk from root children downward Generations ($ai_generation) and embeddings ($ai_embedding) are always leaf nodes. Spans ($ai_span) can have children. Important: This list tool only returns direct children of the trace (events where $ai_parent_id = trace ID) plus all $ai_metric and $ai_feedback events — NOT deeply nested events. For the full event tree with all nested children, use query-llm-trace with the trace's id. Pagination Use limit and offset for pagination. The default limit is 100. The response includes a hasMore field indicating whether more results are available. Filtering - filterTestAccounts — exclude internal/test users - filterSupportTraces — exclude support impersonation traces - personId — filter by a specific person UUID - groupKey + groupTypeIndex — filter by a specific group - randomOrder — use random ordering instead of newest-first (useful for representative sampling) Examples Recent traces with errors ``json { "kind": "TracesQuery", "dateRange": { "date_from": "-7d" }, "filterTestAccounts": true, "properties": [{ "key": "$ai_is_error", "operator": "exact", "type": "event", "value": ["true"] }], "limit": 50 } ` Traces for a specific model `json { "kind": "TracesQuery", "dateRange": { "date_from": "-7d" }, "filterTestAccounts": true, "properties": [{ "key": "$ai_model", "operator": "exact", "type": "event", "value": ["gpt-4o"] }] } ` Traces for a specific person `json { "kind": "TracesQuery", "dateRange": { "date_from": "-30d" }, "personId": "01234567-89ab-cdef-0123-456789abcdef", "filterTestAccounts": true } ` Random sample of traces (avoids recency bias) `json { "kind": "TracesQuery", "dateRange": { "date_from": "-30d" }, "filterTestAccounts": true, "randomOrder": true, "limit": 20 } ` Reminders - Ensure that any properties included are directly relevant to the context and objectives of the user's question. Avoid unnecessary or unrelated details. - Avoid overcomplicating the response with excessive property filters. Focus on the simplest solution. - This tool returns raw trace data — it does not aggregate or visualize. For aggregated LLM metrics over time (e.g. total token usage per day), use query-trends with AI events like $ai_generation instead. - Use filterTestAccounts: true by default to exclude internal users unless the user asks otherwise. - The default time range is last 7 days. LLM trace data tends to be recent, so shorter ranges are usually appropriate. - For deep inspection of a single trace (full event tree with all nested children and complete properties), use query-llm-trace with the trace's id`.query-logs
ChatGPTseverity_text over severity_number / level, and be aware that trace_id and span_id return zero-padded strings rather than null when unset. Use logs-attributes-list and logs-attribute-values-list to discover available attributes before building filters. Workflow — follow this order every time 1. Discover services first. Call logs-attribute-values-list with key: "service.name" and attribute_type: "resource" to see available services. 2. Explore resource attributes. Call logs-attributes-list with attribute_type: "resource" to discover resource-level attributes (e.g. k8s.pod.name, k8s.namespace.name). Then call logs-attribute-values-list with attribute_type: "resource" for relevant attributes to validate what data exists. 3. Explore log attributes if needed. Call logs-attributes-list (defaults to log attributes) and logs-attribute-values-list to discover log-level attributes. 4. Size the total volume with `logs-count`. Call logs-count with the discovered serviceNames and filters. If it exceeds query-logs's max limit of 1000 — or if the user's question is about _when_ something happened — continue to step 5. 5. Find where the volume sits with `logs-count-ranges`. Call logs-count-ranges to get time-bucketed counts. Each bucket carries explicit date_from/date_to you can pass straight back as the next call's dateRange to drill into a sub-range. Recurse up to 3–4 levels to narrow onto a spike or a specific window. Stop when the bucket width drops below your precision goal (e.g. 1 minute). 6. Only then query logs. Once the count is in range and the window is right-sized, call query-logs with serviceNames and any additional filters. Many cheap calls (attribute/value queries, counts, count-ranges) beat one expensive query-logs. Prefer thorough exploration over speculative log searches. CRITICAL: Be minimalist. Only include filters and settings that are essential to answer the user's specific question. Default settings are usually sufficient unless the user explicitly requests customization. MANDATORY: Never call query-logs without setting serviceNames or at least one log_resource_attribute filter. Unfiltered log queries are too broad, expensive, and noisy. If the user hasn't specified a service, use the workflow above to discover services first, then ask or infer. All parameters must be nested inside a query object. Data narrowing Property filters Use property filters via the query.filterGroup field to narrow results. Only include property filters when they are essential to directly answer the user's question. When using a property filter, you should: - Choose the right type. Log property types are: - log — filters the log body/message. Use key "message" for this type. - log_attribute — filters log-level attributes (e.g. "k8s.container.name", "http.method"). - log_resource_attribute — filters resource-level attributes (e.g. k8s labels, deployment info). - Use `logs-attributes-list` to discover available attribute keys before building filters. - Use `logs-attribute-values-list` to discover valid values for a specific attribute key. - Find the suitable operator for the value type (see supported operators below). Important: The logs-attributes-list and logs-attribute-values-list tools default to attribute_type: "log" (log-level attributes). To search resource-level attributes (e.g. k8s.pod.name, k8s.namespace.name), you must explicitly pass attribute_type: "resource". Forgetting this will return log-level attributes when you intended resource-level ones. Supported operators: - String: exact, is_not, icontains, not_icontains, regex, not_regex - Numeric: exact, gt, lt - Date: is_date_exact, is_date_before, is_date_after - Existence (no value needed): is_set, is_not_set The value field accepts a string, number, or array of strings depending on the operator. Omit value for is_set/is_not_set. Time period Use the query.dateRange field to control the time window. If the question doesn't mention time, the default is the last hour (-1h). Examples of relative dates: -1h, -6h, -1d, -7d, -30d. Parameters All parameters go inside query. query.severityLevels Filter by log severity: trace, debug, info, warn, error, fatal. Omit to include all levels. query.serviceNames Filter by service names. Use logs-attribute-values-list with key: "service.name" and attribute_type: "resource" to discover available services. query.searchTerm Full-text search across log bodies. Use this when the user is looking for specific text in log messages. query.orderBy Sort by timestamp: latest (default) or earliest. query.filterGroup A list of property filters to narrow results. Each filter specifies key, operator, type (log/log_attribute/log_resource_attribute), and optionally value. See the "Property filters" section above. query.dateRange Date range to filter results. Defaults to the last hour (-1h). - date_from: Start of the range. Accepts ISO 8601 timestamps or relative formats: -1h, -6h, -1d, -7d, -30d. - date_to: End of the range. Same format. Omit or null for "now". query.limit Maximum number of results (1-1000). Defaults to 100. query.after Cursor for pagination. Use the nextCursor value from the previous response. Examples List recent error logs ``json { "query": { "severityLevels": ["error", "fatal"], "serviceNames": ["<service>"] } } ` Search for a specific log message `json { "query": { "searchTerm": "connection refused", "serviceNames": ["<service>"], "dateRange": { "date_from": "-6h" } } } ` Filter logs from a specific service `json { "query": { "serviceNames": ["api-gateway"], "dateRange": { "date_from": "-1d" } } } ` Filter by a log attribute `json { "query": { "serviceNames": ["<service>"], "filterGroup": [{ "key": "http.status_code", "operator": "exact", "type": "log_attribute", "value": "500" }], "dateRange": { "date_from": "-1d" } } } ` Combine severity and attribute filters `json { "query": { "severityLevels": ["error"], "filterGroup": [ { "key": "k8s.container.name", "operator": "exact", "type": "log_resource_attribute", "value": "web" } ], "dateRange": { "date_from": "-12h" } } } ` Filter by log body content using property filter `json { "query": { "serviceNames": ["<service>"], "filterGroup": [{ "key": "message", "operator": "icontains", "type": "log", "value": "timeout" }] } } ` Check if an attribute exists `json { "query": { "serviceNames": ["<service>"], "filterGroup": [{ "key": "trace_id", "operator": "is_set", "type": "log_attribute" }] } } ` Reminders - Always set serviceNames or a resource attribute filter. Never run a broad unfiltered log query. - Limit dateRange to at most -1d (24 hours) unless the user explicitly requests a longer range. - When using logs-attributes-list or logs-attribute-values-list, remember they default to attribute_type: "log". Pass attribute_type: "resource" to search resource-level attributes. - Ensure that any property filters are directly relevant to the user's question. Avoid unnecessary filtering. - Use logs-attributes-list and logs-attribute-values-list to discover attributes before guessing filter keys/values. - Prefer searchTerm for simple text matching; use filterGroup with type log and key message` for regex or exact matching.query-paths
ChatGPTpaidCustomer or icp_score. - Ensure that you find both the property group and name. Property groups should be one of the following: event, person, session, group. - After selecting a property, validate that the property value accurately reflects the intended criteria. - Find the suitable operator for type (e.g., contains, is set). - If the operator requires a value, use the read-data-schema tool to find the property values. - You set logical operators to combine multiple properties of a single series: AND or OR. Infer the property groups from the user's request. If your first guess doesn't yield any results, try to adjust the property group. Supported operators for the String type are: - equals (exact) - doesn't equal (is_not) - contains (icontains) - doesn't contain (not_icontains) - matches regex (regex) - doesn't match regex (not_regex) - is set - is not set Supported operators for the Numeric type are: - equals (exact) - doesn't equal (is_not) - greater than (gt) - less than (lt) - is set - is not set Supported operators for the DateTime type are: - equals (is_date_exact) - doesn't equal (is_not for existence check) - before (is_date_before) - after (is_date_after) - is set - is not set Supported operators for the Boolean type are: - equals - doesn't equal - is set - is not set All operators take a single value except for equals and doesn't equal which can take one or more values (as an array). Time period You should not filter events by time using property filters. Instead, use the dateRange field. If the question doesn't mention time, use last 30 days as a default time period. Paths guidelines Event types Paths analyze sequences of events. Specify which event types to include using includeEventTypes. If omitted, all events are included without type filtering. - $pageview - web page views. Path values come from $current_url, with trailing slashes stripped, so they must match your stored URL format. This is often a path like /login, but may also be a full URL like https://example.com/login. Best for analyzing website navigation flows. This is the most common choice. - $screen - mobile screen views. Path values are screen names (from $screen_name). Use for mobile app navigation analysis. - custom_event - custom events (any event whose name does not start with $). Path values are event names. Use for analyzing flows of custom-tracked events like button clicks, form submissions, or feature usage. - hogql - custom HogQL expression. Use with pathsHogQLExpression for advanced path definitions. You can combine multiple types. For example, include both $pageview and custom_event to see how page views and custom events interleave. Start and end points Use startPoint to filter paths that begin at a specific step, or endPoint to filter paths that end at a specific step. The value format depends on the event type: - For $pageview: use the same URL format as your $current_url values, often paths like /login, /dashboard, /settings, but sometimes full URLs - For $screen: use screen names - For custom_event: use event names like user signed up, purchase completed Path cleaning Use localPathCleaningFilters to normalize dynamic URLs. Each filter has a regex pattern (ClickHouse regex syntax) and an alias replacement. Filters are applied in sequence using replaceRegexpAll(path, regex, alias). For example, to normalize product URLs: { "regex": "\\/product\\/\\d+", "alias": "/product/:id" }. Use pathGroupings for simpler glob-like grouping of paths into single nodes. Use * as a wildcard — the patterns are auto-escaped so only * has special meaning. For example, /product/* groups all product sub-pages into one node. Exclusions Use excludeEvents to remove specific path items that clutter the visualization. The values must match path item values, not event types: for $pageview paths these must match your stored $current_url format (e.g., /health-check or https://example.com/health-check), for custom_event paths these are event names (e.g., heartbeat). To control which event types are included, use includeEventTypes instead. Examples What pages do users visit after the homepage? ``json { "kind": "PathsQuery", "pathsFilter": { "includeEventTypes": ["$pageview"], "startPoint": "/", "stepLimit": 5 }, "dateRange": { "date_from": "-30d" }, "filterTestAccounts": true } ` What do users do after signing up? `json { "kind": "PathsQuery", "pathsFilter": { "includeEventTypes": ["custom_event"], "startPoint": "user signed up", "stepLimit": 5 }, "dateRange": { "date_from": "-30d" }, "filterTestAccounts": true } ` Navigation paths excluding noisy URLs `json { "kind": "PathsQuery", "pathsFilter": { "includeEventTypes": ["$pageview"], "excludeEvents": ["/health-check", "/ping"], "stepLimit": 5, "edgeLimit": 30 }, "dateRange": { "date_from": "-14d" }, "filterTestAccounts": true } ` Custom event paths excluding noisy events `json { "kind": "PathsQuery", "pathsFilter": { "includeEventTypes": ["custom_event"], "excludeEvents": ["heartbeat"], "stepLimit": 5 }, "dateRange": { "date_from": "-14d" }, "filterTestAccounts": true } ` Paths with URL cleaning for dynamic segments `json { "kind": "PathsQuery", "pathsFilter": { "includeEventTypes": ["$pageview"], "stepLimit": 5, "localPathCleaningFilters": [ { "regex": "\\/user\\/\\d+", "alias": "/user/:id" }, { "regex": "\\/project\\/[a-f0-9-]+", "alias": "/project/:id" } ] }, "dateRange": { "date_from": "-30d" }, "filterTestAccounts": true } ` What paths lead to the pricing page for mobile users? `json { "kind": "PathsQuery", "pathsFilter": { "includeEventTypes": ["$pageview"], "endPoint": "/pricing", "stepLimit": 5 }, "properties": [{ "key": "$os", "operator": "exact", "type": "event", "value": ["iOS", "Android"] }], "dateRange": { "date_from": "-30d" }, "filterTestAccounts": true } ` Reminders - Ensure that any properties included are directly relevant to the context and objectives of the user's question. Avoid unnecessary or unrelated details. - Avoid overcomplicating the response with excessive property filters. Focus on the simplest solution. - Always specify includeEventTypes to scope the analysis to relevant event types. If omitted, all events are included which may produce noisy results. - Use $pageview as the default event type for web navigation questions. - Path cleaning filters (localPathCleaningFilters) use ClickHouse regex and are only needed when dynamic URL segments would fragment the visualization. Path groupings (pathGroupings) use glob-like patterns with *` wildcards for simpler cases. - Paths group events into sessions with a 30-minute inactivity threshold — events more than 30 minutes apart start a new path session.query-retention
ChatGPTpaidCustomer or icp_score. - Ensure that you find both the property group and name. Property groups should be one of the following: event, person, session, group. - After selecting a property, validate that the property value accurately reflects the intended criteria. - Find the suitable operator for type (e.g., contains, is set). - If the operator requires a value, use the read-data-schema tool to find the property values. - You set logical operators to combine multiple properties of a single series: AND or OR. Infer the property groups from the user's request. If your first guess doesn't yield any results, try to adjust the property group. Supported operators for the String type are: - equals (exact) - doesn't equal (is_not) - contains (icontains) - doesn't contain (not_icontains) - matches regex (regex) - doesn't match regex (not_regex) - is set - is not set Supported operators for the Numeric type are: - equals (exact) - doesn't equal (is_not) - greater than (gt) - less than (lt) - is set - is not set Supported operators for the DateTime type are: - equals (is_date_exact) - doesn't equal (is_not for existence check) - before (is_date_before) - after (is_date_after) - is set - is not set Supported operators for the Boolean type are: - equals - doesn't equal - is set - is not set All operators take a single value except for equals and doesn't equal which can take one or more values (as an array). Time period You should not filter events by time using property filters. Instead, use the dateRange field. If the question doesn't mention time, use last 30 days as a default time period. Retention guidelines Retention insights always require two entities: - The activation event (targetEntity) – determines if the user is a part of a cohort (when they "start"). - The retention event (returningEntity) – determines whether a user has been retained (when they "return"). For activation and retention events, use the $pageview event by default or the equivalent for mobile apps $screen. Avoid infrequent or inconsistent events like signed in unless asked explicitly, as they skew the data. The activation and retention events can be the same (e.g., both $pageview to see if users who viewed pages come back to view pages again) or different (e.g., activation is signed up and retention is completed purchase to see if sign-ups convert to purchases over time). Examples Weekly retention of users who created an insight ``json { "kind": "RetentionQuery", "retentionFilter": { "period": "Week", "totalIntervals": 9, "targetEntity": { "id": "insight created", "name": "insight created", "type": "events" }, "returningEntity": { "id": "insight created", "name": "insight created", "type": "events" }, "retentionType": "retention_first_time", "retentionReference": "total", "cumulative": false }, "filterTestAccounts": true } ` Do users who sign up come back to view pages? `json { "kind": "RetentionQuery", "retentionFilter": { "period": "Week", "totalIntervals": 8, "targetEntity": { "id": "user signed up", "name": "user signed up", "type": "events" }, "returningEntity": { "id": "$pageview", "name": "$pageview", "type": "events" }, "retentionType": "retention_first_time", "retentionReference": "total", "cumulative": false }, "dateRange": { "date_from": "-60d" }, "filterTestAccounts": true } ` Daily retention of pageviews for mobile users only `json { "kind": "RetentionQuery", "retentionFilter": { "period": "Day", "totalIntervals": 14, "targetEntity": { "id": "$pageview", "name": "$pageview", "type": "events" }, "returningEntity": { "id": "$pageview", "name": "$pageview", "type": "events" }, "retentionType": "retention_first_time", "retentionReference": "total", "cumulative": false }, "properties": [{ "key": "$os", "operator": "exact", "type": "event", "value": ["iOS", "Android"] }], "dateRange": { "date_from": "-30d" }, "filterTestAccounts": true } `` Reminders - Ensure that any properties included are directly relevant to the context and objectives of the user's question. Avoid unnecessary or unrelated details. - Avoid overcomplicating the response with excessive property filters. Focus on the simplest solution.query-stickiness
ChatGPTpaidCustomer or icp_score. - Ensure that you find both the property group and name. Property groups should be one of the following: event, person, session, group. - After selecting a property, validate that the property value accurately reflects the intended criteria. - Find the suitable operator for type (e.g., contains, is set). - If the operator requires a value, use the read-data-schema tool to find the property values. - You set logical operators to combine multiple properties of a single series: AND or OR. Infer the property groups from the user's request. If your first guess doesn't yield any results, try to adjust the property group. Supported operators for the String type are: - equals (exact) - doesn't equal (is_not) - contains (icontains) - doesn't contain (not_icontains) - matches regex (regex) - doesn't match regex (not_regex) - is set - is not set Supported operators for the Numeric type are: - equals (exact) - doesn't equal (is_not) - greater than (gt) - less than (lt) - is set - is not set Supported operators for the DateTime type are: - equals (is_date_exact) - doesn't equal (is_not for existence check) - before (is_date_before) - after (is_date_after) - is set - is not set Supported operators for the Boolean type are: - equals - doesn't equal - is set - is not set All operators take a single value except for equals and doesn't equal which can take one or more values (as an array). Time period You should not filter events by time using property filters. Instead, use the dateRange field. If the question doesn't mention time, use last 30 days as a default time period. Stickiness guidelines Stickiness insights measure engagement intensity — how many intervals (days, weeks, etc.) within a date range each user performed an event. Unlike trends which show event counts over time, stickiness shows the distribution of user engagement frequency. Key concepts: - The interval field determines what counts as one period. With day interval over a 30-day range, the chart shows how many users performed the event on 1 day, 2 days, 3 days, etc., up to 30 days. - When math is omitted on a series, stickiness counts unique persons by default. - Multiple series can be included to compare stickiness of different events side by side. - Stickiness does NOT support breakdowns. Aggregation The default aggregation for stickiness is unique persons. You can change how users are identified using the math field on each series: - dau or omit math — count unique persons (default behavior; both resolve to person_id aggregation) - unique_group — count unique groups (requires math_group_type_index to be set to the group type index from the group mapping) - hogql — custom HogQL expression (requires math_hogql to be set to a valid HogQL aggregation expression, e.g. count(distinct properties.$session_id)) Stickiness criteria Use stickinessFilter.stickinessCriteria to filter which intervals count based on event frequency within each interval. This applies a HAVING clause to the inner aggregation. - operator — one of gte (greater than or equal), lte (less than or equal), exact (exactly equal) - value — the threshold count For example, to only count intervals where the user performed the event at least 3 times, set stickinessCriteria: { "operator": "gte", "value": 3 }. Cumulative mode Use stickinessFilter.computedAs to change how stickiness is computed: - non_cumulative (default) — each bar shows users active on exactly N intervals - cumulative — each bar shows users active on N or more intervals Time interval Specify the time interval using the interval field. Available intervals are: hour, day, week, month. Unless the user has specified otherwise, use day as the default interval. Use intervalCount to group multiple base intervals into a single period. For example, interval: "day" with intervalCount: 7 groups by 7-day periods. Defaults to 1. Compare Use compareFilter with compare: true to show the current and previous period side by side. Examples How many days per week do users use pageview? ``json { "kind": "StickinessQuery", "series": [{ "kind": "EventsNode", "event": "$pageview" }], "dateRange": { "date_from": "-30d" }, "interval": "day", "filterTestAccounts": true } ` Compare stickiness of two features `json { "kind": "StickinessQuery", "series": [ { "kind": "EventsNode", "event": "insight created" }, { "kind": "EventsNode", "event": "dashboard viewed" } ], "dateRange": { "date_from": "-30d" }, "interval": "day", "filterTestAccounts": true } ` Weekly stickiness for paid users, compared to previous period `json { "kind": "StickinessQuery", "series": [{ "kind": "EventsNode", "event": "$pageview" }], "dateRange": { "date_from": "-90d" }, "interval": "week", "properties": [{ "key": "paidCustomer", "operator": "exact", "type": "person", "value": ["true"] }], "compareFilter": { "compare": true }, "filterTestAccounts": true } ` Stickiness with criteria: only count days with 3+ events `json { "kind": "StickinessQuery", "series": [{ "kind": "EventsNode", "event": "$pageview" }], "dateRange": { "date_from": "-30d" }, "interval": "day", "filterTestAccounts": true, "stickinessFilter": { "stickinessCriteria": { "operator": "gte", "value": 3 } } } ` Cumulative stickiness: users active on N or more days `json { "kind": "StickinessQuery", "series": [{ "kind": "EventsNode", "event": "feature used" }], "dateRange": { "date_from": "-30d" }, "interval": "day", "filterTestAccounts": true, "stickinessFilter": { "computedAs": "cumulative" } } ` Organization-level stickiness for a feature `json { "kind": "StickinessQuery", "series": [ { "kind": "EventsNode", "event": "feature used", "math": "unique_group", "math_group_type_index": 0 } ], "dateRange": { "date_from": "-30d" }, "interval": "day", "filterTestAccounts": true, "stickinessFilter": { "display": "ActionsBar" } } ` Reminders - Ensure that any properties included are directly relevant to the context and objectives of the user's question. Avoid unnecessary or unrelated details. - Avoid overcomplicating the response with excessive property filters. Focus on the simplest solution. - Stickiness does NOT support breakdowns — do not include a breakdownFilter. - When using group aggregations (unique groups), always set math_group_type_index to the appropriate group type index from the group mapping. - The default interval is day` and the default math is unique persons — omit these unless the user asks for something different.query-trends
ChatGPTA/B*100 to calculate a ratio. - Filter and break down data using multiple properties. - Compare with the previous period and sample data. - Apply various aggregation types, like sum, average, etc., and chart types. Examples of use cases include: - How the product's most important metrics change over time. - Long-term patterns, or cycles in product's usage. - The usage of different features side-by-side. - How the properties of events vary using aggregation (sum, average, etc). - Users can also visualize the same data points in a variety of ways. CRITICAL: Be minimalist. Only include filters, breakdowns, and settings that are essential to answer the user's specific question. Default settings are usually sufficient unless the user explicitly requests customization. Data narrowing Property filters Use property filters to narrow results. Only include property filters when they are essential to directly answer the user's question. Avoid adding them if the question can be addressed without additional segmentation and always use the minimum set of property filters needed. IMPORTANT: Do not check if a property is set unless the user explicitly asks for it. When using a property filter, you should: - Prioritize properties directly related to the context or objective of the user's query. Avoid using properties for identification like IDs. Instead, prioritize filtering based on general properties like paidCustomer or icp_score. - Ensure that you find both the property group and name. Property groups should be one of the following: event, person, session, group. - After selecting a property, validate that the property value accurately reflects the intended criteria. - Find the suitable operator for type (e.g., contains, is set). - If the operator requires a value, use the read-data-schema tool to find the property values. - You set logical operators to combine multiple properties of a single series: AND or OR. Infer the property groups from the user's request. If your first guess doesn't yield any results, try to adjust the property group. Supported operators for the String type are: - equals (exact) - doesn't equal (is_not) - contains (icontains) - doesn't contain (not_icontains) - matches regex (regex) - doesn't match regex (not_regex) - is set - is not set Supported operators for the Numeric type are: - equals (exact) - doesn't equal (is_not) - greater than (gt) - less than (lt) - is set - is not set Supported operators for the DateTime type are: - equals (is_date_exact) - doesn't equal (is_not for existence check) - before (is_date_before) - after (is_date_after) - is set - is not set Supported operators for the Boolean type are: - equals - doesn't equal - is set - is not set All operators take a single value except for equals and doesn't equal which can take one or more values (as an array). Time period You should not filter events by time using property filters. Instead, use the dateRange field. If the question doesn't mention time, use last 30 days as a default time period. Trends guidelines Trends insights enable users to plot data from people, events, and properties however they want. They're useful for finding patterns in data, as well as monitoring product usage. Users can use multiple independent series in a single query to see trends. They can also use a formula to calculate a metric. Each series has its own set of property filters. Trends insights do not require breakdowns or filters by default. Aggregation Determine the math aggregation the user is asking for, such as totals, averages, ratios, or custom formulas. If not specified, choose a reasonable default based on the event type (e.g., total count). By default, the total count should be used. You can aggregate data by events, event's property values, groups, or users. If you're aggregating by users or groups, there's no need to check for their existence. Available math aggregation types for the event count are: - total count - average - minimum - maximum - median - 90th percentile - 95th percentile - 99th percentile - unique users - unique sessions - weekly active users - daily active users - first time for a user - unique groups (requires math_group_type_index to be set to the group type index from the group mapping) Available math aggregation types for event's property values are: - average - sum - minimum - maximum - median - 90th percentile - 95th percentile - 99th percentile Available math aggregation types counting number of events completed per user (intensity of usage) are: - average - minimum - maximum - median - 90th percentile - 95th percentile - 99th percentile Examples of using aggregation types: - unique users to find how many distinct users have logged the event per a day. - average by the $session_duration property to find out what was the average session duration of an event. - 99th percentile by users to find out what was the 99th percentile of the event count by users. Combining multiple events into a single series (GroupNode) Use a `GroupNode` when the user says "X OR Y" (or "any of these events") and wants one line / one number as the result. Different filters per event are fine — put them on the inner nodes. Use separate top-level series instead when the user wants the events compared side by side. Only OR is supported. Where things live: - On the group: math / math_property / math_property_type / math_multiplier / math_group_type_index / math_hogql, plus name. The engine reads aggregation from here. - On each inner node: event (or action id), properties, name — all respected normally; properties applies only to that node. Mirror the group's math* values on each inner node for UI round-trip, but they're ignored at execution time. Example — different filter per event "Pageviews on Safari OR pageleaves on Chrome, as one line." Each inner node carries its own properties; the group ORs them and aggregates as one series. ``json { "kind": "TrendsQuery", "series": [ { "kind": "GroupNode", "operator": "OR", "name": "Pageviews on Safari, Pageleaves on Chrome", "math": "total", "nodes": [ { "kind": "EventsNode", "event": "$pageview", "name": "Pageview", "math": "total", "properties": [{ "key": "$browser", "operator": "exact", "type": "event", "value": ["Safari"] }] }, { "kind": "EventsNode", "event": "$pageleave", "name": "Pageleave", "math": "total", "properties": [{ "key": "$browser", "operator": "exact", "type": "event", "value": ["Chrome"] }] } ] } ], "dateRange": { "date_from": "-30d" }, "interval": "day" } ` Math formulas If the math aggregation is more complex or not listed above, use custom formulas to perform mathematical operations like calculating percentages or metrics. If you use a formula, you should use the following syntax: A/B, where A and B are the names of the series. You can combine math aggregations and formulas. When using a formula, you should: - Identify and specify **all** events and actions needed to solve the formula. - Carefully review the list of available events and actions to find appropriate entities for each part of the formula. - Ensure that you find events and actions corresponding to both the numerator and denominator in ratio calculations. Examples of using math formulas: - If you want to calculate the percentage of users who have completed onboarding, you need to find and use events or actions similar to $identify and onboarding complete, so the formula will be A / B 100`, where `A` is `onboarding complete` (unique users) and `B` is `$identify` (unique users). - To calculate conversion rate: `A / B 100 where A is conversions and B is total events. - To calculate average value: A / B where A is sum of property and B is count. Time interval Specify the time interval (group by time) using the interval field. Available intervals are: hour, day, week, month. Unless the user has specified otherwise, use the following default interval: - If the time period is less than two days, use the hour interval. - If the time period is less than a month, use the day interval. - If the time period is less than three months, use the week interval. - Otherwise, use the month interval. Breakdowns Breakdowns are used to segment data by property values of maximum three properties. They divide all defined trends series into multiple subseries based on the values of the property. Include breakdowns **only when they are essential to directly answer the user's question**. You should not add breakdowns if the question can be addressed without additional segmentation. Always use the minimum set of breakdowns needed. When using breakdowns, you should: - **Identify the property group** and name for each breakdown. - **Provide the property name** for each breakdown. - **Validate that the property value accurately reflects the intended criteria**. Examples of using breakdowns: - page views trend by country: you need to find a property such as $geoip_country_code and set it as a breakdown. - number of users who have completed onboarding by an organization: you need to find a property such as organization name and set it as a breakdown. Examples How many users signed up? `json { "kind": "TrendsQuery", "series": [{ "kind": "EventsNode", "event": "user signed up", "math": "total" }], "dateRange": { "date_from": "-30d" }, "interval": "month", "trendsFilter": { "display": "BoldNumber" } } ` Page views by referring domain for the last month `json { "kind": "TrendsQuery", "series": [{ "kind": "EventsNode", "event": "$pageview", "math": "total" }], "dateRange": { "date_from": "-30d" }, "interval": "day", "breakdownFilter": { "breakdowns": [{ "property": "$referring_domain", "type": "event" }] } } ` DAU to MAU ratio for users from the US, compared to the previous period `json { "kind": "TrendsQuery", "series": [ { "kind": "EventsNode", "event": "$pageview", "math": "dau" }, { "kind": "EventsNode", "event": "$pageview", "math": "monthly_active" } ], "dateRange": { "date_from": "-7d" }, "interval": "day", "properties": { "type": "AND", "values": [ { "type": "AND", "values": [{ "key": "$geoip_country_name", "operator": "exact", "type": "event", "value": ["United States"] }] } ] }, "compareFilter": { "compare": true }, "trendsFilter": { "display": "ActionsLineGraph", "formula": "A/B", "aggregationAxisFormat": "percentage_scaled" } } ` Unique users and first-time users for "insight created" over the last 12 months `json { "kind": "TrendsQuery", "series": [ { "kind": "EventsNode", "event": "insight created", "math": "dau" }, { "kind": "EventsNode", "event": "insight created", "math": "first_time_for_user" } ], "dateRange": { "date_from": "-12m" }, "interval": "month", "filterTestAccounts": true, "trendsFilter": { "display": "ActionsLineGraph" } } ` P99, P95, and median of a "refreshAge" property on "viewed dashboard" events `json { "kind": "TrendsQuery", "series": [ { "kind": "EventsNode", "event": "viewed dashboard", "math": "p99", "math_property": "refreshAge" }, { "kind": "EventsNode", "event": "viewed dashboard", "math": "p95", "math_property": "refreshAge" }, { "kind": "EventsNode", "event": "viewed dashboard", "math": "median", "math_property": "refreshAge" } ], "dateRange": { "date_from": "yStart" }, "interval": "month", "filterTestAccounts": true, "trendsFilter": { "display": "ActionsLineGraph", "aggregationAxisFormat": "duration" } } ` Organizations that signed up from Google in the last 30 days (group aggregation) `json { "kind": "TrendsQuery", "series": [ { "kind": "EventsNode", "event": "user signed up", "math": "unique_group", "math_group_type_index": 0, "properties": [{ "key": "is_organization_first_user", "operator": "exact", "type": "person", "value": ["true"] }] } ], "dateRange": { "date_from": "-30d" }, "interval": "day", "properties": { "type": "AND", "values": [ { "type": "OR", "values": [{ "key": "$initial_utm_source", "operator": "exact", "type": "person", "value": ["google"] }] } ] }, "trendsFilter": { "display": "ActionsLineGraph" } } ` Reminders - Ensure that any properties included are directly relevant to the context and objectives of the user's question. Avoid unnecessary or unrelated details. - Avoid overcomplicating the response with excessive property filters. Focus on the simplest solution. - When using group aggregations (unique groups), always set math_group_type_index` to the appropriate group type index from the group mapping. - Visualization settings (display type, axis format, etc.) should only be specified when explicitly requested or when they significantly improve the answer.read-data-schema
ChatGPTread-data-warehouse-schema
ChatGPTrole-get
ChatGPTrole-members-list
ChatGPTroles-list
ChatGPTscheduled-changes-create
ChatGPTscheduled-changes-delete
ChatGPTscheduled-changes-get
ChatGPTscheduled-changes-list
ChatGPTscheduled-changes-update
ChatGPTsdk-doctor-get
ChatGPTsurvey-create
ChatGPTsurvey-delete
ChatGPTsurvey-get
ChatGPTsurvey-stats
ChatGPTsurvey-update
ChatGPTsurveys-get-all
ChatGPTsurveys-global-stats
ChatGPTswitch-organization
ChatGPTswitch-project
ChatGPTupdate-feature-flag
ChatGPTuser-get
ChatGPT@me as the UUID to fetch the authenticated user — non-staff callers may only access their own account.user-home-settings-get
ChatGPT/ — it can point at any PostHog destination (dashboard, insight, search, scene, etc.). Pass @me as the UUID.view-get
ChatGPTview-list
ChatGPTview-run-history
ChatGPTaction-create
Claudeaction-delete
Claudeaction-get
Claudeaction-update
Claudeactions-get-all
Claudeadd-insight-to-dashboard
Claudecreate-feature-flag
Claudedashboard-create
Claudedashboard-delete
Claudedashboard-get
Claudedashboard-reorder-tiles
Claudedashboard-update
Claudedashboards-get-all
Claudedelete-feature-flag
Claudedocs-search
Claudeentity-search
Claudeerror-details
Claudeevent-definition-update
Claudeevent-definitions-list
Claudeexecute-sql
Claudeexperiment-create
Claudeexperiment-delete
Claudeexperiment-get
Claudeexperiment-get-all
Claudeexperiment-results-get
Claudeexperiment-update
Claudefeature-flag-get-all
Claudefeature-flag-get-definition
Claudeget-llm-total-costs-for-project
Claudeinsight-create-from-query
Claudeinsight-delete
Claudeinsight-get
Claudeinsight-query
Claudeinsight-update
Claudeinsights-get-all
Claudelist-errors
Claudelogs-list-attribute-values
Claudelogs-list-attributes
Claudelogs-query
Claudeorganization-details-get
Claudeorganizations-get
Claudeprojects-get
Claudeproperties-list
Claudequery-generate-hogql-from-question
Claudequery-run
Clauderead-data-schema
Clauderead-data-warehouse-schema
Claudesurvey-create
Claudesurvey-delete
Claudesurvey-get
Claudesurvey-stats
Claudesurvey-update
Claudesurveys-get-all
Claudesurveys-global-stats
Claudeswitch-organization
Claudeswitch-project
Claudeupdate-feature-flag
ClaudeCapabilities
Example Prompts
Click any prompt to copy it.
Links
App Stats
178
Tools
3
Prompts
ChatGPT, Claude
Platforms
Category
Investigate IssuesWorks with
Data refreshed daily




